Smalltalk-72で学ぶOOPの原点:条件分岐以外の制御構造

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


条件分岐式についてもう少しからの続き)

Smalltalk-72のforループ

いわゆるforループは for <変数名> ← <開始値> to <終了値> by <差分> do (<処理>) のように書きますが、条件分岐が 'if' アクション(オブジェクト)へのメッセージ送信で実現されているのと同様に、もちろん for アクションへのそれで実現されています。

f:id:sumim:20191206095310p:plain
典型的なforループの記述と実行

例によって完全な仕様は ALLDEFS(ブートストラップコード)で for アクションの定義を読むのが手っ取り早いです。

f:id:sumim:20191206095529p:plain
ALLDEFSの「for」アクションの定義

  • for アクションの定義( to for …
  • token step stop var start exp という一時変数の宣言
  • まず、メッセージの最初のトークンを評価せずにそのまま var に取り込む( :☞var.
  • 続くメッセージで がマッチしたら、メッセージの続きを式として評価して start に取り込む( ∢← ⇒ (:start.)
  • そうでなければ、start の値は 1 に( ☞start ← 1
  • 続くメッセージで to がマッチしたら、メッセージの続きを式として評価して stop に取り込む( ∢to ⇒ (:stop.)
  • そうでなければ、stop の値は start と同じ値に( ☞stop ← start.
  • 続くメッセージで by がマッチしたら、メッセージの続きを式として評価して step に取り込む( ∢by ⇒ (:step.)
  • そうでなければ、step の値は 1 に( ☞step ← 1.
  • 続くメッセージでdo がマッチしたら、その参照を exp に取り込みプリミティブCODE 24をコール( ∢do ⇒ (:#exp. CODE 24)

差分はもちろん、初期値も終了値すらも省略可能である仕組みがよく分かって面白いですね。なお、プリミティブ CODE 24 は、一時変数を取り込んで実質的なforループ処理を実行します。コメントにもあるように後述のdone(中断して抜ける)やagain(中断して次の回の処理を実行)も使えます。

その他のループ

forループの他にも、単純なループのrepeat(停止するときは esc キーを押す)や

f:id:sumim:20191206102542p:plain
repeatループ(マウスポインタの位置「mx」「my」をタートル「😄」に追従させる)

今のSmalltalktimesRepeat:Rubytimesにあたるdoもあります。ただし、今のSmalltalkRubyが整数にメッセージを送る(体になっている──)のに対し、Smalltalk-72ではdo自身がループ回数を表す整数を含めたメッセージの受け手になっていて、結果、記述順が異なるので要注意です。

f:id:sumim:20191206103651p:plain
タートル「😄」に「100進んで右に90度向きを変える」を3回繰り返させる

doneagain

doneはループを中断して抜けるアクションです。with <値> で、ループを抜けたときの返値を指定することもできます。

f:id:sumim:20191206135255p:plain
「done」で値を指定してループを抜ける

againRubyでいうところの(redoではなく)next の役割を持つアクションのようです。

f:id:sumim:20191206114246p:plain
ループ中での「again」の挙動

文字列操作…の前にクラス定義についてに続く)