"명령"과 "프로그램"(미로에 거주하는 로봇에 대한 우리 교수가 발명 한 "로봇 언어"의 해석자)의 목록을 재귀 적으로 분석해야하는 프로그램을 작성 중입니다. 초기 구현이 너무 느리기 때문에 call-with-current-continuation을 사용하기로 결정했습니다.스키마 호출/cc 문제 - exit 구현.
나는 call/cc가 어떻게 작동하는지 알고있다. 설명으로 this과 this을 읽었다.
내 전화/CC는 튜토리얼의이 부분을 기반으로합니다
는 종종 우리가 사용하고자하는 통화와 전류 연속 탈출 절차 이외의 인수를 일부 프로 시저를 호출 할 수 있습니다.(정의 (foo는 XY 탈출) ... (만약 (= X 0) (탈출 'ERROR)) : 예를 들어, 우리는 외에 두 개의 인수하여 이스케이프 절차를 취하는 절차가있을 수 있습니다. ..)) 우리는 프로 시저를 currying하여이를 해결할 수 있습니다. 프로 시저를 하나의 인수로 만듭니다.
[이전 장에는 currying에 대한 토론이 있어야합니다! ]
x 및 y의 값으로 0과 1을 전달하고 이스케이프 프로 시저를 전달하는 것으로 가정합니다. 오히려
말보다 (통화와 전류 연속 foo는) foo에 대한 호출에 충분한 인수를 전달하지 않습니다, 우리는 말을(통화와 전류 연속 (람다 (탈출) (foo 0 1 escape))) 람다 식은 정확히 우리가 수행하는 클로저를 만듭니다. . 인수 0, 1을 사용하여 foo를 호출하고 call-with-current-continuation으로 생성 된 이스케이프 프로 시저 을 호출합니다.
그러나, 그것은 작동하지 않습니다 어떤 이유로이 예외가 발생합니다 :
call-with-current-continuation: contract violation
expected: (any/c . -> . any)
given: #<procedure:...mazesimulator.ss:301:34>
난 당신이 내 실수를 발견하고이 발생하는 이유를 설명하는 데 도움 싶습니다을 ...
다음은이 질문과 관련된 코드 부분입니다.
; main program
(define (simulate state expression-list program limit)
; read the input and set global variables
(set! current-orientation (list-ref state 2))
(set! current-coordinates (list-ref state 1))
(set! current-maze (list-ref state 0))
; call the inner function
(call-with-current-continuation (lambda (exit)
(command state expression-list program limit exit)))
; this is the output
(list list-of-executed-commands (list current-maze current-coordinates current-orientation))
)
;; main recursive function
;; analyses expression-list parameter
;; evaluates its elements
;; and calls itself on the cdr of the espression-list
(define (command state expression-list program limit exit)
(if (and (not (null? expression-list))(equal? stop-command #f))
; recursion end condition, the whole procedure will be done only
; if the list is still not empty
(if (atom? expression-list) ;if the list consists of only one command
(if (equal? stop-command #f) ;positive branch - if there were no erros before
(atomic-command state expression-list program limit exit) ;call atomic-command on this element
;when flag is set to #t
(exit))
; here comes a problem with "inner ifs"
(if (atom? (car expression-list)) ;negative branch - if the first element is "if"
(if (equal? (car expression-list) 'if) ;if the list consisits only of if-clause, no other commands ((if ...))
(if ((name->function (list-ref expression-list 1))) ;evaluate the boolean - wall? north? and choose corresponding branch
(command state (list-ref expression-list 2) program limit exit)
(command state (list-ref expression-list 3) program limit exit))
(evaluate-first-and-call-command-on-rest expression-list program limit exit))
(if (equal? (car(car expression-list)) 'if) ;if the if-clause is not the only element in list - "inner if" ((if ...) turn-left put-mark)
(begin ;not only evaluate if-clause,
(if ((name->function (list-ref (car expression-list) 1)))
(command state (list-ref (car expression-list) 2) program limit exit)
(command state (list-ref (car expression-list) 3) program limit exit))
(command state (cdr expression-list) program limit exit)) ;but also call command on cdr!
(evaluate-first-and-call-command-on-rest expression-list program limit exit))))
;when limit is exceeded or when the flag is set to #t
(exit)))
[1] 라켓에서 사용하는 언어는 무엇입니까? (나는 당신이 DrRacket을 사용하고 있다고 가정합니까?) 또한, 어떤 버전의 Racket을 사용하고 있습니까?; [2] 동일한 버그를 보여주는 직접 실행할 수있는 작은 버전의 예제를 파생시킬 수 있습니까? (어떤면에서는 작은 독립적 인 테스트를 구축하는 것에 대한 필자의 기본 조언은 여전히 여기에 적용됩니다.) – pnkfelix
@pnkfelix - DrRacket, language Scheme, standard R5RS를 사용합니다. 모든 테스트를 시도했지만 지금까지는 내 프로그램에 어플라이언스가 적용되지 않습니다. 나는 내가 추측하는 더 많은 시간이 필요해. – petajamaja
나쁜 소식. 꼬리 - 재귀를 사용하지 않았으므로 여기서는/cc를 사용하면 전혀 쓸모가 없습니다. – petajamaja