IokeでFizzBuzz

Ioke を使ってみるよ。

前回は Iokeを入れてみた - paz3のおもいつき 。さて、次に何をしようかと考えて、とりあえず FizzBuzz を作ってみた。

fizzbuzz.ik:

FizzBuzz = Origin mimic
FizzBuzz count_to = method(max, (1..max) asList map(n, num_to_str(n)))
FizzBuzz num_to_str = method(n, str_or_num(fizz(n) + buzz(n), n))
FizzBuzz str_or_num = method(s, n, if(s != "", s, n asText))
FizzBuzz fizz = method(n, if(n % 3 == 0, "Fizz", ""))
FizzBuzz buzz = method(n, if(n % 5 == 0, "Buzz", ""))

FizzBuzz count_to(50) println

実行結果はこれ。

C:\Documents and Settings\paz\My Documents\program\ioke>ioke fizzbuzz.ik
[1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz, 16, 17
, Fizz, 19, Buzz, Fizz, 22, 23, Fizz, Buzz, 26, Fizz, 28, 29, FizzBuzz, 31, 32,
Fizz, 34, Buzz, Fizz, 37, 38, Fizz, Buzz, 41, Fizz, 43, 44, FizzBuzz, 46, 47, Fi
zz, 49, Buzz]

C:\Documents and Settings\paz\My Documents\program\ioke>

プログラムは、まずmimicメッセージでルートオブジェクトのコピーを作成し、methodでメソッドを作ってcount_toなどの各セルに代入してる。今回は大きなメソッドを作らず細かいメソッドに分けてみた(もっと効率のよい書き方があるのかもしれないけど、よくわかってない)。

fizzメソッドは3の倍数のときに“Fizz”を返す。buzzメソッドは5の倍数のときに“Buzz”を返す。num_to_strでfizzとbuzzを連結して、もしfizzでもbuzzでもないときはstr_or_numで数字が返る。

“n asText”はnにasTextメッセージを送って文字列にしてる。激しくSmalltalk的。本当はifも

(n % 3 == 0) ifTrue("Fizz") ifFalse("")

のようにメッセージで書ける。書けるけど、これだと“Fizz”とかは返ってこなくって、trueとかfalseが返ってくる(そしてtrueと文字列を+するところでエラーになる)。

引数と内容をコンマで区切るとか、すごくシンプルにプログラムが書けるのに感激! かなり好みのタイプ。しかもJavaのライブラリが使えるから実用性も十分。これで起動時間がもうちょっと短ければ(&Windows環境で対話的に使えれば)もっと良いのになぁ。

<追記>

(n % 3 == 0) ifTrue("Fizz") ifFalse("")で文字列ではなくBooleanが返ってくる理由がなんとなくわかった。

これは“ifTrue ifFalse”というシグニチャではなく、BooleanにifTrueメッセージを送ると再びBooleanが返ってくるので、それに対してifFalseメッセージを送っているのだと思う。

っていうか、ガイドに「these conditionals can not return any value」と書いてあったよ… orz

ifTrue/ifFalseの引数部分は遅延評価されるのかな。特殊形式なのかな?