2016-10-21 4 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 + 2, N))'라도 '0 파라미터를 포함하는 "스트림"함수를 사용하여 변수로서 정의되는 것으로 이해한다. '스트림'의 내부에서는 n + 2의 자동차로 죄수 노드를 무기한 생성하지 않습니까? 그러나 'even'을 반환하면 (0. # < Closure>)의 단점이 있습니다. 누군가가 왜 이렇게 친절했는지 설명 할 수 있습니까? 감사!

답변

0

매번 (lambda ...)이 평가됩니다. 즉, f은 무료이며 절차 next과 프로 시저 모두에서 사용할 수 있습니다. next의 바운드 변수 인 m도 익명 프로 시저에서 자유 변수로 캡처됩니다. 언어가 동적으로 바인드 된 경우 cdr에서 결과 프로 시저를 호출하면 해당 바인딩이 존재하지 않으므로 바인딩이 더 이상 존재하지 않으므로 클로저가 있으므로 변수를 작성한 프로 시저가 종료 된 후에도 변수가 존재합니다.

stream 프로 시저에서 반환 된 쌍에는 이 호출되었지만 (lambda (n) (+ n 2))이 평가 된 경우 작성된 ​​클로저에 대한 참조가 있습니다. 당신이 할 따라서 경우 :

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

그것은 next의 평가가 2이 시간 새로운 무료 변수 m을 가진 새 폐쇄와 쌍을하게 알고하는 것이 중요합니다. cdr으로 전화 할 때마다 새 폐쇄로 새 쌍을 만듭니다. 반복 할 때마다 동일한 결과를 얻지 못할 때마다 동일한 결과를 얻었습니다.

람다는 자체 코드를 실행하지 않습니다. 따라서 무한 재귀 대신에 한 단계 만 얻으면 결과는 (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

관련 문제