第5回Smalltalk勉強会に行ってきました。
制御構造を自分で作ってみるというのが今回のテーマでした。
僕はまだまだ Smalltalk のスキルが足りてないので、if 文を書いてみたり Smalltalk のソースを読んだりしてました。
他の人は GOTO っぽいものを実現したり、C の for 文みたいなものを作ったり(continue も break もある!)してました。
Smalltalk の if 文の書き方がなかなかおもしろくて、例えば以下のような Ruby コードが、
if a > 0 ごにょごにょ end
Smalltalk では以下のような感じになります。
(a > 0) ifTrue: [ ごにょごにょ ]
(a > 0) の結果は True クラスもしくは False クラスのインスタンスになります。
あと、Smalltalk では [ 〜 ] がブロックの定義で、引数をとる場合は [:foo | 〜 ] というふうに書きます。
True クラスと False クラスには ifTrue: というメソッドが定義されていて、それぞれ以下のような実装になっています。
True ifTrue:
ifTrue: alternativeBlock ^alternativeBlock value
False ifTrue:
ifTrue: alternativeBlock ^nil
ブロックの value メソッドを呼ぶとそのブロックが評価されます。
Ruby の Proc#call みたいなものだと思います。
True ifTrue: は引数として渡されたブロックを評価し、False ifFalse: は何もせずに nil を返すだけです。
非常に単純ですね!
Smalltalk で「if 〜 else 〜 」みたいなコードを書きたいときは ifTrue: ifFalse: メソッドを使います。
例えば以下のような感じになります。
(a > 10) ifTrue: [ ごにょ ] ifFalse: [ にょご ]
実装はそれぞれ以下のようになっています。
True ifTrue: ifFalse:
ifTrue: trueAlternativeBlock ifFalse: falseAlternativeBlock ^trueAlternativeBlock value
False ifTrue: ifFalse:
ifTrue: trueAlternativeBlock ifFalse: falseAlternativeBlock ^falseAlternativeBlock value
これも非常に単純ですね!
他にも and: や or: といったメソッドがあって、これを使うと Ruby みたいな if 文が書けます。
(a > 1 and: [a < 4]) ifTrue: [ Dialog warn: '1 < a < 4'. ]
and: の実装は True クラスと False クラスでそれぞれ以下のようになっています。
True and:
and: alternativeBlock ^alternativeBlock value
False and:
and: alternativeBlock ^self
また、or: の実装は以下のようになってます。
True or:
and: alternativeBlock ^self
False and:
and: alternativeBlock ^alternativeBlock value
あ、そうだ、Smalltalk では ^ が Ruby でいうところの return を意味します。
あとは、Collection クラスもなかなか面白いです。
do: メソッドが Ruby の each に相当する感じですかね。
コレクションを普通にループしたい場合は以下のようにします。
|collection| collection := OrderedCollection new. collection add: 'foo'. collection add: 'bar'. collection add: 'jugyo'. collection do: [:each| Dialog warn: each. ]
Ruby っぽいですね!
というか逆で、Ruby が Smalltalk っぽいんですね。
Collection クラスには collect: や select:、inject: なんかもありますよ。

