2013年5月8日水曜日

[Ruby][Scheme] Micro Schemeの実装(3) let式の評価

let式を扱えるようにした。
https://github.com/takeisa/uschemer/tree/v0.03

lambda式への変換

let式の束縛リストに定義した環境で本体を評価すれば良いので、以下のようにlambda式に変換する。

(let 束縛リスト 本体)

((lambda 仮引数リスト 本体) 引数)

let式を使って作成したクロージャをlambda式に変換する例

(let ((a 1) (b 2))
     (lambda (x) (+ a b x)))

((lambda (a b)
     (lambda (x) (+ a b x))
) 1 2)

処理手順

  1. let式か判定する。
  2. let式の場合は、上記のルールでlambda式に変換する。
  3. 変換後の式を再評価する。

実行例

eval_print([:let, [[:a, 1], [:b, 2]], [:+, :a, :b]], env)
[:let, [[:a, 1], [:b, 2]], [:+, :a, :b]] #=> 3

eval_print([:let, [[:a, 1]], [:lambda, [:x], [:+, :a, :x]]], env)
[:let, [[:a, 1]], [:lambda, [:x], [:+, :a, :x]]] #=> [:closure,
 [:x],
 [:+, :a, :x],
 [{:a=>1},
  {:+=>[:built_in, #<Proc:0x9d4bbe8@uschemer.rb:6 (lambda)>],
   :-=>[:built_in, #<Proc:0x9d4bbc0@uschemer.rb:7 (lambda)>],
   :*=>[:built_in, #<Proc:0x9d4bb98@uschemer.rb:8 (lambda)>],
   :/=>[:built_in, #<Proc:0x9d4bb70@uschemer.rb:9 (lambda)>]}]]

eval_print([[:let, [[:a, 1]], [:lambda, [:x], [:+, :a, :x]]], 2], env)
[[:let, [[:a, 1]], [:lambda, [:x], [:+, :a, :x]]], 2] #=> 3