2008-10-20
■ [ruby] Rubyで広がる日本語DSLの世界!!
Rubyを使って自然言語(というか英語)っぽい記述を行うライブラリといえばRSpecがまず例に上がるんですけど、 最近はもう英語に近くなりすぎて、日本人にとっては逆に使いにくくなっているんじゃないかという気がするんですよ。
このままでは英語圏と日本人のプログラマの生産性の格差は高まるばかり、 ていうか正直に言って英語ばっかりずるい、ここは一つ日本語を生かしたコード、日本語DSLの登場が待ち望まれているのではないか。 以下「それなでしこでできるよ」禁止。
というわけで妄想してみました、日本語でBDDを行うライブラリ、その名も「Japanespec」。
require 'japanespec'
include Japanespec
"Ruby".の 仕様{
# ==
Math.sqrt(4).は 2.に なる #案1
Math.sqrt(4).は 3.に ならない
Math.sqrt(4).は 2, である #案2
Math.sqrt(4).は 3, ではない
# be
[1,2,3].include?(3).は 正しい # be_true
[1,2,3].include?(4).は 正しくない # be_false
[].first.は nil.に なる # be_nil
[1].first.は nil.に ならない # not be_nil
# equal?
5.は 5.と 同一である
"5".は "5".と 同一ではない
# should change
obj = 1
lambda{ }.は obj.の :prop.を 変える
lambda{ }.は obj.の :prop.を 1.から 2.に 変える
# has, include
ary = [1,2,3]
ary.は 2.を 含む
ary.は 3.個の :item, を持つ
ary.は 3.個以上の :item, を持つ
ary.は 3.個未満の :item, を持つ
# respond_to
ary.は :size, :length, に応答する
# raise
lambda{ }.は 例外 を投げる
lambda{ }.は 例外 ArgumentError, を投げる
lambda{ }.は 例外 ArgumentError, "foobar", を投げる
# match
str = "abcde"
str.は /abc/.に マッチする
# satisfy
obj = 1
obj.は {|o| o<3 and o%3 == 1 }.を 満たす
}
どうでしょうか?
まだ中身の実装はしてないんですけど、恐ろしいことにこれ、ちゃんとパーズが通ります。ソースはgithub。
暇な人は冬休みの課題として実装してみるといいよ!
テクニカルなこと
以下、Rubyで日本語DSLを設計する際の注意点など。
まず、Ruby 1.8だとwarning出まくるんで1.9でやりましょう。1行目の「# coding: utf-8」も忘れずに。
上のソースがどのように解釈されるかですが、一つだけ例を挙げると
str.は /abc/.に マッチする
というコード(コードですよ)は、
str.は(/abc/.に(マッチする))
と解釈されます。より分かりやすく書き換えると、
str.foo(/abc/.bar baz())
ということ。foo, bar, bazというメソッドの呼び出しがネストしてるわけです。日本語版ではそれぞれ「String#は」、「Regexp#に」、「Japanespec#マッチする」ね。 こんな感じで、
obj.foo bar baz
のようにメソッドや関数を並べるのがRubyによる日本語DSLの定石です。
ちょっと凝ったことをしたいときには、つい
foo(bar, 3) baz
みたいにカッコを使いたくなりますが、これはパースエラーになってしまいます。 「あれ、fooがProcオブジェクトを返したらいけるんじゃね?」と思ったあなたはScheme脳(もしくはHaskell脳)(もしくはPython脳)で、 Procオブジェクトを実行するには
foo(bar, 3).call baz foo(bar, 3)[baz]
のようにcallか[]が必要です。まあcallは論外ですが[]も記号だらけになってあんまりよろしくないですね。
なのであり得る形としては、
a.foo b.bar baz, 3
のように一番右のメソッド呼び出しだけ引数をカンマで区切るくらいかと思われます。 もっとクール(笑)な書き方を見つけた方はご一報ください。
Proc#callの別名として<br>Proc#は<br>Proc#の<br>Proc#みたいな<br>とかを作るのはどうかlang:ja
例えば(ary.は 3.個以上の(:item).を 持つ).みたいな? "これはすごい"
ケータイ小説プログラミングの予感!
あたし 彼女.スイーツ(笑)