2010-03-12 2 views
4

if 또는 cond과 같은 구조를 사용하여 없이 "early return"을없이 어떻게 사용할 수 있는지 알아 내려고합니다.제도가 일찍 "단락 회로 복귀"?

(define (win b) 
(let* ((test (first (first b))) 
     (result (every (lambda (i) (= (list-ref (list-ref b i) i) test)) 
         (enumerate (length b))))) 
    (when (and (not (= test 0)) result) test)) 
0) 

예를 들어, 위의 코드에서, 내가 무슨 일하는 것은, 그렇지 않으면 그러나 0으로 돌아가 when 조건이 충족되는 경우 test을 반환 win를 원하는 것입니다 항상 반환 0에 관계없이의 절차 when 상태의 결과입니다.

이유는이 절차에서 많은 복잡한 검사 (예 : let*과 유사한 여러 블록)를 수행하고 큰 것을 모두 넣어야하기 때문입니다. cond은 매우 다루기 힘듭니다.

+1

당신은 큰 COND을 만들어 잘 선택한 이름으로 별도의 기능의 각 수 있도록 블록을 넣으면 네,하지만, 당신이 더 많은 읽을 수있는 코드와 바람 것입니다. –

답변

7

return 직접 구축 통화 /의 CC를 사용하는 방법입니다. 당신의 계획은,/CC가 사소한하지 않는 경우 물론

(define (example x) 
    (let/cc return 
    (when (< x 0) (return #f)) 
    0)) 

:

(define (example x) 
    (call/cc (lambda (return) 
    (when (< x 0) (return #f)) 
    ; more code, including possible more calls to return 
    0))) 

일부 구성표하자라는 매크로/당신이 람다의 소음의 일부를 드롭 할 수 있습니다 CC를 정의 쓰다.


호출/cc는 연속으로 호출 된 지점을 저장하기 때문에 작동합니다. 그것은 그 연속을 함수 인수로 전달합니다. 함수가 그 지속을 호출 할 때, 계획은 지금까지 구축 한 어떤 호출 스택을 포기하고 통화/cc의 호출의 끝에서 계속됩니다. 물론 함수가 연속을 결코 호출하지 않는다면, 그냥 정상적으로 반환됩니다.

계속 기능을 사용하면 기능에서 반환하기 시작하거나 전역 데이터 구조에 저장하고 나중에 호출하기 전까지는 계속 마음이 계속 뛰지 않습니다. 그렇지 않으면 다른 언어의 구조화 된 goto 문 (/ for/break/return/continue/exceptions/conditions)과 같습니다.


전체 코드가 어떻게 생겼는지는 모르겠지만 cond로 가서 복잡한 검사를 개별 기능으로 분류하는 것이 좋습니다. returnlet*을 필요로하는 것은 일반적으로 지나치게 필수적 코드의 증상이다. 그러나 call/cc 메서드는 현재 코드를 작동시켜야합니다.

+0

설명해 주셔서 감사합니다. 나는 당신이 제안한대로 분리 된 기능을 만드는 것과 함께 최상위 수준의 조건을 사용하여 끝내었다. – Suan

1

한 가지 방법은 조기 종료가 더 재귀하지 않음으로써 달성 재귀 대신 루프를 사용하는 것입니다.

0

당신은 수익을 시뮬레이션하기 위해 "현재 계속 콜"지원을 사용할 수 있습니다. wikipedia에 대한 예가 있습니다. 이 기능은 전화 - 현재 - 계속라고 불리는데, 종종 call/cc이라는 별칭이 있지만 정확히 동일한 것입니다. here

주 약간 청소기 예를도있다 : 이것은 아주 고급 구성표 프로그래밍 기술이며, 처음에는 굽힘 조금 마음이 될 수 있습니다 ... !! 여기

0

이 경우에는 원하지 않지만, 최상위 레벨이 아니더라도 if를 원합니다.

(define (win b) 
    (let* ((test (first (first b))) 
     (result (every (lambda (i) (= (list-ref (list-ref b i) i) test)) 
         (enumerate (length b))))) 
    (if (and (not (= test 0)) result) 
     test 
     0))) 

언제나 0을 반환하는 이유는 해당 본문이 실행되었는지 여부에 상관없이 결과가 바닥에 떨어지는 것입니다. 당신은 모든 중간 결과를 삭제하면서 이렇게

(define foo 
    (lambda (b) 
    (begin 
     (let ...) 
     0))) 

와 방법, 작품이 내 마지막 형태의 결과를 반환되어 시작 함수에서 암시 람다 폼을 암시 너무 블록을 시작 생성 정의 참조 바닥. 이러한 중간 결과는 부작용이있는 것입니다. 당신은 위대한 (!) 중 하나를 사용하지는 않지만, 함수 정의 안에 오직 하나의 폼 (결과가 정말로 원하는)만을 갖도록주의해야합니다.

Grem

+0

예. Scheme에서 (lambda (stmt1 stmt2 stmt3)에 여러 표현식이있는 경우) 마지막 명령문의 결과 만 리턴됩니다. asker의 예에서, if 문이 끝나면 계속 작업이 잔인 할 수 있습니다. – erjiang