2016-10-21 11 views
0

このコードスニペットを解読するのに問題があります。このスキームスニペットではどのようにクロージャが発生しますか?

(define (stream n f) 
    (define (next m) 
     (cons m (lambda() (next (f m))))) 
    (next n)) 
(define even (stream 0 (lambda (n) (+ n 2)))) 

私は「(()ラムダ(N + N 2))」も '0パラメータとを含んでいる「ストリーム」機能を使用して変数として定義されていることを理解します。 'ストリーム'の内部では、 '(次のn)'は無期限にn + 2の車でコンスノードを作成しませんか?しかし、私が「偶数」に戻ると、それは(0。#< Closure>)の短所です。誰かがとても親切で、なぜこれが説明できるのでしょうか?ありがとう!

答えて

0

毎回(lambda ...)が評価されると閉鎖になります。つまり、fは無料で、手続きnextとそれが作成する匿名プロシージャの両方で利用可能です。 の結合変数であるmも、匿名手順で自由変数として取得されます。変数が動的にバインドされていた場合は、cdrで結果のプロシージャを呼び出すと存在しませんでしたが、バインディングが存在しなくなったため、クロージャが作成されているため、変数を作成したプロシージャを終了しても変数は存在します。

streamプロシージャによって返されたペアは、コールが終了してもという名前で(lambda (n) (+ n 2))が評価されたときに作成されたクロージャへの参照を持ちます。あなたが行う場合はこのように:

((cdr even))   ; ==> 
(#<closure>)   ; ==> 
(cons 2 #<new-closure>) ; ==> Here 

をそれはnextの評価が2この時点で新しい自由変数mを持つ新しい閉鎖と対になっていることを知っておくことが重要です。 cdrに電話するたびに、新しいクロージャで新しいペアが作成されます。それが毎回同じであった場合、それぞれの反復ごとに異なる結果が得られません。

ラムダ自身のコードではコードが実行されません。したがって、無限再帰の代わりに1ステップしか得られず、結果は(cons 2 #<new-closure>)になります。あなたはもう一度ステップを得るために、これのcdrにもう一度電話する必要があります。私はこれなかった場合など同様に:

(define (test a) 
    (define (helper b) 
    (+ a b)) 

    helper) ; return the helper that has a as closure variable 

を私たちが実際に名前を使用していないので、一つはだけではなく、define +結果の変数の存在匿名ラムダを持つことができます。とにかく、部分的にアプリケーションを提供するものが得られます:

((test 5) 2) ; ==> 7 

(define ten-adder (test 10)) 
(ten-adder 2) ; ==> 12 
(ten-adder 5) ; ==> 15 
+0

私はまだこれをすべて処理していますが、これまでのところ非常に役に立ちます。私はラムダの仕組みを知っていましたが、体内で動かなかったという事実を完全に逃してしまったので、少しクリアします。 – Taylor

関連する問題