https://github.com/takeisa/uschemer/tree/v0.07
defineの構文
以下の二つの構文に対応する。(1)第一引数に変数、第二引数に値を指定する形式
(define id (lambda (x) ...))
(2)第一引数に関数名と仮引数のリスト、第二引数に関数本体を指定する形式
(define (id x) (...))
変数と値の束縛
変数をdefineで定義する際に、変数が束縛されているかどうかによって、以下のように処理する。(1)束縛されている場合
束縛されている変数の値をdefineで指定した値に設定する。
(2)束縛されていない場合
defineで指定した変数と値の束縛を環境に作る。
(1)と(2)のどちらにも対応するというのが嫌な仕様だな。
例えば、
(define fuga ...) ...(a)
(define hoge ...
(define fuga ...)) ...(b)
この場合、(b)のdefineは、(a)でfugaが定義されているため、上書きされる。
(a)がなければ、hoge内のローカルとなる。
ということは、ローカルのつもりで変数を定義していても、間違って外側でdefineしてしまうと、そちらを参照してしまい、良く分からないバグの原因になりそうだ。
そもそも、defineはこの仕様で正しいのかな?
実行例
フィボナッチ数を求める関数を定義してみた。(define (fib n)
(if (<= n 2)
1
(+ (fib (- n 2)) (fib (- n 1)))))
#=> [:fib,
[:closure,
[:n],
[:if, [:<=, :n, 2], 1, [:+, [:fib, [:-, :n, 2]], [:fib, [:-, :n, 1]]]],
[{:fib=>[...]},
{:fact=>
[:closure,
[:n],
[:if, [:"=", :n, 0], 1, [:*, :n, [:fact, [:-, :n, 1]]]],
[...]]},
{:one=>1},
{:true=>true, :false=>false},
{:+=>[:built_in, #<Proc:0x931b574@uschemer.rb:8 (lambda)>],
:-=>[:built_in, #<Proc:0x931b54c@uschemer.rb:9 (lambda)>],
:*=>[:built_in, #<Proc:0x931b4fc@uschemer.rb:10 (lambda)>],
:/=>[:built_in, #<Proc:0x931b4d4@uschemer.rb:11 (lambda)>],
:"="=>[:built_in, #<Proc:0x931b4ac@uschemer.rb:12 (lambda)>],
:<=>[:built_in, #<Proc:0x931b484@uschemer.rb:13 (lambda)>],
:>=>[:built_in, #<Proc:0x931b45c@uschemer.rb:14 (lambda)>],
:<==>[:built_in, #<Proc:0x931b434@uschemer.rb:15 (lambda)>],
:>==>[:built_in, #<Proc:0x931b40c@uschemer.rb:16 (lambda)>]}]]]
(fib 15)
#=> 610
正しく計算できた。これは楽しい!
0 件のコメント:
コメントを投稿