Smalltalk-72で学ぶOOPの原点:配列要素の参照と要素の代入

アラン・ケイの“オブジェクト指向”というアイデアをもとに(非同期処理などいろいろ足りていないながらも──)比較的忠実に実装された1970年代の非常に古いSmalltalk-72で遊んでみるシリーズです(なお最新のSmalltalkについては Pharo などでお楽しみください!)。他の記事はこちらから→Smalltalk-72で学ぶOOPの原点 Advent Calendar 2019 - Qiita


LivelyWeb版Smalltalk-72についてからの続き)

配列オブジェクトの生成

Smalltalk-72にも今のSmalltalkや他の一般的な言語同様に動的な配列生成式が書けますが、要素がすべてリテラルならリテラル配列式で生成するのが簡単です。今のSmalltalkは #(1 2 3 4) のように括弧の前に「#」を使いますが、Smalltalk-72 では「☞」(右方向指さしマーク)を代わりに用います。入力はKeyboardHelpにもあるように「"(ダブルクオーテーション)」です。評価の際に do-it (グリフは「!」、キーは「\」)の入力をお忘れなく。

f:id:sumim:20191203101116p:plain
リテラル配列式

今のSmalltalkと同様に、リテラル配列式の場合、変数による参照も含めて式による要素の動的生成はサポートしていない(もっとも、最近のSmalltalkは擬変数「true」「false」「nil」については便宜上例外的にリテラル扱いにしていますが──)ので、要素を生成する式のようなつもりで計算式を混ぜても、式のトークンが要素になるだけなので注意してください。

f:id:sumim:20191203102117p:plain
リテラル配列式の要素はリテラルだけなので注意(式を書いても評価はされず、式の各トークンを要素とする配列になる)

もし、式を用いて要素を動的に生成したい場合は、今のSmalltalkと同じように { } でくくる、配列の動的生成式を使います。ただし、今のSmalltalkは式の区切り(つまり要素ごと)に、式の区切りである「.」(ピリオド)を、一般的な言語では「,」(カンマ)が必須なのに対し、Smalltalk-72ではこうした式の区切りは無用です。

f:id:sumim:20191203103018p:plain
配列の動的生成

面白いのは式(要素)の区切りが“不要”(あってもなくてもよい)なのではなく“無用”(あってはいけない)である点です。どこが式(要素)の区切りになるかは、要素を生成する各メッセージ式のレシーバー(メッセージの受け手であるオブジェクト)により動的に判断されます。うっかりいつもの習慣でピリオドやカンマなどを入れてしまうとエラーになるので注意してください。

f:id:sumim:20191203103402p:plain
動的配列生成式にピリオドを入れてしまったときのエラー

なお、エラーが出たときにポップアップするサブウインドウ(REPL)は done と入力して評価(「\」をタイプ)すると消すことができ、元のウインドウに復帰できます。

f:id:sumim:20191203103709p:plain
エラー時REPLからの復帰(done を入力して評価)

f:id:sumim:20191203103856p:plain
エラーからの復帰後(エラーを起こした直前の式の評価はキャンセルされる)

追記:要素を区切りを明示的にするには、{1 (2+3) 4}のように要素を生成する式ごとに()で括ってやればよいようです。

変数への代入

変数への代入は、今のSmalltalkRubyなどのシンボルに似た扱いのアトムへの「← 値」というメッセージ送信で行われます。アトムの生成も配列のリテラル式同様「☞」を使って表現します。古典的Smalltalk-80やSqueakの初期にも使われていた代入記号「←」は「_」で入力できます。

f:id:sumim:20191203112826p:plain
変数への代入

なお、この図の最初の式のようにREPLで評価する式の最後にピリオドを追加しておけば、評価時に最後の式の値の出力をいちいちしなように抑制することも可能です。ちなみに、次の世代のSmalltalk-76の doIt(今のSmalltalkの print it に相当)もこれと同じ運用になっていましたが、Smalltalk-80以降の今のSmalltalkでは末尾のピリオドの有無にかかわらず最後の式の結果が戻り値(print it なら出力値)になるように変更されています。

配列要素の参照

配列の要素の参照は arr[3] のように記述します。

f:id:sumim:20191203114136p:plain
配列要素の参照

省コスト版のメッセージング機構を採用した次の世代のSmalltalk-76の arr ◦ 3 や、今のSmalltalkの arr at: 3 とはずいぶんと様子が違って、一般の言語に近い表現になっているのが面白いですね。

配列要素の代入

配列の要素の代入は arr[3] ← 4.56 のように記述します。

f:id:sumim:20191203114716p:plain
配列要素の代入とその結果の確認

こちらも次世代のSmalltalk-76の arr ◦ 3 ← 4.56 や、今のSmalltalkの arr at: 3 put: 4.56 とは違いますね。Rubyの arr[2] = 4.56 とは見た目は似ていますが、しかし、Smalltalk-76では ◦← 、今のSmalltalkでは at:put: 、そしてRubyでは []= というメソッド(ある種の関数)を定義してそれを使っているのに対し、Smalltalk-72では別のアプローチをとっています。

配列要素の参照と要素の代入の実装へ続く)