apply
Tclでlambda式を使う手段として、Tcl 8.6でapplyコマンドが標準装備されました。
実は私はlambda式のメリットを理解できていません。このため、普段はapplyコマンドを使うことがありません。
だけどもしかしたら知ってしまえば使わずにはいられないくらい便利なものかも知れない・・・とも思うわけで、勉強がてらapplyコマンドを試してみました。
基本的な使い方
applyコマンドのヘルプによれば書式は以下の通りです。
apply func ? arg1 arg2 ... ?
で、最も簡単な例だと
puts [apply {{a b} {expr $a + $b}} 1 2]
を評価すると「3」が表示される、と。
まぁ、機能は何となく分かります。しかし問題は「で?」という感想しか出せないところ。
ヘルプで紹介されている便利な使い方
ヘルプでは「traceのコールバックが書きやすいよ」と紹介されています。
trace add variable vbl write {apply {{v1 v2 op} {
upvar 1 $v1 v
puts "updated variable to \"$v\""
}}}
逆にapplyを使わなかったらこうなるんでしょうね。
trace add variable vbl write report
proc report {v1 v2 op} {
upvar 1 $v1 v
puts "updated variable to \"$v\""
}
まぁ、確かにapplyを使うことでtraceからしか呼び出さないコールバック関数にわざわざ「report」なんてな名前を付けずに済みます。
しかし「そもそもtraceはデバッグ用の機能で他の変数の監視もするから関数化しとくべき」とか「ゴチャゴチャして可読性さがる」という印象の方が強い。
頑張って無理にでも使ってみた
「TclでHello, world! ~その2~」に書いたTCPのEchoサーバーを無理やりapplyで書いてみました。
socket -server [list apply {{sock host port} {
fconfigure $sock -buffering line -encoding utf-8 -translation crlf
fileevent $sock readable [list apply {{sock} {
set data [gets $sock]
if {[eof $sock]} {
close $sock
} else {
puts $sock $data
}
}} $sock]
}}] 9999
vwait forever
ちぇんと動作しました。が・・・う~ん、やっぱりゴチャゴチャして理解しにくい。