Smalltalk-72で学ぶOOPの原点:Rubyのinstance_eval相当の「's」
アラン・ケイの“オブジェクト指向”というアイデアをもとに(非同期処理などいろいろ足りていないながらも──)比較的忠実に実装された1970年代の非常に古いSmalltalk-72で遊んでみるシリーズです(なお最新のSmalltalkについては Pharo などでお楽しみください!)。他の記事はこちらから→Smalltalk-72で学ぶOOPの原点 Advent Calendar 2019 - Qiita
's
でオブジェクトの中身を直接いじる
すでに何度か触れたり、エディターのソースにも出てきた's
は、それに続くメッセージとして送られる「括弧でくくられたコード(ある意味で“ブロック”)」をレシーバーのコンテキストで実行する振る舞いをさせるときに使う(ことになっている)記号です。
ただ、これもやはり既に述べたとおり、継承の無いSmalltalk-72ではObject
に代表される基底クラスに定義された“デフォルトの振る舞い”などというものは期待できないので、自作のクラス(に限らず、それが期待される全てのクラス)にはそうした振る舞いをさせたい旨の記述をいちいちしておく必要があります。
試しに、インスタンス変数iv
を持つクラスfoo
について、通常どおりiv ← <値>
というメッセージを送るのとは別に、's
で直接値を変更することも可能なように定義してみましょう。
インスタンス変数はクラス名の後に(一時変数宣言と区別するために──):
(コロン)で区切りを入れてから宣言します。アクセッサーのパターンマッチコード片は「iv
というメッセージを受け取ったら(∢iv⇒(
)、続くメッセージが←
なら(∢←(
)、さらにそれに続くメッセージを評価してiv
に代入してからその値を返し(⇑:iv)
)、そうでなければ単純にiv
を返す(⇑iv)
)」と記述します。
一方、's
のパターンマッチコード片はALLDEFSに何度も現れる決まり文句ならぬ“お決まりのコード片”のとおり「∢'s⇒(⇑⦂ eval)
」です。⦂
は続くメッセージとして与えられたトークン(配列ならトークン列)を評価せずにトークンのまま取り込むアクションで、したがって⇑⦂ eval
は取り込んだ配列を自分のコンテキストで評価(eval
)して返す(⇑
)ことを意味します。
's
という一文字の記号は、ちょい直し版でのみ入力可能で、「KeyboardHelp」にあるとおり ctrl+shift+s か、あるいはブラウザなどの都合で同キーアサインが使用できない場合は「|」をタイプすることでも入力できます(ちょい直し版は、ドキュメント通りの ctrl+shift+s が機能するようにすると同時に、代替キーアサインの追加もしています)。
x
にfoo
のインスタンスを代入し、アクセッサーの動作を確認します。
この状態でインスタンス変数iv
には3
が代入されているわけですが、これを's
を使って直接4
に書き換えてから、あらためてアクセスしてみましょう。
's
や⦂
が入力できないときの代替策
's
が入力できなくても、たとえばss
など適当なメッセージに応答して同じ振る舞いをするように記述すればよいわけですが、ただ、⦂
が入力できないと件のお決まりのコード片である「∢ss⇒(⇑⦂ eval)
」が記述できずそこで困ってしまいます。改めて⦂
アクションの定義をALLDEFSで探すと次のように(プリミティブCODE 36
を呼んでこそいますが──)「(:☞)
と等価である」と分かります。
したがって、's
の代替を⦂
を使わずに書くと∢ss ⇒(⇑(:☞) eval)
と書くことができ、既存のクラスにもaddto
アクションを使うか、edit
の「Add」等で追加できます。
それでも's
が入力できないと、そのうち不可能なこともなにかと出てきて不便なので、なんとか's
を入力できるようにした件の「ちょい直し版」を作ったというわけです。