Smalltalk
Smalltalk は反復処理のための基本構文を備えているが、ある値の生成器(入出力等)やある集合要素から要素を取得するときに基本的な反復構文を使う事は稀である。Smalltalk では、値を列挙するために値の生成器や集合要素に送るべきメッセージが概ね決まっており、値を取り出す際は極力、列挙メッセージ(英: enumerating)を使用する事が作法となっている。
次に列挙メッセージの送信例を示す。
配列に対する列挙メッセージの例:
実行結果:
数値に対する列挙メッセージの例:
実行結果:
列挙メッセージで使えるセレクターは #do: の様に全ての要素にブロックを適用するだけの単純なセレクターだけでなく、現在の集合要素の要素を操作した上で新しい集合要素を作成する #collect: や、集合要素から条件に一致する要素だけを抜き出し、新しい集合要素を作り出す #select:、集合要素の中から特定の要素を見つけ出す #detect:ifNone: など様々なセレクターがある。処理系によっては #groupBy:having: などSQLに類似したセレクターに対応するメソッドを多数用意しているものもある。Smalltalk では集合要素や値の生成器自体にこれらのメッセージを受け取れるよう実装する事で、集合要素のデータ構造や、生成器の入力元などの構造に依存せず最適な反復処理を実現できるようになっている。これらの列挙機能は近年の言語において foreach やyeild、LINQ等言語機能として賄われつつあるが Smalltalk においては、単にライブラリーの慣習として実現されている所が特徴的である。
Smalltalk では、単一の値を出し入れするメッセージの事を特にアクセッサ―と呼ぶ。引き数の有無により値の入出の方向を区別する。
例:
Smalltalk においてアクセッサーはその他のメソッドと役割に違いはなく特別な意味を持たないが、プロトコルとして明示的に accessing()として登録される点が特徴的である。
Smalltalk においてアクセッサーはインスタンス変数の出し入れや、クラス変数の単純な出し入れに使用される事は多くない。Smalltalk においてアクセッサーは次の用途でよく使われる。
プール辞書は、クラスの変数として連想配列または、他のクラスオブジェクトのクラス変数を取り込むという機能である。取り込む連想配列の要素やクラスオブジェクトのクラス変数はプール変数と呼ばれる。連想配列やクラスオブジェクトは大域変数でなくてはならない。
プール辞書には複数の連想配列やクラスオブジェクトを指定できるが、プール変数が重複した場合は、先に指定した連想配列やクラスオブジェクトのプール変数が使われる。
言語として Smalltalk が目指したもの。それは計算機を計算機の集合体として構築し、さらに計算機を構成する個々の計算機も計算機の集合体で構築するというように、再帰的な計算機を構築することであった。この再帰的な計算機を構築している無数の計算機は、個々の内部には干渉せずメッセージによる通信のみによって相互作用を発生させ目的の計算を完遂させる。
ここでいう計算機が Smalltalk ではオブジェクトという形で実装された。
この設計思想の誕生は、ロバート・S・バートン(英語版)とB5000の設計者らが会談した際の次の発言をアラン・ケイが聞き「計算機の全体を計算機とみなした場合、その計算機の構成要素を計算機に分解するのではなく関数やデータ構造に分解したいと誰が思うのか」と疑問を浮かべた事がきっかけとなっている。
ここで言及された再帰という概念は、オブジェクトの成立以外にも Smalltalk の至るところに影響を与えている。
しかし、クラスの登録はあくまでメッセージであり自由に作れるため、実行環境には大抵その他のメソッドが用意されている。例えば、近代的な Smalltalk 環境の一つ Pharo では、次のセレクターに対応したメソッドが用意されている。
クラスオブジェクトには、クラス変数とは別途、クラスオブジェクトが Class クラスから派生したインスタンスとして状態を持つためのインスタンス変数がある。このクラスオブジェクトのインスタンス変数はクラスオブジェクト内だけで共有され、インスタンスオブジェクトからは直接使用できない。
Smalltalk 環境に対するクラスオブジェクトのインスタンス変数の登録は次の様に記述する。
クラスオブジェクトがもつインスタンス変数には変数を登録した基底クラスと派生クラスで別々の変数領域が確保されるという特筆すべき点がある。これを使用して下記の様にクラスに所属するオブジェクトだけを保持する変数としてつかったりする事ができる。
複数の例外は、#on:do:on:do・・とon:do:を繰り返し(処理系が定義している限りの数で)記述して補足する事もできるが、次の様に例外の型を,で並べて補足する事も出来る。
なお、Smalltalkでは正常な結果を返せない異常な状態と通知両方を合わせたものが例外である。例外は正常な戻り値を返せない異常な場合と割り込みの様に非同期な通知に利用される。特徴的な点として異常な場合と通知の場合では動作が異なる。異常な場合は他の言語の例外同様、補足しなければその時点で停止しDebugウィンドウに移行するが、通知の場合は補足しなければ例外発生地点から処理を継続する。
並列処理
Smalltalkでは、標準で並列処理が存在する。並列処理は次の様に記述する。
並列処理はスレッドに類似するプロセスという仕組みにより実装されている。プロセスはSmalltalk環境内で構築された並列処理の仕組みであり、グリーンスレッドで実装されている事が多い。このため、プロセスは論理的に非プリエンプティブなスレッド(グリーンスレッド)を前提しており、現在実行している処理を切り替える切り替え点を必要とする。論理的な前提は非プリエンプティブではあるものの、POSIX環境で動作させたGNU Smalltalkの様に実際はプリエンプティブなスレッドで実装されている場合もある。プロセスは他のプロセスから割り込みとして任意の例外を投げる機能があり(記述方法は環境によって異なる)、切り替え点はプリエンプティブなスレッドを使う場合でも例外の発生地点として機能する。
反復はメソッドの再帰呼び出し。
インスタンスオブジェクトを生成しているクラスオブジェクトも、クラスオブジェクトに所属するインスタンスオブジェクトであり再帰関係を持つ。
MetaclassはMetaclass classのインスタンスオブジェクトでありMetaclass classは、Metaclassであり再帰関係を持つ。
基本的な派生元となるObjectやProtoObjectは、それらから派生したUndefinedObjectのインスタンスオブジェクトであるnilを継承しており再帰関係を持つ。
Smalltalk 言語は Smalltalk 言語自身によりメッセージ送信等の言語機能が制御される。
Smalltalk 言語の翻訳や仮想機械は Smalltalk 言語により実装される。
Smalltalk 言語の大域変数はSmalltalk変数に格納されたオブジェクトにより管理されるが、Smalltalk変数自体も大域変数である。
一時変数は宣言が必要で、「|」で挿むように記述する。変数への代入は「:=」。古い処理系では「_」が使用された(字形は「←」)。変数に型はなく全てハンドルになっている。
Smalltalk環境は翻訳方式を使う処理系としては珍しくプログラムの実行時書き換えを基本とする。例えば後述のClass Browserに入力したプログラムはソースコードを中間言語に変換したあとSmalltalk環境の一部として取り込まれ、環境を再起動したり読み込み操作をしなくても起動中のSmalltalk環境内で実行することができる。C++のような翻訳式の言語であれば原則、ソースコードを書き換えた場合は原則プログラムの再起動が必要となる。またPythonの様な言語ではソースコードを再読み込みする処理を予め書き換えたい処理の呼び出し元に組み込んでおかなければソースコードをいくら書き換えても動作に反映できない。Smalltalkではその再起動や再読み込み処理の組み込みが必要ない。このため環境をソースコードを書き換える都度環境全体を再起動しなくて済むのはもちろん、Windowを表示するプログラムを作った場合であれば、Window内のButtonの動作を変更する時もWindowを表示したままソースコードを書き換えて動作を変更できる。このためButtonを押すまでに複数の手順が必要なプログラムやWindowの表示に時間がかかるプログラムでもButtonを表示した状態から再起動せず何度でもやり直しができ効率的なソースコード変更が可能になっている。
Smalltalk 環境から見た Smalltalk 言語は、いわば bash などのシェルに近い。Smalltalk 環境内であればどこでもマウスで選択した文字列を Smalltalk のソースコードとして実行できるためシェルにコマンドを打ち込んだ時の様に簡単な問い合わせをすぐ実行できるようになっている。
例えばオブジェクト(クラスやメソッドも含む)の構造を調べたければ、そのオブジェクトに#browse()セレクターあるいは#inspect()セレクターを使ったメッセージ式を書き、そのメッセージ式をマウスで選択してdo it(WindowsであればCtrl+Dを押す)すれば良い。
また、設定値の指定に Smalltalk 言語のメッセージ式が使われる。現在設定されている値がメッセージ式として取得でき、値の設定をメッセージ式として指定する。この設定値を指定するメッセージ式は Smalltalk 環境の実行中に設定用のウィンドウから入力される。