2017-12-05 2 views
0

combine은 이진 연산자 bin으로 목록을 축소해야하지만 술어 pred?에 실패한 값을 찾으면 exc을 반환해야하며 이러한 값을 찾으면 목록에서 계산을 수행하면 안됩니다.Racket에서 call/cc의 재미있는 동작을 설명하는 방법은 무엇입니까?

이것은 계속되는 간단한 문제입니다.

#lang racket 

(define (id x) 
    x) 

(define (const x) 
    (lambda (_) x)) 

(define (combine pred? bin zero exc) 
    (call/cc 
    (lambda (exit) 
    (letrec 
     ((f (lambda (xs) 
       (if (empty? xs) 
        zero 
        (if (pred? (first xs)) 
         (exit exc) 
         (bin (first xs) (f (rest xs)))))))) 
     f)))) 

(define product 
    (combine zero? 
      * 
      1 
      0)) 

(product '(1 2 3 0 4)) 

코드는 거의 작동하지만 아주 미묘한 오류가 있습니다.

그것은 다음과 같은 예외가 발생 :

define-values: assignment disallowed; 
cannot re-define a constant 
    constant: product 

일을 쉽게 만들 수 있습니다. 단지 작은 변화가 필요하다 :

(define (combine pred? bin un zero exc) 
    (lambda (ys) 
    (call/cc 
    (lambda (exit) 
     (letrec 
      ((f (lambda (xs) 
       (if (empty? xs) 
        zero 
        (if (pred? (first xs)) 
         (exit exc) 
         (bin (first xs) (f (rest xs)))))))) 
     (f ys)))))) 

나는 문제가 라켓 정의의 연속 함수를 정의하는 것입니다,하지만 사람이 더 자세한 정보를 줄 수있는 것을 볼? 예를 들어 어떤 신택스 변형이 관련 되었습니까? 여기에 있어야 순서의

답변

1

생각해 : 여기

(define product (combine ....)) 

먼저 (combine ...) 평가하고 계속이 이름 product으로 계산 된 값을 저장하기로 시작하는 프로그램의 나머지 부분입니다. f에서 계속을 호출하면 다시 product에 저장됩니다.

(product '(1 2 3 0 4))을 호출하면 product이 프로그램의 연속이어서 call/cc이 연속을 캡처하므로 다시 정의 할 수 있습니다.

두 번째 시도에서 람다로 랩핑하고 f를 동일한 인수로 리팩터링합니다. call/cc이 발생하면 계속 지연되며 따라서 연속에 포함됩니다. 이 버전에서 계속되는 것은 (product ...) 뒤에 오는 것이고, 설정하지 않는 것입니다. product(define product ...)

+0

이것은 체계 자체로 설명 할 수 있습니까, 아니면 구현에서 언어 외부를 봐야합니까? –

+0

@Rdgstv'#lang racket'은 표준을 따르지 않지만, [호환 가능] 것으로 보인다 (http://www.r6rs.org/final/html/r6rs/r6rs-ZH-14.html#node_idx_352). 구현 책임 : 구현시 의 연속이 두 번 이상 호출됨을 감지해야합니다. 구현에서이를 감지하면 조건 유형 및 어설 션으로 예외를 발생시켜야합니다. "*. Racket (구현)은 많은 표준 Scheme 보고서 언어를 지원합니다. 동일한 primitive로'define'과'set! '을 가진 많은 "scheme"구현물을 보았습니다. – Sylwester

+0

@Rdgstv'call/cc'에 관해서는. 모든'call/cc'는 연속을 함수로 드러내는 것입니다. 많은 Scheme 구현체가 어쨌든 CPS로 코드를 변환하지만'call/cc '에서는 코드를 변환하지 않습니다. CPS'call/cc'는 단지'(define (call/cc body c) (body (람다 (실제 값의 연속) (c 값))) c))'입니다. 'define '과 같은 특별한 형식은 CPS에서하기가 어렵습니다. 함수 내에서 최상위 바인딩을 정의하는 프리미티브가 없기 때문입니다. (함수 안에서'define '은'letrec'가되고 그것은 우리가 원하는 것이 아닙니다) – Sylwester

관련 문제