その他の「+」、「*」、「/」関数も同様に対応させた。
https://github.com/takeisa/uschemer/tree/v0.10
四則演算部分のコード
FUNCS = {:+ => [:primitive, lambda {|*xs| xs.reduce(0) {|a, x| a + x}}],
:- => [:primitive, lambda {|*xs| if xs.size == 1 then -xs[0] else xs.reduce {|a, x| a - x} end}],
:* => [:primitive, lambda {|*xs| xs.reduce(1) {|a, x| a * x}}],
:'/' => [:primitive, lambda {|*xs| if xs.size == 1 then 1 / xs[0] else xs.reduce {|a, x| a / x} end}],
..snip..
}
RSpecでテストファースト
コードが増えてくると、機能の追加や修正で、デグレしやすくなる。今回からRubyのテスティングフレームワークであるRSpecを使い、テストファーストで実装した。
以下は「+」関数のテストケース。
結構、分かりやすいコードになる。
describe '+ operator' do
before do
@env = [USchemeR::KEYWORDS, USchemeR::FUNCS]
end
context 'one parameter' do
it { eval("(+ 1)", @env).should eq 1 }
end
context 'two parameters' do
it { eval("(+ 1 2)", @env).should eq 3 }
end
context 'many parameters' do
it { eval("(+ 1 2 3 4 5)", @env).should eq 15 }
end
end
テストファーストで実装すると、NGだったテストがOKになるときに、気持ち良さがあり、ちょっとしたコードの実装でも、なかなか楽しい。
本当は、このような上位レベルのテストコードにするのではなく、NGになったときに、原因が明確になるように、機能の対象となる部分のテストコードを書くべきなんだろうけど、まずはこれで良しとしよう。
参考
Rubyist Magazine 改めて学ぶ RSpecとても分かり易くまとまっているのでおすすめ。
0 件のコメント:
コメントを投稿