About Tcl

Tclはインタプリタ言語・リスト処理・連想配列などの特長を有するスクリプト言語です。

What's Tcl
Tclの特長
シンプルな文法
インタプリタ型言語
再利用可能なライブラリ
ドキュメント性
変数宣言が不要
仮想関数
連想配列
リスト処理

What's Tcl

Tcl(Tool Command Language)はJohn K. Ousterhout博士が1988年にカリフォルニア州立大学バークレー校で開発したスクリプト言語で、ティクルと読みます。

インタプリタ言語,リスト処理,連想配列などの特長を持ち、アプリケーション開発のためのスクリプト言語として設計・拡張されてきたものです。

提供されているライブラリを用いることによりアプリケーションに組み込むことができます。つまり汎用的なスクリプト言語です。フリーソフトウエアですが商用利用も許されており、Tclにより開発したアプリケーションには著作権を主張することもできます。

TclはTcl/Tkとして一般には知られています。Tkは「ツールキット」の意味であり、GUI作成をはじめとするグラフィックアプリケーション作成ツールです。TkはTclのアプリケーションの一つですが、スクリプトを変更することなくほとんどのOSで実行できるところが人気です。また、Webアプリケーションを構築する上ではDHTMLやJavaScriptをはじめとするスクリプト言語を用いることが必須ですが、Tclはこの分野でも有効活用されています。Unix系のWebサーバーの拡張においてもTclは広く用いられており、フリーソフトウエアで開発ツールが提供されています。

言語にはそれぞれの特長があります。 目的にあった言語の選択が重要です。Tclをプログラミング言語と比較して優劣を論じるのは適切ではありません。

Tclの特長について簡単に紹介してみます。
まず「文法」はC言語に似ています。従ってJavaScriptにも似ています。しかし「文法」というものが無いところにそもそも特長があります。「文」に該当するものは「コマンドライン」です。このコマンドラインはリスト構造になっています。リストの先頭要素が「コマンド」で、残りの要素は「アーギュメント」です。この構造だけが「決めごと」であり、「if文」や「while文」のような「文」に見えるものは、実は「ifコマンド」「whileコマンド」であるにしか過ぎません。TclがC言語に似ているのは「Built-In Commands」としてあらかじめ組み込まれているこれらのコマンドがC言語に似せて作られているだけのことです。逆に言うと「制御文」まで自分で作れるということです。実際、列挙型関数などはforeachコマンドに似せた制御型コマンドとして実装すると便利です。

Tclを初めて使う時は少しとまどいます。特にブランクが重要な役割を果たしていることにとまどいます。一般的なプログラム言語ではブランクやタブは無視されますが、Tclではリストを構成する要素の区切り文字なので重要なのです。プログラムをコーディングしているのではなく、リストを記述しているという事を自覚すると「とまどい」から解放されます。

Tclパーサーはリスト処理としてコマンドを解釈実行しますが、コマンド間のデータ交換のため変数機能を提供しています。変数には型もサイズもありません。配列変数も同様です。配列サイズを超えてしまうという伝統的なバグから解放されます。また、配列の要素には文字列を使うことができます。配列と構造体がクロスオーバーしている様なものです。
変数に格納されている値を文字として、あるいは整数として、あるいは実数として、あるいはリストとして見なすのかは、それを渡されたコマンドに委ねられます。これはスクリプト言語として当然の仕様であり、プログラミング言語のような厳格さを求めてはなりません。

Tclは、提供されるC言語ライブラリを用いて容易にアプリケーションに組み込むことができます。
正確に言うと、アプリケーションにTclインタプリタ機能を組み込むことが容易にできるのです。
また、Tclコマンドとしてダイナミックリンクライブラリ(DLL)の関数を使うことも容易です。Tcl側では、loadコマンドで新しいコマンドを作成します。loadコマンドにはDLL名とコマンド名を与えて実行します。DLL側ではあらかじめ決められた命名規則でインターフェイス用の関数を実装しておきます。

インタプリタ機能を実装し、次にアプリケーションの関数をTclコマンドとして登録すれば、その後の拡張はTclスクリプトで可能になります。そしてエンドユーザーにはTclをカスタマイズ言語として提供できるのです。

自分が作成したアプリケーションではなく、市販されているアプリケーションでも、DLLによる機能追加方式がサポートされていさえすれば同様の拡張が可能です。

