Tcl/Tkでスクリプトを書く時、各コマンドのちょっとした挙動を確認するためにtkconをよく使います。(ディストロはMagicsplatを使っています)
先日、tkconがおかしくなって、他のアプリでコピーした文字列をtkconに貼り付けられなくなったことがあって、一度、ちゃんとtkconのソースも読んどかないとだめだな~と感じていました。
その手始めとして、tkcon.tkappを読んでみたところ、色々と発見があって勉強になりました。
ちなみにヘルプをちゃんと読めば書いてある場合が多いですが、Tcl/Tkのヘルプって徹底的に文章だけで図解とか一切無いので、(英語はGoogle翻訳で何とかできるけど)初見で理解するのはほぼ無理です、私には。せめてTkのヘルプには図解も入れて欲しいものですが。
dict with apps $app {}
スクリプト本体(body)がありません。ナニコレ??
辞書appsは
:
set apps {
tkcon {
Name "Tkcon Enhanced Shell"
Path {apps tkcon.tcl}
Exec 1
}
tclprodebug {
Name "TclPro Debugger"
Path {apps tclprodebug startup.tcl}
Exec 0
}
sockspy {
Name "Socket Spy"
Path {apps sockspy.tcl}
Exec 0
}
tpack {
Name "Tpack deployment tool"
Path {apps tpack.tcl}
Exec 1
}
}
:
と定義されており、appにはtkconが代入されているので、dict with apps $app {}
のスクリプト本体({}
の中)ではName、Path、Execを変数名として扱えます。
が、スクリプト本体が空です。
さらに読み進めると
:
dict with apps $app {}
set script [file join $tcldir {*}$Path]
:
dict with
文の次の行でPathという変数が使えています。
dict with
のヘルプを(Google翻訳して)読み直してみると、
The variables are mapped in the scope enclosing the dict with
(Google翻訳: 変数はdict を 囲むスコープにマッピングされます。)
とあり、謎が解けました。
dict with
で変数化されたtkconキー配下のName、Path、Execは、dict with
コマンド以降も変数として存続するんですね。(dict with
前後のinfo vars
の実行結果でも確認できます)
ぜ~んぜん、知りませんでした。てっきりVisual Basicとかにあるwith文のように、階層を省略して記述するための糖衣構文的なものと思い込んでいました。
dict with
文のスクリプト本体(body)の中と外の違いは、変数への代入で辞書そのものも変化するか否かのようです。
これは
puts [dict get $apps tkcon Exec]
#=> 1
dict with apps tkcon {set Exec 2}
puts [dict get $apps tkcon Exec]
#=> 2
set Exec 3
puts [dict get $apps tkcon Exec]
#=> 2
という実験をしてみれば確かめられます。
info nameofexecutable
実行環境のインタプリタのフルパスが分かるコマンドがあったんですね。
しかしヘルプに不穏な一文が。
Returns the absolute pathname of the program for the current interpreter. If such a file can not be identified an empty string is returned.
「分からんときは空っぽになるけどな」って、えー!
しかもTcl/Tkのヘルプのいつもの悪い癖硬派なところで、どんな時に「分からん」のかまでは教えてくれません。
kit化した時とかかな? とか邪推するしかない。
exec -- [info nameofexecutable] $script {*}$::argv &
最後の&はUNIX OSでよく使うバックグラウンド実行のコマンドラインを彷彿とさせますね。
実際、tkcon.tkappをtclshで実行すると、tclshが終了せずwishが起動してtkconのGUIが表示されます。(一方でUNIX OSのexecとは違ってプロセスの成り代わりは起きないってことですね)
ところでタスクマネージャーを表示しておいてwishでtkcon.tkappを実行しても、wishは2個になりません。
exec -- wish ... &
で別プロセスでもう一個のwishが起動しそうなものですが、不思議です。(こちらは何だかUNIX OSのexecみたいな挙動です)