home(h) links(l) memo(m) profile(r)
memo(m) cgi(u) gauche

gauche関係

index

gaucheのインストール

2012/01/30現在、最新バージョンは0.9.2(2009/11/22、メジャーバージョンアップした)。 RPMを用いない場合は、こちらから最新のバイナリをダウンロードし、展開、./configuremakemake installという一般的な手順でOK。 詳細は以下の通り。

shell> wget http://jaist.dl.sourceforge.net/project/gauche/Gauche/Gauche-0.9.2.tgz ←ソースバイナリをダウンロード
shell> tar -zxvf Gauche-0.9.2.tgz ←ソースバイナリを解凍展開
shell> cd Gauche-0.9.2 ←解凍展開したディレクトリに移動
shell> ./configure --enable-threads=pthreads
                     ↑マルチスレッドサポートありの設定でMakefileを生成(Macではこのオプションが必須らしい)
shell> make ←コンパイル
shell> make install ←インストール(要管理者権限、必要に応じ前に"sudo "を付ける)
shell> gosh -V ←バージョン確認
Gauche scheme shell, version 0.9.2 [utf-8,pthreads], i386-apple-darwin10.8.0
  

RPMを使ってインストールする場合、RPMファイルを作ってRPMインストールする。 RPMファイルを作るには、バイナリtarballからspecファイル(RPM設計指示書)を取り出してビルドする方法と、RPMソースファイルを使う方法がある。多分後者の方が多少簡単。

【specファイルを取り出してビルドする場合】
shell> cd /usr/src/redhat/SOURCES/ ←ソース置き場にカレントディレクトリを移動
shell> wget http://prdownloads.sourceforge.net/gauche/Gauche-0.8.14.tgz ←ソースバイナリをダウンロード
shell> tar zxvf Gauche-0.8.14.tgz ←ソースバイナリを解凍展開
shell> cd Gauche-0.8.14 ←解凍展開したディレクトリに移動
shell> cp Gauche.spec ../../SPECS ←specファイルをspecファイル置き場にコピー
shell> cd ../../SPECS
shell> rpmbuild -bb Gauche.spec ←RPMパッケージを作成※1
shell> cd ../RPMS/i386
shell> rpm -Uvh Gauche*.rpm ←RPMパッケージをインストール
※"Gauche-common","Gauche-文字コード","Gauche-gdbm-文字コード" がインストールされる(通常、文字コードはutf8)。
shell> gosh -V ←バージョン確認
Gauche scheme interpreter, version 0.8.14 [utf-8,pthreads]

※1:Ver.0.9をRHEL5.3で処理すると、以下のエラー。
伸張ファイルの検査中: /usr/lib/rpm/check-files /var/tmp/rpm
エラー: インストール済み(ただし未伸張)ファイルが見つかりました:
   /usr/lib/libgauche.so.0.9.0


RPM ビルドエラー:
    ファイルが見つかりません: /var/tmp/rpm/usr/lib/libgauche.so.0.9
    インストール済み(ただし未伸張)ファイルが見つかりました:
   /usr/lib/libgauche.so.0.9.0

回避方法1:検査をスキップ
インストール済み(ただし未伸張)ファイルが見つかりました orz - HDEラボによると、SPECファイルに伸長ファイルの検査をスキップするよう記述すればいいらしい(SPECファイルの先頭に「%define __check_files %{nil}」と追記)。
回避方法2:specファイルを修正
このエラーは、パッケージに含めるべきファイル一覧を記している項目"%file"に書き漏らしているファイルがあることを示しているらしい。
つまり書き漏らしている(若しくは名前を間違っている)ファイルがないように記述を修正すればよい。

【RPMソースファイルを使う場合】(実動未検証)
shell> cd /usr/src/redhat/SRPMS/ ←ソース置き場にカレントディレクトリを移動
shell> wget http://prdownloads.sourceforge.net/gauche/Gauche-0.8.14-1.src.rpm ←RPMソースをダウンロード
shell> rpm -Uhv Gauche-0.8.14-1.src.rpm ←RPMソースをインストール
shell> cd ../SPECS
shell> rpmbuild -bb Gauche.spec ←RPMパッケージを作成
shell> cd ../RPMS/i386
shell> rpm -Uvh Gauche*.rpm ←RPMパッケージをインストール
shell> gosh -V ←バージョン確認
Gauche scheme interpreter, version 0.8.14 [utf-8,pthreads]
  

参考文献・サイト:

基本事項

実行中に式の評価値を表示する

#?= をS式の直前に追加する。

例:fold プロシージャの再定義中にて。

