DSL
2008年04月26日
本日、Ruby勉強会@札幌-8に行ってきた。私は初めての勉強会参加だった。
本日のトピックは上記リンクを参照いただくとして、今日扱われた言語はRubyのみならずPythonやSmalltalkなどにも及び、濃密な1日になった。
特に気に入ったのは、島田さんによる、RubyでDSLを作成するというもの。DSL(Domain Specific Language:ドメイン特化言語)とは、特定の用途の文言を容易に記述するための言語であり、RubyではRSpecやRuby on Railsがこれに当てはまるようである。さてRSpecを例にとると、RSpecのスペックファイルには、実際に使われるプログラムが満たすべき条件が記述される。その際にスペックファイルには例えば
# multiset.rbに対するスペックファイルより lambda{ Multiset.parse("hoge\npiyo\n") }.should raise_error(ArgumentError)
のような書き方をする。これは見ての通りなのだが、「lambda{ ... }の内容がエラーを起こすべき(should raise_error)」という内容を示している。Rubyはこのような「見ての通り」の書き方が出来るようにクラスやメソッドを定義するのが得意なので、それを利用してDSLを作るというものであった。
さて、そのようなRubyの性質が面白いと思い、試しに世界のナベアツプログラムをDSL的に書いてみた。
require "nabeatsu" # 後述
nabeatsu = Nabeatsu.new
nabeatsu.status "アホ", :rule => [3.no_baisu_no_toki, 3.no_tsuku_toki]
nabeatsu.status "犬", :rule => 5.no_baisu_no_toki
nabeatsu.say 1..40 do |number, status|
if status
print "#{number}(#{status.join(' ')})"
else
print number
end
print " "
end
puts
これを実行すると
1 2 3(アホ) 4 5(犬) 6(アホ) 7 8 9(アホ) 10(犬) 11 12(アホ) 13(アホ) 14 15(アホ 犬) 16 17 18(アホ) 19 20(犬) 21(アホ) 22 23(アホ) 24(アホ) 25(犬) 26 27(アホ) 28 29 30(アホ 犬) 31(アホ) 32(アホ) 33(アホ) 34(アホ) 35(アホ 犬) 36(アホ) 37(アホ) 38(アホ) 39(アホ) 40(犬)
のように、上記のプログラムで指定した通り「3の倍数と3のつくときは"アホ"」「5の倍数のときは"犬"」が表示される。
このnabeatsu.rbの内容はここで公開しています。 世界のナベアツプログラム on Ruby
※この手の問題、一般にはFizzBuzzと言われているそう。