Tcl/Tk
出典: フリー百科事典『ウィキペディア(Wikipedia)』
Tcl/Tk(ティクル・ティーケーと読む)は、スクリプト言語 Tcl (Tool Command Language)と、そのGUIツールキット Tk (Tool Kit) を指す。非常に強力なGUIツールキットと、シンプルな文法をもつ言語により、GUIツールを素早く作り上げるのに適した強力なスクリプティング環境である。
目次 |
[編集] 概要
Tcl/Tk は、スクリプト言語TclとGUIツールキットTkからなる 非常に強力なGUIスクリプティング環境である。現在、各種Unix、Windows、Macintosh上で動作する。
Tclは、ブロックを文字列で表現することで、コマンド行のみで構造化文法をフォローしてしまう非常にシンプルな文法を特徴とする。TclのソースコードとTclソースコードの文字列編集の境界は非常に曖昧であり、その点は好みの分かれるところである。Tk はクロスプラットフォームなGUI環境としても有名で、Tclに限らず、Perl、Python、Ruby などからも一般的にTkが利用されている。
他にも Webブラウザ上でTcl/Tkを動作させるプラグイン Tcletなどがある。
[編集] 背景
Tcl が カリフォルニア大学(UC)バークレー校のJ.K.Ousterhout博士により最初に開発されたのは1988年の事である。当時アプリケーションプログラムに組み込まれる拡張用スクリプト言語には標準がなく、アプリケーション毎に独自の言語が実装されていた。そのためアプリケーション使用者はツール毎に異なるスクリプト言語を習得を余儀なくされた。この非効率さを嘆いたOusterhoutは、状況打開するためにUnixアプリケーションにおける標準となる拡張スクリプト言語をデザインしよう考えた。こうして作られたのがTclの始まりである。 そのためTclはアプリケーションへの組み込みが容易であることを重視しデザインされた。具体的には処理系をライブラリとして提供することでCで書かれたアプリケーションに容易に組み込めることや、言語構造がシンプルであり、かつ高い拡張性を持つこと、インタプリター言語であることが挙げられる。
Tk はTcl用に開発された、非常に簡単なコードでGUIを作成できるツールキットである。1990年代初頭にTclにバンドルされる形で公開された。AppleのHyperCardに触発されて開発されたと言う。当初Tclの有用な活用事例の一つとして紹介されたTkだが、その取り扱いやすさからTcl言語と共に一躍人気に火がつく。Tclは当初の設計意図と異なり、単体のGUIスクリプティング環境として人気を博した。特にTkの人気は高く、TclにとどまらずPerl (Perl/Tk)、Python (Tkinter)、Ruby (Ruby/Tk)など、他の言語でも標準的なGUIキットとしてTkを利用した。
OusterhotがSun Microsystemsに勤めていた1994-1998年はTcl/Tkは同社で開発が進められた。このころのSunはWWWクライアント環境の制覇に向け邁進していた時期であり、Tcl/Tkもその流れの上、その対象領域をWebに広げていく。Webブラウザ上でTk GUIを動作させるプラグインTcletや、ブラウザのスクリプト言語としてのTclの組み込み、国際化対応(内部処理のUnicode化)、インタプリタからバイトコンパイラへの変更による実行速度の大幅な向上など、Tcl/Tkはこの時期 機能的にもっとも大きな進歩を果たした。しかし他技術との競合やブラウザでのサポートの薄さなどもあり、WWWを「第二のTk」として人気を拡大することは残念ながら出来なかった。
Ousterhoutの退職に伴い、Tcl/Tkの開発はSunの手を離れた。 2000年からは Tcl/Tkの開発はオープンソースにその場を移し、精力的に開発が続けられている。
2005年現在 Tcl言語は "Tcl/Tk" の知名度とは裏腹にユーザ数は少なく、PerlやPython、Rubyに比べ 若干マイナーと言わざるを得ない。特に国内でのユーザ数は少ない。ただし、EDAツールにおいては標準的なスクリプト言語として広く利用されている。一方 Tk は、後発の GTK+、Qtと並び、Lightweight Languageでの事実上の標準GUIツールキットの一つとなっており、広く利用されている。
[編集] 特徴
Tk については、別項 Tk に譲る。ここでは Tcl 言語の特徴を記す。
Tcl 言語の特徴は一言でいえばなんでも文字列である。 Tclは、
- コマンド行の順次実行のみのシンプルな文法
- 首尾一貫したリスト構造
の二つを組み合わせ、非常に小さいルールで広範囲の領域をカバーする点にある。コマンド行はひとつのリストであり、先頭の要素がコマンド、それ以降の要素がコマンドへのアーギュメントとして扱われる。Lisp的な美しさを持つと言えるが、リストの要素分離記号がブランクやタブであるため、両文字が無視される一般のプログラム言語に慣れた人には「とまどい」を与えるかもしれない。
[編集] リスト構造
リストは文字列である。リストを構成する要素はブランクかタブで区切られる。ブランクやタブを要素に含めたい場合には、その要素をブレス({})で挟めば良い。以下の文字列は3つの要素から成るリストである。
This is {a pen}
[編集] リストの抽出
Tclパーサーがソースコードからコマンド行としてリストを取り出すとき、ひとつのリストの終端は改行コードかセミコロン(;)で判断する。 しかし改行コードやセミコロンがブレスの内側にあれば、それをリストの終端記号とは見なさない。したがって、以下の3行の文字列は3つの要素から成るひとつのリストである。改行コードは3個あるが、最後の改行コードだけがリストの終端記号の役割を果たす。
if {$a<0} { set a 0 }
上記リストはTclのifコマンドでありC言語のif文に似ている。しかしブレスがリスト記述記号として採用されているので似ているだけである。上記のifコマンドを以下のように改行の位置を変えると、C言語では許されるがTclではifコマンドの引数エラーになる。
if {$a<0} { set a 0 }
Tclパーサーは上記4行の文字列を2つのリストとして認識する。したがって先頭行のifコマンド行はアーギュメントがひとつだけしか与えられていないことになり、引数エラーが発生する。
ここで重要なのは、エラーを返したのはifコマンドであり、Tclパーサーが検出した「文法エラー」ではないということである。Tclには制御文などの「文」はない。分岐や繰り返しなどの実行制御も単にコマンドによって実現されているだけである。「Tclには細かなルールが無い」のであり、そこにはリスト構造と、以下に解説する「特殊記号」しかない。
[編集] ブラケット記号(コマンド置換)
Tclパーサーはリストの先頭要素を常にコマンド名として認識する。それ以外の要素はコマンドに渡すべきアーギュメントとして認識する。しかし、そのアーギュメント要素がブラケット([ ])で挟まれていると、その中身をコマンド行と認識し、それを実行してから本来のアーギュメント値を求めてくれる。これが「コマンド置換」である。
set a [expr 100*2]
[編集] $記号(変数置換)
Tclパーサーは変数機能の提供によりコマンド間でのデータの受け渡しも扱ってくれる。変数はsetコマンドにより生成される。そして、$記号が先頭に付いた要素を変数名とみなし、その値に要素全体を置換する。これが「変数置換」である。
set a {This is a pen.} puts $a
変数置換はコマンド行の先頭要素に対しても機能する。つまりコマンド名を変数で与えることも可能である。
変数置換は1回しか実行されない。変数置換結果に$文字が含まれていても再置換が試みられることはない。
また、変数置換で得られた文字列にブランクが含まれていても、2つのアーギュメントとしてではなく、ブランクが含まれた1つのアーギュメントとして渡される。アーギュメントの分離(リストの認識)は変数置換前に行われるからである。もし置換結果から改めてアーギュメント分離を行わせたいならevalコマンドを利用する。
[編集] ダブルコーテーション記号
リスト構造で解説したように、ブレス({})は、改行コードなどの特殊文字の機能を無効化する。この法則はコマンド置換子であるブラケットや、変数置換子である$記号に対しても貫かれる。以下のコードではコマンド置換も変数置換も行われないので"[expr 100*$num] 円" が出力されてしまう。
puts {[expr 100*$num] 円}
コマンド置換も変数置換も機能させ、かつブランクを含む文字列をひとつのアーギュメントとしてputsコマンドに渡すには、ブレスの代わりにダブルコーテーション("")で挟めば良い。
puts "[expr 100*$num] 円"
num変数に3がセットされていればコマンドの実行結果として
300 円
が出力される。
このように、ダブルコーテーションの機能はブレス機能とほぼ同等であるが、コマンド置換と変数置換をTclパーサーに許すところが異なる。 ダブルコーテーションの中でのコマンド置換、変数置換はTclの特長的な機能である。 なお、ダブルコーテーションとブレスの機能は、それらがリスト要素の先頭と末尾に記述された場合にのみ有効である。下の例では""は文字として扱われる。
set text 石を投げたら"ゴツン"と音がした
[編集] セミコロン記号(マルチコマンド)
複数のコマンドを1行に記述したい場合はコマンド行をセミコロン(;)で区切れば良い。
set a 100; set b 200; puts [expr $a * $b]
[編集] #記号(コメント行)
コマンドの位置に # を記述すると行末までコメントと見なされる。「コマンドの位置に」ということが重要であり、以下の最後のコードは#がコマンドの位置にないので誤りである。
#初期値セット # set a 0 set b 0 ; # 初期値 set c 0 # 初期値
[編集] バックスラッシュ記号
ひとつのコマンドを複数行で記述したい場合は、行の末尾にバックスラッシュを付ける。
command $arg1 $arg2 \ $arg3 $arg4
$文字の前に\を置くと$置換子の機能を抑制して単なる文字として扱わせることができる。
puts "金額=\$100"
コマンド置換子([ ])、ブレス({})の前に置いた場合も同様である。 基本的にバックスラッシュにはC言語とほぼ同じ機能がある。例えば改行コードは \n と書ける。
[編集] 補足:アーギュメントをブレスで挟むことのもうひとつの意味
Tclパーサーから渡されたアーギュメントがコマンド内部で評価されるか否かは重要である。ここでの評価とはコマンド置換や変数置換のことである。例えば算術演算を行う"expr"コマンドはアーギュメントを内部で評価している。従って以下の2つのコマンドは同じ結果を返す。
expr $a*$b expr {$a*$b}
Tclパーサーが行ってくれずとも、"expr"コマンドが内部で変数置換しているので同じ結果が得られるのである。"if"コマンドや"while"コマンドのアーギュメントも内部で評価が行われる。 一方、"switch"コマンドの第1引数は内部では評価されない。したがって下記の2番目の記述は期待する結果が得られない。
switch $val {...} switch {$val} {...}
もしアーギュメントをコマンド内部で評価してくれるならば、そのアーギュメントはブレス({})で挟んで渡した方が効率が良い。Tclパーサーとコマンドの両方よる多重評価処理を回避できるからである。このような理由により、ifコマンドやwhileコマンドのアーギュメントは常にブレスで挟むべきである。
[編集] 外部リンク
- Tcl Developer Exchange - Tcl/Tk開発のホーム
- Tcl 8.4.1 Manual Command Reference - 日本語のTclリファレンス