Tclを使ってもC言語のようなコーディングをしては意味がありません。例えば配列の要素にi変数を記述したforループ処理を書いたり、switchのcaseに整数を用いたり、制御フラグに数字を用いる等々をしてはなりません。データをそのまま参照及びセットする方法を採用すべきです。そのためにはリストや連想配列を意識的に使用することです。こうすることによってプログラムが読みやすくなり、簡潔に記述することが可能になります。

ここまでTclの良さをアピールしてきましたが、スクリプト言語にプログラミング言語の機能を期待してはいけないことも付記しておきます。

Tclの得意な分野と不得意な分野を見分けることが大切です。
アプリケーションエンジンを記述することには向きません。それから高速な計算処理にも向きません。これらは処理速度の面からのみならず、言語仕様の面からも不得意です。
つまり、C言語の得意分野には使うなということです。
ハードウエアで例えると、「ICはC言語でつくり、基板をTclでつくる」ということでしょう。

Tclが得意とするケースは、

  • 文字処理が多い
  • 現れるデータの予測が付かない
  • 頻繁に変更が発生する
  • プロトタイプを作成する
  • マルチプラットホーム対応にしたい

などの場合です。

最後に、処理速度についてですが、Ver8.0から拡張されたバイトコードコンパイル機能が処理速度を高めました。これは実行時に行われるコンパイルであり、メモリ空間にバイトコードを生成してから実行する仕組みになっています。
また名前空間機能がサポートされ、大きなプログラムの作成も容易になりました。そして最新のTclでは国際化も果たされました。しかも内部コードはunicodeそのものではなくUTF-8コードが採用され効率の良いものになっています。

※参考文献 Tcl&TKツールキット/ソフトバンク株式会社発行

Tclの特長

シンプルな文法

■コマンドと、そのコマンドが必要とするアーギュメントをリスト形式で記述するだけです。リストの先頭要素がコマンドで、以降の要素はすべてアーギュメントです。

set val 123

■コマンドには

  1. Tclがあらかじめ提供しているコアコマンド
  2. ユーザーがC++などで作成したもの
  3. 複合コマンドとしてのプロシージャ

などがあります。これらは完全に同格です。

■リストを記述するための特殊文字{ } " "と、Tclパーサーにリスト要素を置換する特殊文字[ ] $ があります

@リストを ""で挟むとひとつの要素になります(ブランクやタブが単なる文字扱いとなります)。

set address "東京都 町田市"

A同様にリストを{}で挟んでも一つの要素になります。ブランクやタブが単なる文字扱いとなるだけではなく、[ ] $ も単なる文字扱いとなり、下記の置換子の機能が働かなくなります。

B$が文字列中に現れると、$に続く文字列が変数とみなされ、その値に置き換えられます(変数置換)。

puts $address

Cリストを[]で挟むと、コマンドラインとみなされ、その実行結果に置き換えられます(コマンド置換)。

set answer [expr sin(1.24)*cos(2.8)]

コンパイル,リンクの手間が不要(インタプリタ型言語)

実行前にバイトコードにコンパイルされ、高速化が図られています。

再利用可能なライブラリを構築

sourceコマンドでソースファイルをロードするだけで、そのファイルに記述されているプロシージャ(関数)が利用可能になります。

source mylib.tcl

ドキュメント性が良い

簡潔に記述できます。日本語で変数名プロシージャ名を記述できます。

set 住所 横浜市神奈川区東神奈川2-33

変数宣言が不要−型をもたない

  • 整数型,実数型,文字型,配列...すべて宣言不要です。
  • 代入コマンド(set)に初めて現れたときメモリが確保されます。
  • 変数・配列とも、サイズは自動拡張されます。
  • ローカル変数とグローバル変数、名前空間変数がサポートされています。
  • 変数はunsetコマンドで削除(メモリ開放)できます。

仮想関数

ライブラリをロードするだけでダイナミックに関数の入れ替えが可能です。
また実行時の再定義も可能です。
つまり仮想関数がサポートされていると言えます。

連想配列−多次元配列で、添え字に文字列が使える

配列を構造体のように使うことができます。

array set 社員0012 {
   名前 "渡辺 淳一"
   役職 係長
   年齢 36
}

リスト処理

リスト内の項目を順に取り出したり、入れ替えたり、挿入したりできます。

要素の追加

lappend list $elem1 $elem2 $elem3 ...

要素の抽出

set elem1 [lindex $list 0]

要素を順に抽出して処理

foreach elem $list {
  puts $elem
}