SSブログ

Tcl8.5 の apply コマンドで関数型プログラミング [Tcl]

私はこれまではまだ Tcl8.4 をメインにしていて 8.5 の機能をあまり触っていないことに気がついたので新機能を試してみることにしたい。

まずは新規追加になった apply コマンド。これは端的に言うと Tcl で関数型プログラミングへの道を開くものだ。

プログラミング言語のデザインでは「なんでも○○」という原則を作ることで仕様を簡潔にするということがしばしば行われている。○○に入るのは「オブジェクト」だったり「S式」だったりするかもしれない。Tcl ではそこに「文字列」が入る。Tcl という言語におけるファーストクラスは文字列のみであり(EIAS: Everything Is A String)、Tcl の魅力と奇怪さの多くはここから来ている。

さて、 Tcl ではプロシージャ(=関数)は通常の変数とは別の名前空間を持ち、また通常の変数への代入はできない。
例えば Lua や OCaml では funtion f (x) ... や let f x = ... は f = function(x) ... や let f = function x -> ... と同等であるのに対して、 Tcl の proc f {x} {...} は set コマンドでは置き換えられない。プロシージャを作ることとそれに名前をつける事は proc コマンドの中で結びついている。別の言い方をすると無名関数を作ることができない(これまではできなかった)。

勿論 EIAS 原則に基づけばプロシージャも文字列である。例えば次のように書いてプロシージャを定義するときは「x」という文字列と「puts "Hello, $x"」という文字列を引数に与えて「proc コマンド」を呼んでいるのだ。

% proc say_hello_to x {puts "Hello, $x"}

定義した後も info args と info body を使えば定義済みのプロシージャの中身を文字列として得ることができる。

% info args say_hello_to
x
% info body say_hello_to
puts "Hello, $x"

さて、文字列は受け渡しすることができるのだから高階関数のような技法もこれまでの仕組みでまったく不可能というわけではない。

% proc do_something_on_7 {a b} {
proc tmpf $a $b
tmpf 7
}
% do_something_on_7 x {expr $x*2}
14
% do_something_on_7 x {expr pow($x,2)}
49.0

このプロシージャは「渡された関数」を呼ぶために、引数で与えられた引数列 a と本体 b を使って内部で tmpf というプロシージャを定義している。
この方法の問題点はこの一時プロシージャの名前が既存の定義と衝突するかもしれないということだ。名前空間を分けるなどのトリックで衝突の危険を減らすことはできるかもしれない。しかしそれはその分だけ手間がかかるということだし、問題を綺麗さっぱり忘れてよくなるというわけではない。「名前の付けられたプロシージャしかプロシージャとして呼び出すことはできない」という制約がある限りは。

apply コマンドはこの問題を解決する。これを使うと上記の do_something_on_7 は以下のように書ける。

% proc do_something_on_7 {args} {
apply $args 7
}

これにより一時的な名前などは気にすることなくプロシージャを呼ぶことができるというわけだ。

今まで例えば tcllib の struct::list map なんかは関数渡しもどきの部分が制約の多いかなりいまいちな仕様になっていたのだけど 8.5 対応すれば自然な書き方ができるようになるだろう。

% proc map {l args} {
  set res [list]
  foreach item $l {
    lappend res [apply $args $item]
  }
  return $res
}
% map {1 2 3 4 5} x {expr $x*2}
2 4 6 8 10
%

nice!(1)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 1

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

DSL の10年Tcl 8.5 の lassign で多.. ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。