Tcl/Tk
は、スクリプト言語 と、その GUIツールキット Tk を指す。非常に強力な GUI ツールキットと、シンプルな文法をもつ言語により、GUI ツールを素早く作り上げるのに適した強力なスクリプティング環境である。
は、スクリプト言語 とGUIツールキット Tk からなる 非常に強力なGUIスクリプティング環境である。現在、各種オペレーティングシステム（、、）上で動作する。
他にも ウェブブラウザ上で を動作させるプラグイン がある。
がカリフォルニア大学バークレー校のジョン・ケネス・オースターハウト博士により最初に開発されたのは1988年の事である。当時アプリケーションプログラムに組み込まれる拡張用スクリプト言語には標準がなく、アプリケーション毎に独自の言語が実装されていた。そのためアプリケーション使用者はツール毎に異なるスクリプト言語の習得を余儀なくされた。この非効率さを嘆いたオースターハウトは、状況を打開するために アプリケーションにおける標準となる拡張スクリプト言語をデザインしようと考えた。こうして作られたのが の始まりである。そのため はアプリケーションへの組み込みが容易であることを重視してデザインされた。具体的には処理系をライブラリとして提供することでC言語で書かれたアプリケーションに容易に組み込めることや、言語構造が簡素であり、かつ高い拡張性を持つこと、インタプリター言語であることが挙げられる。
Tk は 用に開発された、非常に簡単なコードで GUI を作成できるツールキットである。1990年代初頭に にバンドルされる形で公開された。アップルの に触発されて開発されたと言う。当初 の有用な活用事例の一つとして紹介された Tk だが、その取り扱いやすさから 言語と共に一躍人気に火がつく。 は当初の設計意図と異なり、アプリケーションの組み込み言語として使われるよりも、Tk と合わせた「」の形の GUI スクリプティング環境として人気を博した。特に Tk の人気は高く、 にとどまらず （）、 （）、 （）など、他の言語でも標準的な GUI キットとして Tk が利用された。
オースターハウトがサン・マイクロシステムズに勤めていた1994-1998年は は同社で開発が進められた。このころのサンは WWW クライアント環境の制覇に向け邁進していた時期であり、 もその流れの上、その対象領域をウェブに広げていく。ウェブブラウザ上で Tk GUI を動作させるプラグイン「」や、ブラウザのスクリプト言語としての の組み込み、国際化対応（内部処理の 化）、インタプリタからバイトコンパイラへの変更による実行速度の大幅な向上など、 はこの時期機能的にもっとも大きな進歩を果たした。しかし他技術との競合やブラウザでのサポートの薄さなどもあり、WWWを「第二の Tk」として人気を拡大することは出来なかった。
オースターハウトの退職に伴い、 の開発はサンの手を離れた。2000年からは の開発はオープンソースにその場を移し、精力的に開発が続けられている。
2005年現在 言語は「」の知名度とは裏腹に利用者数は少なく、 や 、 に比べ劣勢と言わざるを得ない。特に日本国内での利用者数は少ない。ただし、EDAツールにおいては標準的なスクリプト言語として広く利用されているほか、電子国土Webシステムにおいても一部で 言語が使われている。一方 Tk は、後発の GTK+、Qt と並び、軽量プログラミング言語における事実上の標準 GUI ツールキットの一つとなっており、広く利用されている。
なお、 言語の名前は「ツールコマンド言語」を意味する英語「」に由来し、Tk の名前は「ツールキット」を意味する英語「」に由来する。
ここでは 言語の特徴を記す。の二つを組み合わせ、非常に小さいルールで広範囲の領域をカバーする点にある。コマンド行はひとつのリストであり、先頭の要素がコマンド、それ以降の要素がコマンドへの引数として扱われる。 言語と同様の一貫性を持つと言えるが、リストの要素分離記号がブランクやタブであるため、これらの文字が無視される一般のプログラム言語に慣れた人には「とまどい」を与えるかもしれない。
リストは文字列である。リストを構成する要素はブランクかタブで区切られる。ブランクやタブを要素に含めたい場合には、その要素をブレス（codice_1、codice_2）で挟めば良い。以下の文字列は三つの要素から成るリストである。
パーサーがソースコードからコマンド行としてリストを取り出すとき、ひとつのリストの終端は改行コードかセミコロン（codice_3）で判断する。しかし改行コードやセミコロンがブレスの内側にあれば、それをリストの終端記号とは見なさない。したがって、以下の3行の文字列は3つの要素から成るひとつのリストである。改行コードは3個あるが、最後の改行コードだけがリストの終端記号の役割を果たす。
上記リストは の codice_4 コマンドでありC言語の codice_4 文に似ている。しかしブレスがリスト記述記号として採用されているので似ているだけである。上記の codice_4 コマンドを以下のように改行の位置を変えると、codice_4コマンドの引数エラーになる。
ここで重要なのは、エラーを返したのは codice_4 コマンドであり、 パーサーが検出した「文法エラー」ではないということである。 には制御文などの「文」はない。分岐や繰り返しなどの実行制御も単にコマンドによって実現されているだけである。「 には細かなルールが無い」のであり、そこにはリスト構造と、以下に解説する「特殊記号」しかない。
パーサーはリストの先頭要素を常にコマンド名として認識する。それ以外の要素はコマンドに渡すべき引数として認識する。しかし、その引数要素がブラケット（codice_10、codice_11）で挟まれていると、その中身をコマンド行と認識し、それを実行してから本来の引数値を求めてくれる。これが「コマンド置換」である。
パーサーは変数機能の提供によりコマンド間でのデータの受け渡しも扱ってくれる。変数はsetコマンドにより生成される。そして、$記号が先頭に付いた要素を変数名とみなし、その値に要素全体を置換する。これが「変数置換」である。
変数置換はコマンド行の先頭要素に対しても機能する。つまりコマンド名を変数で与えることも可能である。
変数置換は1回しか実行されない。変数置換結果に文字「codice_12」が含まれていても再置換が試みられることはない。
また、変数置換で得られた文字列にブランクが含まれていても、2つの引数としてではなく、ブランクが含まれた1つの引数として渡される。引数の分離（リストの認識）は変数置換前に行われるからである。もし置換結果から改めて引数分離を行わせたいなら codice_14 コマンドを利用する。
リスト構造で解説したように、ブレス（codice_1、codice_2）は、改行コードなどの特殊文字の機能を無効化する。この法則はコマンド置換子であるブラケットや、変数置換子である$記号に対しても貫かれる。そのため、下記のコードではコマンド置換も変数置換も行われない。
そのため、実行結果として出力される文字列は以下のものになる。
コマンド置換も変数置換も機能させ、かつブランクを含む文字列をひとつの引数として codice_17 コマンドに渡すには、ブレスの代わりにダブルクォーテーション（codice_18）で挟めば良い。
num変数に3がセットされていればコマンドの実行結果として
が出力される。
このように、ダブルクォーテーションの機能はブレス機能とほぼ同等であるが、コマンド置換と変数置換をTclパーサーに許すところが異なる。ダブルクォーテーションの中でのコマンド置換、変数置換は の特長的な機能である。なお、ダブルクォーテーションとブレスの機能は、それらがリスト要素の先頭と末尾に記述された場合にのみ有効である。下の例では「codice_18」は文字として扱われる。
複数のコマンドを1行に記述したい場合はコマンド行をセミコロン（codice_3）で区切れば良い。
コマンドの位置に「codice_21」を記述すると行末までコメントと見なされる。「コマンドの位置に」ということが重要であり、以下の最後のコードは「codice_21」がコマンドの位置にないので誤りである。
ひとつのコマンドを複数行で記述したい場合は、行の末尾にバックスラッシュを付ける。
$文字の前に\を置くと$置換子の機能を抑制して単なる文字として扱わせることができる。
コマンド置換子（codice_10、codice_11）、ブレス（codice_1、codice_2）の前に置いた場合も同様である。
基本的にバックスラッシュにはC言語とほぼ同じ機能がある。例えば改行コードは「codice_27」と書ける。
パーサーから渡された引数がコマンド内部で評価されるか否かは重要である。ここでの評価とはコマンド置換や変数置換のことである。例えば算術演算を行う codice_28 コマンドは引数を内部で評価する。従って以下の2つのコマンドは同じ結果を返す。
この場合、 パーサは引数を順に評価し、第一引数として「codice_51」という4文字の文字列リテラルを、第二引数として「{～処理～}」を、codice_4、codice_31 コマンドに渡す。codice_4、codice_31 コマンド側は受け取った文字列を codice_28 コマンドに「codice_57」として渡し、その結果をもって処理を続ける。codice_31 コマンドは codice_36 をひと通り評価し終えた後、再度、第一引数を codice_28 で評価するが、上記のコードでは与えられている値が codice_51 なので codice_36 の中で「codice_48」のような文があれば、その評価値も codice_64 になって、その時点で繰り返し処理を終了する。
一方、codice_65コマンドの第1引数は内部では評価されない。したがって下記の2番目の記述は期待する結果が得られない。
もし引数をコマンド内部で評価してくれるならば、その引数はブレス({})で挟んで渡した方が効率が良い。Tclパーサーとコマンドの両方による多重評価処理を回避できるからである。このような理由により、codice_4コマンドやcodice_31コマンドやcodice_68コマンドの引数は常にブレスで挟むべきである。特にループの条件式は必ずブレスで挟む必要がある。ブレスで挟まないと変数置換されてからループコマンドに渡されてしまうので、定数を並べた条件式になってしまい、無限ループをもたらす。
コマンドには、 パーサーにあらかじめ実装されているビルトインコマンドと、ユーザーにより作成された拡張コマンドがある。ユーザーによる拡張コマンドの実装は簡単である。まず、C言語などで「コマンド本体関数」と「登録用関数」を記述し、ダイナミックリンクライブラリファイルに格納する。そして組み込みコマンドの codice_69 を用いて拡張コマンドを登録する。
codice_69 コマンドの引数には、「ライブラリファイル名」と「登録用コマンド名」を与える。codice_69 コマンドは、登録用コマンド名から「登録用関数」名を求め、これを実行してくれる。例えば codice_72 コマンドであれば codice_73 を実行してくれる。この「登録用関数」の中に本当の登録処理を記述しておく。従って、例えば codice_69 コマンドに渡したコマンド名にライブラリ名の意味を持たせ、「登録用関数」の中で複数のコマンドを登録してしまうことも可能である。
「本当の」コマンド登録はC言語のインターフェース用の関数の codice_75 や codice_76 を用いて行う。拡張コマンドの実体となる「コマンド本体関数」を、決められた型と引数に従って先に定義しておき、そのコマンド関数アドレスと公開コマンド名を引数に与えて実行すれば登録される。
コマンド登録関数
コマンド本体関数
コマンド本体関数は、 パーサーからの引数を、引数の数（codice_77）と引数文字列配列（codice_78）で受け取る。ただし、引数を文字列で受け取るこの方式は codice_75 関数で登録する場合であり、引数を オブジェクトで受け取りたい場合には、上例のように codice_76 関数で登録する。
パーサーは、スクリプト文字列を受け取り、常に処理結果を文字列で返すように見える。これでは文字列の解析や文字コードとバイナリ値への変換が頻繁に行われていることになり、いかにも効率が悪く思える。しかし決してそのような単純なものではなく、内部では可能な限りバイナリ値を維持している。 スクリプトでバイナリ値も扱えるのはこのおかげである。
例えば下記のように変数に数値を与え、その計算結果を変数に格納するとき、おのおの変数の型は文字列と codice_81 の二つの型を持つ。文字列として参照されるときは文字列型として振る舞い、codice_81 として参照されるとき（計算式の中などで）は codice_81 型として振る舞うことができる。
リストも同様に内部ではリスト型の オブジェクトとして存在している。このような仕組みになっているので、リストを作成する時は codice_91 コマンドを用いるべきであることが分かる。また、巨大なリストを文字列として全体参照するのも効率を悪くするので慎重にすべきである。下記の例では変数 codice_92 には文字列として格納されるが、codice_93 には codice_85 値のリストとして格納される。この後、これらの変数にリスト処理コマンドでアクセスすると、codice_92 に対しては要素分解処理が行われるが、codice_93 に対しては不要となる。
前項で解説したコマンド登録関数の後者（codice_76）は、 パーサーからの引数を、無駄に文字列変換することなく、 オブジェクトのままで受け取るコマンド関数を登録するためのものである。
返値も オブジェクトを通じて返すことができる。下記は codice_98 値をそのまま返す例である。
返値のみならず、 オブジェクトは不要になったとき自動的に削除される仕組みがある。それは オブジェクトが持つ「参照カウンタ」による制御である。アプリケーションで オブジェクトを作成し、それを存続したければ参照カウンタを増加させておき（codice_99）、必要なしとなったところで減ずる（codice_100）ようにする。参照カウンタが減らされて codice_101 になったときにのみ、そのオブジェクトは削除される。つまり、存続と廃棄の要求を自分だけの都合で出しておくだけで、削除のタイミングがコントロールされるという仕組みである（スマートポインタ）。
変数のみならず、スクリプト自体も オブジェクトとして存在している。