2010-04-05 1 views
0

"The Seasoned Schemer"의 16 장에서 저자는 '깊이 3'과 같이 n 목록에 중첩 된 피자를 반환하는 재귀 프로 시저 'depth'를 정의합니다. (((피자))). 그런 다음이를 "depthM"으로 향상 시키며, 이는 set을 사용하여 반환 값을 캐시합니다! 조회 테이블을 구성하는 Ns와 Rs 목록에서 이전에 보았던 반환 값에 도달하면 모든 과정을 반복하지 않아도됩니다. 예 : 이미 (depthM 8)을 계산했다면, 나중에 depthM 9를 계산할 때 (depthM 8)의 반환 값을 조회하고 null로 놓습니다 (depthM 0까지).스키마의 이전 반환 값 캐싱

그러나 Ns와 Rs를 프로 시저 내부로 옮기고 "let"으로 null로 초기화합니다. 왜 이것이 반환 값을 캐싱하지 못하게합니까? 약간의 실험에서, Ns와 Rs가 "depthM"에 대한 모든 호출에서 다시 초기화되는 것처럼 보입니다.

나는 그 점을 오해하고 있습니까?

내 질문에 정말 같아요 : 당신이 "상태"변수와 Perl 5.10에서 할 수있는 것처럼 어휘 범위 변수가 프로 시저 호출 사이에 그들의 값을 보존 할 수있는 방법이 있나요?

답변

5

Duh. Seasoned Schemer를 읽지 않았기 때문에 여기에 소스 코드를 제공하지 않는 한 메모 작성 문제에 대해서는 언급 할 수 없습니다. 그러나 어휘 적 범위 변수가 함수 호출간에 상태를 유지할 수있는 방법이 있는지에 관한 질문은 ... "closure"라고하는 Scheme 언어의 기능입니다. 다음 예를 고려

(define counter 
    (let ((number 0)) 
    (lambda() 
     (let ((result number)) 
     (set! number (+ number 1)) 
     result))) 

이런 코드는 상태를 추적하기 위해 어휘 변수 (number)를 사용하여 카운터라는 함수를 정의한다. 함수를 호출 할 때마다 다음과 같이 다른 번호가 반환됩니다.

등등. 여기서 중요한 점은 lambda 표현식을 실행하여 생성 된 함수는 어커런스 범위에서 모든 어휘 적으로 볼 수있는 변수를 "닫습니다"(이 경우에만 number입니다.) 즉, 해당 변수가 유효한 값을 유지할 수있는 유효한 위치로 남아 있음을 의미합니다. 새 값을 쓰십시오.

+0

감사합니다. 나는 테스트 케이스와 비슷한 것을 썼지 만, 명시 적 람다를 생략했다. (정의 (foo) (...)) 구문론 설탕 (정의 foo (lamdba() (...))).하지만이 경우에는 작동하지 않습니다. lamdba가 클로저를 만들기 위해 내부에 있어야하기 때문에. – Brock

+0

브록, 특정 권장 사항을 만들 수 있습니까? 이것은 나에게 혼란 스러웠습니다. Dirk이 위에서 쓴 글에 대한 퍼지적인 이해 -하지만이 섹션 3.2.3을 통해 어휘 범위와 환경의 근본적인 개념을 SICP에서 이해할 수있을 것입니다. 아마도 여러분은 그것으로부터 뭔가를 얻을 것입니다 : http : // mitpress .mit.edu/sicp/전체 텍스트/책/책 -ZH-21.html # % _ sec_3.2.3 – mquander