Tclでλ計算ができると聞いたので試してみました。
しかし、まずTclを思い出す作業から始めないといけないのでスタートラインが遠すぎる…。
注意:
Tclのapplyに関しての情報は、
- http://wiki.tcl.tk/4884
- http://www.tcl.tk/cgi-bin/tct/tip/194
- http://www.tcl.tk/man/tcl8.5/TclCmd/apply.htm
等を読む事を*強く*お勧めします。この日記はチラシの裏以下の価値しかありません。
ここから思い出しメモ。
- Tclでは全てが文字列である。
- Tclはスクリプト言語なので一行づつ処理される。
- プログラムは、与えられた文字列中を半角スペースで区切った最初の文字列をコマンド名として、残りの文字列を引数として実行される。
- {}内はひとまとまりの文字列として扱われる。
- []内は計算結果に置換される。
- 変数は頭に'$'を付けて区別。*1
…まぁ文法はこんな感じだったはず。
hoge fuga
ならhogeを、fugaを引数として呼び出す。
expr 1+1
exprは引数を数式と見なして計算する。この場合の結果は「2」。
if {$n-2==0} {hoge} else {fuga}
ifすら構文には含まれない。コマンドの一つ。
最初の引数({$n==0})をexprで計算した結果が、
proc hoge {fuga} { expr {$fuga*$fuga} } hoge 42
関数はこんな感じ。procはやはり単なるコマンド。
hogeは1-arityの関数で、引数^2を計算する。途中に改行が含まれるが、{}内なので問題なし。*3
ここから本題。
さて、Tcl 8.5でapplyが追加されました。
引数に取った文字列を解釈して実行してくれる、素晴らしい関数です。
- 一つ目の引数には処理する内容を書きます。{arg_list body}の形です。
- arg_listは引数のリストです。
- bodyは実際の処理です。arg_listで宣言した引数を使う事が出来ます。
- 二つ目以降の引数には実引数を書きます。arg_listとマッチするように与える必要があります。
つまり、procの関数名より後ろをまとめて書けばOKです。
例えば、
apply {x {expr $x*$x}} 42
は42^2を計算します。
ここで、{x {expr $x*$x}}は(というかTclプログラムすべては)単なる文字列ですので、変数に格納できます。
set sqr {x {expr $x*$x}}
$sqrを引数として、applyを呼び出す事ができます。
apply $sqr 42
は1764を返します。
以上でapplyの説明終了。
本題の本題
という事は、似非高階関数が使えるという事になります。
set sqr {x {expr $x*$x}} proc apply_42 {f} { apply $f 42 } apply_42 $sqr
proc get_sqr {} { list x {expr $x*$x} } apply [get_sqr] 42
が、ここで問題発生。
set plus {{x} {list y {expr $x+$y}}} apply [apply $plus 1] 2
"3"を期待したのですが、"can't read "x": no such variable"とエラーが返ってきてしまいました。
試しに
set p [apply $plus 1]
するとpは「y {expr $x+$y}」…
…
…あ、そうか。
「{}」内は文字列だから変数表記も置換されないのでした。
これを回避する方法があったような気もする*4のですが、思い出せない上にそろそろ時間切れ。*5
誰か日本語でちゃんとした記事書いてくれないかなぁ、と他力本願しておきます。