アラン・ケイの“メッセージングによるプログラミング”という着想に基づき(非同期処理などいろいろ足りていないながらも──)比較的忠実に実装された1970年代の非常に古いSmalltalk-72に実際に触れてみるシリーズ 第2弾です(なお最新のSmalltalkについては Pharo などでお楽しみください!)。
今回は謎言語「Smalltalk-71」で書かれたスペースウォー・ゲームを Smalltalk-72に移植して動かすことを目指します。前回(2019年)を含む他の記事はこちらから→Smalltalk-72で遊ぶOOPの原点 | Advent Calendar 2023 - Qiita
sqrt
アクションを定義する
これで準備が整いましたので sqrt
をニュートン法でサクッと実装してしまいましょう。
to sqrt x y z ( 0.0 > :x ? (error) 0.0 = x ? (!0) "y _ 1.0 * x. "z _ 1.0e`8 * x. repeat (z > y - "y _ y - ((y * y) - x) / y * 2 ? (done)). x is float ? (!y) z > abs y - "x _ 1 * y + z ? (!x) !y)
まず、テンポラリ変数として x
y
z
を冒頭で宣言します。
メッセージとして送られた数値(入力値)を x
にフェッチしつつ負ならばエラー(0.0 > :x ⇒ (error)
)、ゼロなら 0
を返します(0.0 = x ⇒ (⇑0)
)。
次に入力値 x
を 1.0
にかけることで(たとえ整数であった場合でも) float
に変換し、y
に代入します。Smalltalk-72 では代入も ☞y
の返値であるアトム(シンボルの実体)へのメッセージ ← 1.0 * x
の送信です。
z
には許容する誤差として、さしあたり入力値の 108 分の1くらいにしました。
あとは y
と y - (y^2 - x) / 2y
の差の絶対値(前回定義した abs
アクションを使用)が z
より小さくなるまで繰り返せば平方根が求まります(repeat (z > y - ☞y ← y - ((y * y) - x) / y * 2 ⇒ (done)).
)。
注意する点は、まず、演算が右結合なので必要なら括弧を適切に使用することです。乗除優先でないことを意識して括弧を用いる点は Smalltalk-80 でも同じですが、右結合か左結合かの違いがあるので、Smalltalkをよく知ってる場合でも要注意です^^;
そして、浮動小数点数と整数との演算で浮動小数点数を返したいときは、整数がレシーバーにならないようにする(交換則が成り立つならメッセージ側に移動、もしくは、今回は該当しませんがそうできない場合は -
アクションのように、あらかじめ整数を 0.0
に足したり 1.0
にかけるなどして浮動小数点数に変換しておく)ことです。
最後は、送られてきた数値が float
なら結果をそのまま返し(x is float ⇒ (⇑y)
)、結果が整数に近い値なら整数として返す(z > abs y - ☞x ← 1 * y + z ⇒ (⇑x) ⇑y
)という余計で汚い処理(^^;)を付け加えています。
(「spaceship」を解析するへ続く)