ここでは SAD/Tkinter で書いた "Hello, World!" をその最も単純なアプリケーションとして紹介します。このプログラムは(1) Xウインドウに "Hello"というボタンを表示し、(2) そのボタンをクリックするとターミナル (標準出力) に "Hello, World!"と出力する、というきわめて単純なものです。それは、SAD/Tkinter では、
FFS; w = Window[]; b = Button[w, Text -> "Hello", Command :> Print["Hello, World!"]]; TkWait[];
となります。
まず、第 1 行の FFS;は SAD の中の FFSというサブシステムを起動することを指示しています。FFSが実際何であるかは後述するとして、ここでは SAD/Tkinter はすべてこの FFSの中で実行されるものとして理解してください。
第 2 行
w = Window[];
はある新しい Windowという部品 (widget と呼ばれる) を定義しています。Windowは Xサーヴァの画面上に通常は枠を伴って表示され、その中に各種の部品を詰めることができます。この例では左辺のシンボル "w"にこの新しい Windowが割り当てられます。
ちなみに SADScript では大文字と小文字は区別されます。また、システムに備え付けられた関数は単語の区切りの頭文字が大文字になり、他は小文字になります。例えば ListPlot, LinearSolveなどがそれです。ユーザはシステムが定義していなければシンボルとして何文字でも使えます。
ひとつのシンボル、数値、演算子の途中に空白や改行をいれることはできません。文字列はその行の最後に ?をおけば、改行して書くことができます。 この場合改行文字はデータの中には含まれません。 データの中に改行文字そのものをいれる場合は ?を入力します (stringinput参照)。 これ以外の場所には自由に改行や空白を入れられます。
従って SADScript の書式はきわめて自由です。その結果、出来上がったプログラムの見やすさはかなり書き方に依存してしまいます。なお実行速度は書式とは関係ありません。
ところでこの行の最後にあるセミコロンは二つ以上の式を互いに連結してひとつの式をつくる演算子です。セミコロンを省いた場合、もしその行の最後で式が完結しているとみなされるならば、その式はそこで評価され、その結果が端末に(Out[n]:= の形で)出力されます。 (なお、この結果は再利用できます)。 したがって、そのような出力が必要なければセミコロンをつけるべきです。ある式がセミコロンで終わってその後ろに何も書かれていないときにはセミコロンの後には特殊なシンボル Nullがあるとみなされます。Nullの出力は何もないので上のような事情になるわけです。
右辺のWindow[]の記号[]は関数の引用を表わしています。この中には以下に見るように必要な引数をいれることができます。
次に第3,4,5行
b = Button[w, Text -> "Hello", Command :> Print["Hello, World!"]];
は Window wにいれる部品として Button bを定義しています。まず第 3 行にあるように、最初の引き数 wはこの Button が前に定義した Window w の子供であることを指示しています。ある部品はこのように直接 Windowの子供となることもできますし、また他の部品、例えば Frameの子供にして間接的にある Windowに表示させることもできます。
次の引数 Text -> "Hello" はこの Button の表面に "Hello"という文字を表示することを指示しています。記号 -> の意味は後述します。このようにある文字列は二重引用符で囲みます。引き数と引き数の区切りはカンマで表わします。
この例にあるように、ある部品の属性の設定を伴う定義は
シンボル = 部品[親, 属性 -> 値, ...];
という形をとります。属性は同時に何種類も指定して構いません。 また、属性は部品を定義した後に
シンボル[属性] = 値;
b = Button[w, Command :> Print["Hello, World!"]]; b[Text] = "Hello";
としても結果は同じです。しかし、順番を逆にして
b[Text] = "Hello"; (ア) b = Button[w, Command :> Print["Hello, World!"]];
としたのでは結果は全然違い、このボタンにはなにも表示されません。これは、(ア) の時点では b はまだButton ではないため、b[Text] = .. に Button の属性を指定するという作用がないからです。
さてその次の引き数
Command :> Print["Hello, World!"]
はこのボタン bがクリックされたときに実行する SAD のコマンドを指定しています。これも構文上は上述の 属性 -> 値という形に似ていますが、記号 ->の代わりに :>が用いられています。:>は ->と同等ですが、違いはその右辺の式、今の場合は Print["Hello, World!"]が直には評価されず、与えた式のまま関数に渡されるという点にあります。もし、:>の代わりに ->を使いますと、この場合にはこのボタンを定義した時点で Print["Hello, World!"]が実行され端末に Hello, World!と出力されてしまい、またボタンのほうには Printの返す値 Null が割り当てられてしまいます。このような事態をさけるため :>が使われます。このような演算子は遅延演算子とよばれ、SAD では随所で用いられます。
また、Commandのような遅延定義を必要とする属性を再定義するには
シンボル[属性] := 値;
のように演算子 :=を =の代わりに用います。
このように、Commandには SAD の任意の式 (プログラム) を結び付けることができますから、ボタンに対して任意の機能を与えることができます。
さて、このように定義してきた二つの部品 Window と Button は、画面上には現われていてもまだ何も動作することはできません。それは次の
TkWait[];
という関数が評価されてはじめて実行されます。TkWait[]は画面上に 図のウインドウを表示して、イヴェント (例えばマウスクリック) 待ちの状態にはいります。 そこでこのボタンをクリックする毎に端末には
Hello, World!
と表示されます。
図 Hello, World!
これでこの章の目的の"Hello, World!"は完成しました。
TkWait[]という関数は TkReturnという関数が実行されるまで無限に待ちつづけ、その間ボタンのクリックへの反応などの必要な動作を行います。 関数 TkReturnが呼ばれれば、その引き数を値として返しつつ TkWait[]は実行を終えます。 現在の TkinterはこのTkReturnを発行する、 図のような特別のボタンを画面の左上に必ず表示します このボタンはクリックされると TkReturn["ReturnToSAD"]というコマンドを実行します。 また、このボタンのあるウインドウの左上の四角をクリックすると SAD が即座に停止します。 ただしこのボタンはデバッグの時以外はあまり有用でないため、将来は標準でなくなる可能性が高いと思われます。
図 ReturnToSADのボタン。ウインドウタイトルにあるのは SAD のプロセス番号