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の引数部分は遅延評価されるのかな。特殊形式なのかな?