こんにちは、@tomoodaです。
今まで書きたいことは基本的にtwitterに書いていましたが、やっぱり文字数制限がつらい。ツ コード例とか書くだけでももう大変。それがブログなら
(PGeneGenerator
on: [ :g |
| i j |
i := 0.
g yield: i.
j := 1.
g yield: j.
[
i + j
=>> [ :k |
g yield: k.
i := j.
j := k ] ] repeat ])
=>> [ :fibonacci |
10
timesRepeat: [
Transcript
cr;
show: fibonacci next printString ] ]
がはははは、余裕で書き下せるぜい!勝ったも同然。なお、上記のコードはPharoというSmalltalk処理系でフィボナッチ数列を10個、トランスクリプトウィンドウに表示します。
Smalltalkerにも見慣れないモノがあると思いますが、これは開発中のPGeneというライブラリが実装するジェネレータPGeneGeneratorの例題です。Pythonのジェネレータがあまりにも便利なので、ついSmalltalk上で実装しちゃいました。
Smalltalkには昔からStreamクラスがあり、nextメッセージを投げる毎に次の値を返してくるのですが、いかんせん数列を定義する度にクラスを定義したのでは、「だからクラスベースは…」などと言われてしまいます。
また、Smalltalkには昔からdo:メッセージもあり、クロージャを渡して繰り返し評価をします。しかし悲しいかな、do:はファーストクラスオブジェクトではないのです。複数のオブジェクトから次から次へとnextメッセージを投げるような自由度はありません。
そこでジェネレータです。nextメッセージを受け取ったら、クロージャ[:g | ... ]を評価します。そして、クロージャを評価していく中で、使いたい値が手に入ったらいつでもyield:メッセージを投げれば、その引数がnextメッセージの返り値となります。また、次にnextメッセージを受け取ったら、前回yield:した箇所から実行を再開して、次のyield:がnextの返り値になります。まあ、なんて便利なんでしょう。ツ このように2つの実行コンテキストを交互に継続させることをコルーチンといいます。
Smalltalkは実行コンテキストまでファーストクラスオブジェクトなので、この程度のことはフフンのフンなのです。ツ
次に見慣れない表記は=>>でしょう。一般には、expr =>> [ :name | ... ]という形で使って、exprの評価結果にnameという名前をつけて、...を評価します。これがあると何が嬉しいかと言うと、自然とローカルなスコープになるだけでなく、破壊代入と名前束縛を明示的に分離できるのが最大の利点です。Smalltalkは関数型言語でも論理型言語でもないので、破壊代入は悪ではありません。しかし、濫用せずに、弊害を最小化しながらそのメリットを享受しようじゃないですか。ツ ちなみに、実装としては=>>の左側のオブジェクトを引数にして右側のクロージャを評価しているだけです。
こんな調子で、Smalltalkのこと、オブジェクト指向のこと、プログラミングのこと、その他いろいろ書いていきます。
よろしく! ツ
0 件のコメント:
コメントを投稿