https://github.com/takeisa/uschemer/tree/v0.11
各式の仕様
and式
(and e1 e2 ... en)式e1からenまで順に評価し、すべてが真の場合は、最後の式enの値を返す。
いずれかが偽の場合は falseを返す。
or式
(or e1 e2 ... en)式e1からenまで順に評価し、真となった値を返す。
すべてが偽の場合は falseを返す。
not式
(not e)式eが真の場合は falseを返す。
式eが偽の場合は trueを返す。
評価部分のコード
実装は仕様そのままで簡単だ。and式の評価
def eval_and(exp, env)exp_list = and_to_exp_list(exp)
last_exp = nil
exp_list.each do |exp|
last_exp = eval(exp, env)
return false unless last_exp
end
last_exp
end
def and_to_exp_list(exp)
exp[1..-1]
end
or式の評価
def eval_or(exp, env)exp_list = or_to_exp_list(exp)
exp_list.each do |exp|
last_exp = eval(exp, env)
return last_exp if last_exp
end
false
end
def or_to_exp_list(exp)
exp[1..-1]
end
not式の評価
def eval_not(exp, env)exp = not_to_exp(exp)
not eval(exp, env)
end
def not_to_exp(exp)
exp[1]
end
リファクタリング
式の種別に応じて、対応する評価メソッドを呼び出す部分は以下の通り。def eval_special_form(exp, env)
if lambda?(exp) then
eval_lambda(exp, env)
elsif let?(exp) then
eval_let(exp, env)
elsif if?(exp) then
eval_if(exp, env)
elsif letrec?(exp) then
eval_letrec(exp, env)
elsif define?(exp) then
eval_define(exp, env)
elsif cond?(exp) then
eval_cond(exp, env)
elsif and?(exp) then
eval_and(exp, env)
elsif or?(exp) then
eval_or(exp, env)
elsif not?(exp) then
eval_not(exp, env)
end
end
うーむ。汚ないコードだ。リファクタリングしたい。
Strategyパターンを適用して、それぞれのスペシャルフォームをクラス化すると、すっきりするかな?
0 件のコメント:
コメントを投稿