(define (fold proc init lis)
  (if (null? lis)
      init
      (fold proc (proc (car lis) init) #?=(cdr lis))))
    

参照:Kahuaプロジェクト『プログラミングGauche』オーラリージャパン(2008),ISBN 978-4-87311-348-7, p51

組み込み関数の定義を元に戻す

組み込み関数と同名でユーザ定義関数を定義してしまうと、関数の内容が上書きされる。それを組み込みのものに戻す手続きは以下の通り。

(define 関数名 (with-module gauche 関数名))
    

参照:Kahuaプロジェクト『プログラミングGauche』オーラリージャパン(2008),ISBN 978-4-87311-348-7, p49

コメント

以下のコメント形式がある。

行コメント(;
; から行末までを読み飛ばし。
ブロックコメント(#|,|#
#| から |# までを読み飛ばし。
S式コメント(#;
#; の後ろのS式ひとつを読み飛ばし。

対とリスト

2つの値をドットでつなぎ、括弧で囲んだものをドット対(dotted pair)と呼ぶ。ドット対は cons コマンドで作ることができる。cons は引数を2つとって、対を返すコマンド。

【例】
gosh> (cons 1 2)
(1 . 2)

対は入れ子構造にすることができる。

【例】
gosh> (cons 1 (cons 2 3))
(1 2 . 3)
gosh> '(1 . (2 . 3)) # 一番内側以外のドットとその後の対を囲む括弧は省略可能
(1 2 . 3)

後の要素が空の対であるものはリストと呼ぶ。

【例】
gosh> (cons 1 '())
(1)
gosh> (cons 1 (cons 2 '()))
(1 2)

スクリプトの実行

gaucheのスクリプトファイルを実行するには、下記の様にファイル名を引数としてgoshプログラムを実行すればよい。

shell> gosh gaucheスクリプトファイル名
    

ファイル名だけで直接実行するには、1行目に実行プログラムのフルパスを表記した上で、スクリプトファイルに実行権限を付与する。

【スクリプトソース例】
#!/usr/local/bin/gosh ←goshプログラムのフルパスを表記

(define (main args)
  (print "Hello, Gauche!")
)

shell> chmod +x gaucheスクリプトファイル名
※この実行権限を付与する処理を行うには管理者権限が必要。必要に応じてコマンドの前に"sudo "をつけるか、"su"コマンドで管理者ユーザになってから行う。
    

この実行可能スクリプトをWebサイトのCGIとして使うこともできる。

記号の意味

'(クォート)
以降をデータとして解釈する。
例1: (+ 1 1)2
例2:'(+ 1 1)(+ 1 1)
参照:kahuaプロジェクト著『プログラミングGauche』p42、オーラリー・ジャパン(2008)、ISBN 978-4-87311-348-7
`(準クォート quasiquote)
基本動作はクォートと同じ、但し以降に,(コンマ)があった場合はそれに続く式がプログラムとして解釈され、結果と置き換えられる。
例1:`(* 3 (+ 1 2))(* 3 (+ 1 2))
例2:`(* 3 ,(+ 1 2))(* 3 3)
参照:kahuaプロジェクト著『プログラミングGauche』p124、オーラリー・ジャパン(2008)、ISBN 978-4-87311-348-7
@(アットマーク)
@から始まるリストはSGMLなどの属性を表す。
例1: 参照:kahuaプロジェクト著『プログラミングGauche』p212、オーラリー・ジャパン(2008)、ISBN 978-4-87311-348-7

コマンドなど

文字列処理

エスケープ文字

ダブルクォートに囲まれた文字列内に記述できるエスケープ文字列

\" ダブルクォート文字("

文字列比較

文字列を比較するにはstring=?を使う6.12.6 文字列の比較 - Gauche ユーザリファレンスstring-ci=?だと大文字小文字を区別しない。

gosh> (string=? "aaa" "aaa")
#t
gosh> (string=? "aaa" "aab")
#f
gosh> (string=? "aaa" "AAA")
#f
gosh> (string-ci=? "aaa" "AAA")
#t

文字列の部分切り出し(substring)

【書式】
(substring 対象文字列 開始位置 終了位置)
      
開始位置
切り出し開始位置を数値で指定。最初の文字を0番目として数える。0 以上 対象文字列の長さ未満であること。
終了位置
切り出し終了位置を数値で指定。0 以上 対象文字列の長さ以下でかつ、開始位置以上の値であること。切り出し位置はこの値で指定した文字の直前まで(つまり、切り出し範囲は 開始位置〜終了位置−1)。
【例】
gosh> (substring "abcde12345" 4 8)
"e123"
      

文字列の結合

文字列を単につなげるにはstring-appendが使える。リストを構成する各値をつなげた文字列を作るにはstring-joinが使える。後者は、つなぐ各要素を間に挿入する文字列を指定できる。

【書式】
(string-append 文字列1 文字列2...)

【例】
gosh> (string-append "aaa" "bbb" "ccc")
"aaabbbccc"

【書式】
(string-join 文字列リスト 糊となる文字)

【例】
gosh> (string-join '("one" "two" "three") "-")
"one-two-three"

文字列パターン検索

rxmatchは文字列が正規表現パターンに一致するかどうかを調べる。

【書式】
(rxmatch 検索パターン 検索対象)
(検索パターン 検索対象)

【返り値】
パターンに一致→<regmatch≥オブジェクト
パターンに一致市内→#f
      
【例】
gosh> (rxmatch #/[1-3]{3}/ "123456")
#<<regmatch> 0x990a450>
以下の書式でも可
gosh> (#/[1-3]{3}/ "123456")

gosh> (rxmatch #/[1-3]{3}/ "456789")
#f
      

検索パターンの記述方法については正規表現も参照のこと。

rxmatchで得られたrxmatchオブジェクトから一致した部分を取り出すにはrxmatch-substringを用いる。サブマッチ番号を指定しなければパターン全体に一致した部分を、サブマッチ番号を指定すればサブパターンに一致した部分を返す。

またrxmatch->stringでもパターン全体に一致した部分を得ることができる。

【書式と返り値】
(rxmatch-substring rxmatchオブジェクト 検索対象 サブマッチ番号)
第1引数が正常なrxmatchオブジェクト→パターンに一致した(部分)文字列
not→#f

(rxmatch->string 検査パターン 検索対象)
パターンに一致→パターンに一致した(部分)文字列
not→#f
      
【例】
gosh> (rxmatch-substring (#/(www)(\..+)(\.jp)/ "www.hoge.jp"))
"www.hoge.jp"
以下のように書いても同じ
gosh> (rxmatch->string #/(www)(\..+)(\.jp)/ "www.hoge.jp")
"www.hoge.jp"

gosh> (rxmatch-substring (#/(www)(\..+)(\.jp)/ "www.hoge.jp") 1)
"www"
gosh> (rxmatch-substring (#/(www)(\..+)(\.jp)/ "www.hoge.jp") 2)
".hoge"
gosh> (rxmatch-substring (#/(www)(\..+)(\.jp)/ "www.hoge.jp") 3)
".jp"
      

文字列置換(string-replace、SRFI-13関数)

【書式】
(string-replace 文字列1 文字列2 文字列1開始位置 文字列1終了位置 文字列2開始位置 文字列2終了位置)

文字列1文字列1開始位置番目(最初が0番目)〜文字列1終了位置ー1番目の間を、文字列2文字列2開始位置番目〜文字列2終了位置−1番目の文字と置換する。
第6引数(文字列2終了位置)を省略すれば、文字列2文字列2開始位置番目〜最後までが、第5、6引数とも省略すれば文字列2全部と置換される。

【例1】"abcde"の2番目(c)〜3番目(d)を"12345"と置換
gosh> (string-replace "abcde" "12345" 2 4)
"ab12345e"

【例2】"abcde"の2番目(c)〜3番目(d)を"12345"の3番目(4)以降と置換
gosh> (string-replace "abcde" "12345" 2 4 3)
"ab45e"

【例3】"abcde"の2番目(c)〜4番目(d)を"12345"の1番目(2)〜2番目(3)と置換
gosh> (string-replace "abcde" "12345" 2 4 1 3)
"ab23e"
      

参考文献・サイト:

文字列パターン置換(regexp-replace)

【書式】最初にマッチした部分だけを置換
(regexp-replace 検索パターン 検索対象 置換パターン)
【書式】マッチしたもの全てを置換
(regexp-replace-all 検索パターン 検索対象 置換パターン)
      
【例】数字3文字の前後に"xx"をつける
gosh> (regexp-replace #/([0-9]{3})/ "abc012def34gh" "xx\\1xx")
"abcxx012xxdef34gh"
\\1 は検索パターンの中の1つ目のグループ(括弧で囲まれたパターン)を参照

【例】
行頭(改行の直後)に"author","著者","筆者"のいずれか、続いて全角か半角のコロン
→"著者:" に揃える
(regexp-replace #/\n(author|著者|筆者)[::]/ val "\n著者:")
      

正規表現も参照のこと。

文字列小文字化(string-downcase、SRFI-13関数)

【書式】
(string-downcase 置換対象文字列 開始位置 終了位置)
      
置換対象文字列(必須)
ダブルクォート(")で囲んで直接指定するか、文字列を値に持つ変数名を指定する。
開始位置(任意)
結果を返す開始位置を指定する。最初が0文字目。
終了位置(任意)
ここで指定した位置(最初の文字を0番目として数えた位置)以降は捨てる。 第3引数が省略されると、文字列の最後まで結果として返る。
【例】
gosh> (use srfi-13) ←最初にsrfi-13モジュールのロードを宣言
#<undef>
gosh> (string-downcase "ABcdEFGh")
"abcdefgh"
第1引数だけを指定した場合、全部が小文字となって返る。
gosh> (string-downcase "ABcdEFGh" 2)
"cdefgh"
第1、2引数だけを指定した場合、第2引数番目(2=3文字目)以降が小文字となって返る。
gosh> (string-downcase "ABcdEFGh" 2 6)
"cdef"
引数を3つ指定した場合、第2引数番目(2=3文字目)から第3引数番目ー1(5=4文字目)までが小文字となって返る。
      

参考文献・サイト:

単純出力(print)

      
gosh> (print "Hello World!")
Hello World!

整形して出力(format)

format 関数は指定した書式で文字列を返す。

【書式】
(format 出力ポート 書式指定 文字列)
出力ポート
#t → 現在のポート、#f → 返り値となる(既定値)。
書式指定
書式指定子を含む文字列。
文字列

参考文献・サイト:

参考文献・サイト:

比較

等価

関数 内容
eq?
型が同じで、メモリ上の同一場所にあるオブジェクトの場合 #t 文字や数値の判定結果は不定。文字や数値については値で比較したい場合は eqv? を用いる。
gosh> (eq? (cons 1 2) (cons 1 2))
#f 値は同じでも別のオブジェクトなのでfalse
gosh> (define p (cons 1 2))
p
gosh> (eq? p p)
#t こちらはpに定義された同一のオブジェクトを比較しているのでtrue
eqv? 数値は値が同じである場合、文字列は文字コードが同じである場合 #t、その他はeq?と同じ
equal?
複合データの各要素を比較し、全て一致すれば #t リストの中にリストがあった場合は再帰的に調べる。 真偽値、数値、文字、シンボルなどの単純型であれば原則として同じデータ型で、同じ値であれば #t
gosh> (equal? (cons 1 2) (cons 1 2))
#t eq? とは異なり、型と値が一致していれば #t
gosh> (define p (cons 1 2))
p
gosh> (equal? p p)
#t
gosh> (equal? 1 1.0)
#f 有効桁が異なるので #f
object-equal?

条件

if

【書式】
(if 条件式
    真の場合
    偽の場合)

まず条件式を評価し、#tが返れば真の場合を、そうでなければ偽の場合を評価しその結果を返す。

【例】
gosh> (if (number? 3) 'yes 'no)
yes
gosh> (if (number? #f) 'yes 'no)
no

参考文献・サイト

cond

【書式1】
(cond (条件式1 評価式1-1 評価式1-2)
      ...
      (else 評価式n-1 評価式n-2))

最初の節から順に条件式を評価し、返り値が#tでなければ次の条件式の評価に移る。返り値が#tであればその節の評価式を順に評価し、最後の評価式の返り値が返り値となる。

【例】
gosh> (cond ((> 3 2) 'greater)
> ((< 3 2) 'less)
> (else 'equal))
greater

参考文献・サイト

case

and

and は引数に指定された評価式を順に評価していき、偽(#f)の返り値を得た時点で偽(#f)を返して処理を終了する(残りの式は評価されない)。全ての式が真(#t)を返した場合は最後の式の返り値を返す。式の指定がない場合は無条件に#tを返す。

【書式】
(and 評価式...)

【例】
gosh> (and (= 2 2) (> 2 1))
#t ※評価式の評価結果は2つとも#t
gosh> (and (= 2 2) (< 2 1))
#f ※2つ目の評価結果が#fなのでそれを返して評価終了
gosh> (and (= 2 2) (< 2 1) (> 2 1))
#f ※#fと評価された2つ目で評価終了(3つ目は評価されない)
gosh> (and 1 2 'c '(f g))
(f g) ※全て#fではない値なので#tと評価され、最後の式の評価結果が返る
gosh> (and)
#t ※引数なしは常に#t

参考文献・サイト

定義

定義(define)

defineを使って手続き(関数)や変数を定義することができる。

【書式1】変数定義
(define 変数名 評価式)

【例1】
gosh> (define x (+ 3 1))
x
gosh> (print x)
4
#<undef>

【書式2】関数定義
(define (リスト) 評価式)
リストのcar(第1要素)は関数名、リストのcdr(第2要素以降)は引数リスト。
ドットリストの場合、引数の数は可変(記述した要素数-1以上)。

【例2】
gosh> (define y (lambda (a) (* a 2)))
      (define (y a) (* a 2)) としても同じ
y
gosh> (y 8)
16
gosh> (define (func a b . c) (print "a=" a _", b=
" b ", c=" c))
func
gosh> (func 1 2)
a=1, b=2, c=()
#<undef>
gosh> (func 1 2 3)
a=1, b=2, c=(3)
#<undef>
gosh> (func 1 2 3 4)
a=1, b=2, c=(3 4)
#<undef>

定義内変数定義(let)

define定義内など限られた範囲でのみ有効な変数定義を行う。letはletが開始される前の状態で評価を行い、let* は記述順に評価していく[3]

【書式】
(let ((変数名 変数値)
      ...
     )
       処理内容
)
(let* ((変数名 変数値)
      ...
      )
       処理内容
)

【例】
gosh> (define x 'hoge)
x
gosh> (let ((x 'foo) (y x)) (cons x y))
(foo . hoge)
yの定義 (y x) では、1番目のxの定義と関係なく、let開始時点でのxの定義 hoge が用いられる
gosh> (let* ((x 'foo) (y x)) (cons x y))
(foo . foo)
yの定義 (y x) では、1番目のxの定義の結果に従った値 foo が用いられる

モジュール処理

define-module

モジュール名の定義。

(define-module module-name body)
module-name:モジュール名
body:エクスポートする名前の選択、利用するモジュールのインポート、モジュールの継承、について記す。
      (define-module sample1
      (export addx))
      

モジュール名前は"sample1"、エクスポートする名前は "addx"。

provide

require

import

外部モジュールを利用する。

(import sample1)
sample1 という名前のモジュールを読み込む

定義類を他から呼び出せるようにする

exportでは、カレントモジュール内で定義されている定義類を他から呼び出した時、使えるようにする定義を列挙する。カレントモジュールをimportした別のモジュール内で列挙された定義類が使えるようになる。カレントモジュール内で定義されているもの全てを利用できるようにするにはexport-allを用いると便利。

【書式】
(export 定義名...)
(export-all)
      

参考文献・サイト

html関係

text.html-lite

文書型宣言

HTML ドキュメントの文書型宣言を返します。 type は、以下のいずれかを指定します (デフォルトは:html-4.01-strict です)。

【例】XHTML 1.1 の宣言
(html-doctype :type :xhtml-1.1)
↓
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
      

www.cgi モジュール関係

【書式】www.cgiモジュールを利用する
(use www.cgi)
	

cgiパラメータを取得するにはcgi-parse-parametersを用いる。

cgi-parse-parameters
cgiプログラムに渡されたクエリ文字列を受け取り、パラメータのリストにして返す。 パラメータに値がない場合は結果のパラメータとして#tが置かれる。
例:
	      (cgi-parse-parameter
	      :query-string "foo=123&bar=%22%3f%3f%22&bar=zz&buzz")
	      ⇒ (("foo" "123") ("bar "\"??\"" "zz") ("buzz" #t))
	    
cgi-get-parameter name params
nameで指定した名前を持つパラメータの値を、paramsクエリ文字列から取り出す。

参考文献・サイト:

http関係

下記各関数を利用するには rfc.http モジュールをロードする((use rfc.http) をスクリプト内に記述する)必要がある。

サーバにhttpリクエストを送って応答を得る(http-get)

【書式】
(http-get サーバ:サーバ側ポート番号 リクエストURI キーワード引数)
【必要モジュール】
rfc.http
【返り値】
httpサーバの応答内容。
サーバ
リクエスト送信先サーバを指定する。:サーバ側ポート番号 を追記することでアクセス先ポート番号を指定することができる。指定が無い場合の既定値は80。
リクエストURI

文字列で指定した場合はその文字列がリクエストURI(通常はHTTP URLのパス部分)であると解釈されて処理される。文字列はそのままサーバに渡されるため、必要な文字コード変換やurlエンコーディングを呼び出し側であらかじめ行っておく必要がある。

文字列がリストの場合、下記形式で指定する必要がある。

(パス (キー ) ...)
パス
リクエストURIのパスコンポーネント(CGIのファイル名など)までを指定する文字列
(キー 値)
GETリクエストのキーおよびそのキーに対応する値の2値を要素とするリストを1つ以上指定する。リストは何組指定してもよい。ここで指定した内容は自動的にurlエンコーディングが行われた上で、パスに追記される。

例えば下記2つのリクエストは同じ効果を持つ。

(http-get "example.com" "/search?q=foo%20bar&n=20")

(http-get "example.com" '("/search" (q "foo bar") (n 20)))
返り値
下記3つの内容が改行区切りで返る。
httpステータスコード
RFC2616で定義されているステータスコード。成功なら200、Not foundなら404など。
httpヘッダ
(ヘッダ名 ) の2値を要素とするリスト、を要素とするリスト。ヘッダ名は「content-type」など。値はそのヘッダ名に対応する値(例:「text/html; charset=iso-8859-1」)。
httpメッセージ本体
空の場合は #f。
キーワード引数
:キー の形で指定する。httpヘッダフィールドに指定できる値(accept-languageuser-agentなど)の場合、指定した内容がリクエストに追加される。その他下記指定が可能。下記項目については、http-get実行時に解釈されてリクエストヘッダには追加されない。
request-encoding
proxy
no-redirect
secure
sink, flusher
【例】
gosh> (use rfc.http)
#<undef>
gosh> (http-get "localhost" "/index.html")
"200"
(("date" "Mon, 30 Jan 2012 04:41:42 GMT") ("server" "Apache/2.2.21 (Unix) DAV/2") ("last-modified" "Mon, 30 Jan 2012 04:19:47 GMT") ("etag" "\"c6076d-2c-4b7b728211ec0\"") ("accept-ranges" "bytes") ("content-length" "44") ("content-type" "text/html"))
"<html><body><h1>It works!</h1></body></html>"
gosh> 

参考文献・サイト:

入出力関係

ファイルの開閉

他の手続き(関数)で利用するための入出力ポートを得るにはopen-input-file(入力用)やopen-output-file(出力用)を用いる。直接得た入出力ポートを手続きに渡すにはcall-with-input-file/call-with-output-fileを用いることができる。

【書式→返り値】
(open-input-file ファイル名 キーワード引数) → 入力ポート
(open-output-file ファイル名 キーワード引数) → 出力ポート
(call-with-input-file ファイル名 手続き キーワード引数) → 手続きの返り値
(call-with-output-file ファイル名 手続き キーワード引数) → 手続きの返り値
【例】
gosh> (define h (open-input-file "/home/user/1a14.xml"))
h
gosh> h
#<iport /Users/kudoutakahiro/downloads/1a14.xml 0x1005da690>

参考文献・サイト

システム関係

環境変数の値を取得(sys-getenv)

【書式→返り値】
(sys-getenv 環境変数名)
→環境変数名の値

環境変数の値を設定(sys-putenv)

【書式】
(sys-putenv 環境変数名 )

ファイルシステム関係

関数 説明
sys-basename パス名 パス名のファイル名部分を取り出す。末尾の文字がスラッシュ(/)であった場合、そのスラッシュは無視される。パス名で指定したファイルが実在するかどうかのチェックは行われない。
gosh> (sys-basename "/foo/bar/hoge.txt")
"hoge.txt"
gosh> (sys-basename "/foo/bar/")
"bar"
sys-dirname パス名 パス名のディレクトリ名部分を取り出す。末尾の文字がスラッシュ(/)であった場合、そのスラッシュは無視される。パス名で指定したファイルが実在するかどうかのチェックは行われない。
gosh> (sys-basename "/foo/bar/hoge.txt")
"/foo/bar"
gosh> (sys-basename "/foo/bar/")
"/foo"

参考文献・サイト

サブプロセス(gauche.process関数)

シェルコマンドなどを実行する。利用するにはgauche.processモジュールのロード((use gauche.process)の実行)が必要。

コマンド実行(run-process)

【書式】
(run-process コマンド・引数のリスト オプション)
コマンド・引数のリスト
car がコマンド名、cdr が引数リストとなるリスト。
:wait #t | #f
#t ならプロセス終了まで待つ、#f なら待たず値を返す。指定がない場合の既定値は#f。
【例1】引数がない場合("ls"コマンドを実行)
gosh> (run-process '(ls))
#<process 12345 "ls" active>
gosh> hoge.txt   fuga.gif   foo.log
Ctrl + c を入力→制御が戻る
*** UNHANDLED-SIGNAL-ERROR: unhandled signal 2 (SIGINT)
Stack Trace:
_______________________________________
gosh> 

【例2】引数がある場合("ls -l"コマンドを実行)
(run-process '(ls -l))

【例3】サブプロセス終了を待ち、終われば制御が戻る
gosh> (run-process '(ls) :wait #t)
hoge.txt   fuga.gif   foo.log
#<process 12345 "ls" active>
gosh> 

【例4】shellコマンド「date」実行結果を格納する変数定義
gosh> (define dateval
(let* ((process (run-process '(date) :output 'stdout :wait #t))
(val (read-line (process-output process 'stdout))))
val))
dateval
gosh> dateval
"2015年 8月 5日 水曜日 16時58分14秒 JST"
      

コマンド・引数のリスト

第1要素(car)がコマンド名、第2要素以降(cdr)が引数として解釈される。

コマンド名にスラッシュが含まれていた場合、パスも含めて指定したものと解釈される。そうでなければ、PATH環境変数にあるディレクトリから指定コマンドを探す。

各要素はクォート記号で囲まなくても自動的にx->stringが適用され文字列に変換される。但し -i はクォートしないと虚数単位として解釈されてしまうため、"-i"のようにクォートする必要がある。

返り値

<process>オブジェクト

オプション

:input ファイル名
:output ファイル名
:error ファイル名
サブプロセスの標準入出力先(:inputは入力、:outputは出力、:errorはエラー出力)を設定する。ファイル名:pipeを指定した場合、入出力先はパイプに接続され、別のプロセスとやりとりされる。その他の文字列を指定すると、その指定した文字列の名前を持つファイルが入出力先に設定される。
:wait フラグ
フラグが真(#t)の場合、run-processはサブプロセスが終了するまで待つ。偽(#f)の場合、サブプロセスが終了するのを待たずにすぐ制御が戻る。この場合、サブプロセスが終了したかどうかを確認するにはprocess-waitコマンドを用いる。

サブプロセスが終了したかを調べる(process-wait)

【書式】
(process-wait プロセスオブジェクト)
      

返り値

終了していれば真(#t)、終了していなければ偽(#f)を返す。

参考文献・サイト

cgi処理関係

www.cgi モジュールは、cgiスクリプトを作成する上で便利な関数群が使えるようになる。

導入方法

モジュールをロードするには以下の1行をスクリプト中に記述する。

(use www.cgi)

環境変数の上書き(cgi-metavariables)

cgi-metavariablesは、ユーザエージェント情報、GET引数などの環境変数を書き換える。

【書式】
(cgi-metavariables '(("キー1" "値1") ...))

【例】REQUEST_METHODと QUERY_STRINGのメタ変数をmy-cgi-procedureの実行中に上書きする
(parameterize ((cgi-metavariables '(("REQUEST_METHOD" "GET")
                                    ("QUERY_STRING" "x=foo"))))
  (my-cgi-procedure))

環境変数値の取得(cgi-get-metavariable)

cgi-get-metavariableは、まずcgi-metavariablesを探し、なければsys-getenvを呼び出して指定したキーに対応する環境変数の値を返す。

【書式】
(cgi-get-metavariable "キー")

【例】USER_AGENTキーに対応する値を返す
(cgi-get-metavariable "USER_AGENT")

CGIパラメータの取得(cgi-parse-parameters)

cgi-parse-parameters 関数はGETやPOST、そしてcookieで送られてきた値を連想配列に変換して返す。キーだけがあって値が設定されていない場合は、値として #t が設定される。

【書式】
(cgi-parse-parameters :query-string "クエリ文字列"
                      :merge-cookies #t | #f
                      :part-handlers 
)
【返り値】パラメータの連想リスト
query-string
指定すると、実際送られてきたパラメータではなく、ここで指定したクエリ文字列を連想配列に変換したリストが返る。値の指定はGET引数指定を行う場合と同じ(キー=&...)。
merge-cookies
指定すると、変数HTTP_COOKIEからcookieの値が読み込まれ、連想配列に変換して結果に追加される。
part-handlers
【例】
(cgi-parse-parameters 
  :query-string "foo=123&bar=%22%3f%3f%22&bar=zz&buzz")
↓
(("foo" "123") ("bar "\"??\"" "zz") ("buzz" #t))

特定キーのCGIパラメータ取得(cgi-get-parameters)

cgi-get-parameter 関数は、cgi-parse-parametersが返す連想配列から指定したキーの値を取り出して返す。

【書式】
(cgi-get-parameter 取り出し対象キー値
                   パラメータ連想配列
                    :default 既定値
                    :list #t | #f
                    :convert 関数
)
【返り値】
スカラー値(:list #t の場合)、リスト(:list #t でない場合)
取り出し対象キー値がなかった場合、
:default 既定値の指定があればその指定値、
そうでなければ #f(偽、:list #t の場合)、()(空リスト、:list #t でない場合)。

正規表現

gauche の正規表現は perl5 の正規表現が使えるとのこと。#//で挟んでパターンを表記する。最後のスラッシュの後にiを付けると大文字小文字を区別しない。

【書式1】大文字小文字を区別する
#/正規表現/

【書式2】大文字小文字を区別しない
#/正規表現/i
  
表記 説明
^正規表現 行頭
¥ 直後に来る、正規表現で意味を持つ文字を通常の文字として扱う。
\;\"\#
. 改行以外の任意の1文字。
$ 行末(行末に改行がある場合は改行の直前の文字)。
| 選択
( ) グループ化
[ ] 文字クラス。[ ]内に含まれる文字のいずれか1文字。
* 0回以上繰り返し(最長パターン)。
+ 1回以上繰り返し(最長パターン)。
? 0回か1回(最長パターン)。
{n} n回繰り返し(最長パターン)。
{n,} n回以上繰り返し(最長パターン)。
{n,m} n回以上m回以下繰り返し(最長パターン、但しn<=m)。
*?, *+, ??, {n,}?, {n,m}? それぞれ1文字目が示す正規表現の最短パターン。
\n バックリファレンス。n番目のグループを参照。実際置換パターンとして参照する際はバックスラッシュをエスケープして\\nと記述する必要あり。また0番はヒットした文字列全体。
\t タブ
\n 改行
\w 英数字とアンダースコア(単語文字)
\W 英数字とアンダースコア(単語文字)以外
\s 空白文字
\S 非空白文字
\d 数字
\D 非数字
\b 単語境界の空文字列
\B 単語境界の空文字列以外

  

参考文献・サイト:

データベース関係

DBM系

準備

データベースを使うには、必要なモジュールをロードする必要がある。

【書式】
(use dbm) ;dbmの抽象インターフェースモジュールを読み込む
(use dbm.gdbm) ;gdbmの具体インターフェースモジュールを読み込む
      

データベースシステム名にはfsdbm, gdbm, ndbm, odbm, qdbmなどを指定。qdbmについてはこちら参照。 なお、具体モジュールでは抽象モジュールを拡張して作られているため、具体モジュールをロードする時は改めて抽象モジュールをロードする必要はない。

【例】qdbmを使う
(use dbm.qdbm)
      

データベースの開閉

データベースを開くにはdbm-openメソッドを用いる。成功すれば<dbm>クラス型のインスタンスを、失敗すればエラーを返す。

【書式】
(dbm-open データベース具体クラス :path データベースファイル名 :rw-mode :モード)
      
データベースシステム名
fsdbm, gdbm, ndbm, odbm, qdbmなど、あらかじめ前項の準備でロードしたもの。
データベースファイル名
データベースのデータを格納している(する)ファイルの名前。パス指定なし、または相対パスでファイル名を指定した場合、パスの起点は実行するGaucheスクリプトがあるディレクトリ。対話モードの場合はカレントディレクトリ。
読み書きモード
モード 読み 書き ファイル既存 ファイル未存
read × エラー
write 新規作成
create 上書き新規作成 新規作成

:path の後にはデータファイル名を、:rw-mode :の後には読み書きモードを"read"(読み出し専用、なければエラー),"write"(読み書き可能、なければ新規作成),"create"(読み書き可能、常に新規作成)のうちから1つを選んで指定する。

【例】
gosh> (dbm-open <gdbm>
                :path "test.db"
                :rw-mode :create)
#<<qdbm> 0x9d99480>
      

なお、インスタンスに名前をつけておかないと扱いにくい(というかどういう名前で呼び出すのか分からない)ので、実際には以下の例のように名前を付けておく(グローバル変数として定義しておく、グローバル変数名の前後にアスタリスクを付けるのはScheme/Lispの慣習で必須事項ではない)。

gosh> (define *db*
       (dbm-open <gdbm>
                 :path "test.db"
                 :rw-mode :create))
*db*
      

データベースを閉じるにはdbm-closeメソッドを用いる。成功すれば#tが、失敗すればエラーが返る。データベースを閉じるとその後のアクセス操作はエラーとなる。

gosh> (dbm-close *db*)
#t
      

データベースが閉じているかどうかを調べるにはdbm-closed?メソッドを用いる。データベースが閉じていると#tを返す。

gosh> (dbm-closed? *db*)
#t
      

アクセス

値をデータベースに保存するにはdbm-put!メソッドを、値をデータベースから取り出すにはdbm-get使う。

【書式】
(dbm-put! データベースインスタンス名 キー )
(dbm-get データベースインスタンス名 キー 既定値)
      

dbm-getで、キーが見つからなかった場合、既定値が設定されていればその既定値を、設定されていなければエラーを返す。

【例】
gosh> (define *db*
       (dbm-open <gdbm>
                 :path "test.db"
                 :rw-mode :create))
*db*
gosh> (dbm-put! *db* "hoge" "foofoo")
#<undef>
gosh> (dbm-get *db* "hoge")
"foofoo"
      

キーが存在するかを調べるにはdbm-exists?メソッドを使う。存在すれば#tを、存在しなければ#fを返す。

【書式】
(dbm-exists? データベースインスタンス名 キー)

【例】
gosh> (dbm-exists? *db* "hoge")
#t
gosh> (dbm-exists? *db* "huga")
#f
      

キーとキーに対応する値の組をデータベースから削除するにはdbm-delete!メソッドを使う。

【書式】
(dbm-delete! データベースインスタンス名 キー)
      

キーが見つからなかった場合はエラーになる。

【例】
gosh> (dbm-exists? *db* "hoge")
#<undef>
gosh> (dbm-exists? *db* "huga")
*** ERROR: dbm-delete!: deleteting key "huga" from #<<qdbm> 0x8433730> failed
Stack Trace:
_______________________________________
      

アクセスの繰り返し

データベースのキーと値の組それぞれに対して処理を行い戻り値は必要ない場合にはdbm-for-eachメソッドを、 各キーと値に対する戻り値をリストで受け取る場合はdbm-mapdbm-foldでは初期値に処理を適用していった最終戻り値が返る。

【書式】
(dbm-for-each データベースインスタンス名 手続き)
      

手続きにはキーと値が渡されるので、手続きは2つの引数を受け付けるものである必要がある。手続きの返り値は捨てられる。

【例1】値を2倍にする
(use dbm.gdbm)
(define *db*
  (dbm-open <gdbm>
            :path "test.db"
            :rw-mode :create))
(dbm-put! *db* "hoge" "1")
(dbm-put! *db* "huga" "2")
(define double
  (lambda (key val)
    (let
      ((oldval (string->(dbm-get *db* key))))
        (dbm-put! *db* key
                      (number->string (* oldval 2))))))
(dbm-for-each *db* double)

【例2】データベースを開き、キーとそれ対応する値を全て取得して表示
(use dbm)
(use dbm.qdbm)

(define *db* (dbm-open <qdbm> :path "data.dbm" :rw-mode :read))
(dbm-for-each *db*
              (lambda (key val) (print key val)))
(dbm-close *db*)
※ちなみにprint文は返り値がない(#<undef>)のでそもそも捨てるものはない。

【例3】"data.dbm"に格納されたqdbmデータベースを全て読み込み、小文字に変換して保存
(use dbm)
(use dbm.qdbm)
(use srfi-13) string-downcase を使うのに必要

(define *db* (dbm-open <qdbm> :path "data.dbm" :rw-mode :write))
(dbm-for-each *db* 
  (lambda (key val)
    (dbm-put! *db* key (string-downcase val))))
(dbm-close *db*)
      

dbm-foldでは3つの引数をとる手続きを指定する。

【書式】
(dbm-fold データベースハンドル 手続き 初期値)
      
【例】データベース中の全整数を加算
(use dbm)
(use dbm.qdbm)

(define *db* (dbm-open <qdbm> :path "data.dbm" :rw-mode :read))
(dbm-fold *db*
          (lambda (key val r)
                  (if (integer? val)
                      (+ val r)
                      r))
          0)
(dbm-close *db*)
      

GaucheでMySQLを使う

Gauche用MySQLドライバをインストール。

shell> wget http://www.kahua.org/download/dbi/Gauche-dbd-mysql-0.2.2.tgz
shell> gauche-package install -S root Gauche-dbd-mysql-0.2.2.tgz
    
【例】
#!/usr/bin/gosh ←実際のgoshプログラムの場所を記述
(use dbi)
(use gauche.parameter)

(define *db-name* "dbi:mysql:db=データベース名;host=MySQLサーバのホスト名")
(define *db-user* "MySQLユーザ名")
(define *db-pwd* "MySQLユーザパスワード")
(define db (make-parameter #f))
(define-syntax with-db
  (syntax-rules ()
    ((with-db (db dsn usr pwd) . body)
     (parameterize
      ((db (dbi-connect dsn :username usr :password pwd)))
      (guard
       (e (else (dbi-close (db)) (raise e)))
       (begin0
	(begin . body)
	(dbi-close (db))))))))
(define (main args)
  (with-db (db *db-name* *db-user* *db-pwd*)
	   (let* ((result (dbi-do (db) "クエリ文"))
		  (getter (relation-accessor result))
		  (rlist (map
			   (lambda (row)
			      (list (getter row "カラム名1")
				    (getter row "カラム名2")
                                    ...
				    (getter row "カラム名n")))
			   result)))
	   (print rlist)
	   ))
0)
    

参考文献・サイト:

コマンドリスト

c

d

p

r

s

開発

GIT

現在、Gaucheの開発はgit(ギット)というシステムを用いて開発管理が行われている。MacOSXの場合、git-osx-installer - OSX Installer for Git - Google Project Hostingからインストーラディスクイメージをダウンロードできる。

Macの場合、/usr/local/git/ 配下にgitがインストールされるようなので、gitコマンドが使えるよう環境変数にパスを追加しておく。

[user@mypc ~]$ export PATH=${PATH}:/usr/local/git/bin # 現在の環境変数を変更
$ printf "\nexport PATH=${PATH}:/usr/local/git/bin" >>~/.bashrc # 今後の環境変数を変更
[user@mypc ~]$ which git
/usr/local/git/bin/git

git用サブディレクトリを作ってそこで作業。

[user@mypc ~]$ mkdir ~/gitproject
[user@mypc ~]$ cd ~/gitproject

まず個人情報設定。

[user@mypc gitproject]$ git config --global user.name "Kuidaore Taro"
[user@mypc gitproject]$ git config --global user.email Kuidaore.Taro@example.org

初期化。カレントディレクトリに.gitというディレクトリが作成され、その中にgitリポジトリのスケルトン(ひな形)が作成される。

[user@mypc gitproject]$ git init
[user@mypc gitproject]$ ls -A
.git
[user@mypc gitproject]$ ls .git
HEAD         config       hooks/       objects/
branches/    description  info/        refs/

git cloneコマンドによりGaucheリポジトリを取得(ダウンロード)。カレントディレクトリにGaucheというディレクトリが作成され、この中にダウンロードされる。大文字小文字の区別なしで同名のディレクトリ(gaucheなど)が既に存在するとコマンド実行に失敗する(「fatal: destination path 'Gauche' already exists and is not an empty directory.」というエラーを出力してコマンドは終了する)。

[user@mypc gitproject]$ git clone git://gauche.git.sourceforge.net/gitroot/gauche/Gauche
Cloning into 'Gauche'...
remote: Counting objects: 47404, done.
remote: Compressing objects: 100% (12670/12670), done.
remote: Total 47404 (delta 37688), reused 43390 (delta 34314)
Receiving objects: 100% (47404/47404), 15.68 MiB | 2.11 MiB/s, done.
Resolving deltas: 100% (37688/37688), done.

上記URLはread-onlyのもの。書き込みもできるようにする手順は以下の通りと思われる。

  1. SourceForgeのアカウントがなければSourceForgeユーザ登録ページで作成する
  2. SourceForge.net: Gauche: Project Member Listで管理者に開発参加申請が必要なよう。
  3. 参加者になれば ssh://SourceForgeユーザ名@gauche.git.sourceforge.net/gitroot/gauche/gaucheで読み書き可能?