2014-02-18 5 views
0

지난 며칠 동안 계획서 (특히 guile)의 연속을 가지고 놀았으며 일부 기능에 대해 궁금해하는 결과에 조금 혼란스러워합니다. 누구든지 여기서 무슨 일이 일어나는지 정확하게 설명 할 수 있습니다.구성표 : 역 추적을 위해 call/cc를 사용하는 방법

(get-token)이라는 함수가 있는데, 주어진 파일에서 다음으로 발견 된 토큰을 검색합니다. 예를 들어, 다음의 3 개의 토큰이 "a", "b", "c"의 경우, get (토큰)의 호출은, 최초로 불려 갔을 때는 "a"를, 불려 갔을 때는 "b" "c"는 세 번 호출됩니다.

내가 무엇을하고 싶은지 (get-token)을 호출하고 토큰을 반환 한 다음 (get-token) 함수가 호출되기 전의 상태로 돌아가는 함수 인 (peek-token)이 있어야합니다. 나는이 결과를 달성하기 위해 다양한 방법들을 시도, 내가 현재 가지고있는 하나입니다 : 내가 지금 그것을 이해하는 방법

;; make things a little easier to write 
(define-syntax bind/cc 
    (syntax-rules() 
    ((bind/cc var . body) 
    (call/cc (lambda (var) . body))))) 

;; function should return next token and then 
;; revert to previous state 
(define (peek-token) 
    (bind/cc return 
      (let ((token (get-token))) 
      (return token)))) 

bind/cc는 다음을 실행 한 후 첫 번째 return에서 연속을 저장합니다 코드 블록 그런 다음 return이 다시 히트되면 프로그램은 연속이 바인딩 된 곳으로 점프하고 결과적으로 token 값이 제공됩니다.

그러나 위의 함수를 실행하면 결과는 원래 (get-token) 함수와 정확히 같습니다.

누군가 내가 잘못 가고 있다고 설명하거나 같은 결과를 얻는 더 좋은 방법을 표현할 수 있다면 매우 감사 할 것입니다. (어떤 사람들은 전화/cc 방식으로가는 것을 싫어합니다.)

답변

4

마크 트웨인의 잘못된 인용 부호를 해킹하기 : call/cc의 능력에 대한 보고서는 크게 과장되어 있습니다.

더 구체적 call/cc는 호 상태하지 프로그램 상태를 캡처한다. 이는 연속이 호출 될 때 코드의 흐름이 어디로가는 지에 대한 정보를 캡처한다는 것을 의미합니다. 이 아닙니다.은 변수에 대한 정보를 캡처합니다. 특히 get-token이 변수를 둡니다 (set!). 반복을 호출 할 때 복원되지는 않습니다.

실제로 표현식이 (call/cc (lambda (k) (let ((token (get-token))) (k token)))) 인 경우는 (get-token)과 동일하게 동작해야합니다. 두 표현 사이에 관찰 가능한 차이가 없어야합니다.

+0

이 문제를 해결해 주셔서 감사합니다. 필자는 스캐너 파일 안에'(peek-token)'함수를 넣고 파일 포인터를 추적하여 토큰을 다시 읽을 수있게되었습니다. 호기심에서, 당신은 계획이나 CL에서 실제 프로그램 상태를 파악할 수있는 방법을 알고 있습니까? 아니면 정말로 이것에 대한 필요성이 없습니까? – vikingsheepman

+0

'(call-cc (lambda (k) ... (k x)))') 형태의 어떤 것이라도'(begin ... x)'와 완전히 동일하지 않다면 말입니다. – jozefg

+0

@jozefg 꽤 많이, 그 유일한 장소는 연속이 사용된다고 가정합니다. –