2017-11-02 11 views
1

내가 계획하고 일반적으로 리스프에 새로운 해요, 학습에 내가 바인딩 로컬 프로 시저에 사용되는 암호 같은 구문을 우연히 발견했습니다 : 그것은 있음을 파악 걸 렸어요로컬 프로 시저 바인딩

(define mock 
    (lambda (s) 
     ;; this is what I don't understand 
     (let splice ([l '()] [m (car s)] [r (cdr s)]) 
     (append 
     (map (lambda (x) (cons m x)) r) 
     (if (null? r) '() 
      (splice (cons m l) (car r) (cdr r))))))) 

splice 3 개 요소가있는 범위가 지정된 절차입니다.

(define mock2 
    (lambda (s) 
     ;; define `splice` first 
     (define splice 
     (lambda (la lb lc) 
      (append 
      (map (lambda (x) (cons lb x)) lc) 
      (if (null? lc) '() 
       (splice (cons lb la) (car lc) (cdr lc)))))) 
     ;; bind `splice` and its arguments together and call it with them 
     (let ([sp splice] [l '()] [m (car s)] [r (cdr s)]) 
     (splice l m r)))) 

두 번째 버전은 조금 더하고 좀 더 필수적 보이지만, 병렬에 바인딩하기 전에 범위 내 정상적인 절차로 splice 정의 : ML - 억양 스타일이 다시 쓰기는 유사한 출력을 생성하는 것 논쟁과 함께 (또는 그대로있는 척하십시오) 부름을 청합니다.

질문이 두 버전을 교체 할 수 있습니까? 그렇다면 splice 바인딩 양식 내에서 로컬 변수 (l, mr)를 바인딩하는 첫 번째 버전의 구문을 설명하는 데 도움이 될 수 있습니까?

+0

'(null? r)'에 이르렀을 때 L을 돌려 보내면 안됩니다 : 달리 사용되지 않는 것 같습니다. – coredump

+0

@coredump 네 말이 맞아. – PieOhPah

답변

2

splice을 호출하는 것은 루프에 다시 입력하는 것과 같습니다. 꼬리 전화는 어쨌든 고토입니다. 특별한 이름을 생각하는 대신에 종종 loop으로 명명됩니다.

"seem saner"는 논쟁의 여지가 있습니다. 실제로 이것은 Schemer와 마찬가지로, 이라는 매우 유명한 Scheme 구성이기 때문에 이것을 잃을 것입니다.. 재 작성을 원할 경우 보통 더 잘 이해하기 위해 보통 letrec btw로 다시 쓰여집니다. 내부 define도 사용할 수 있지만 처음에는 (define (mock s) ...을 사용하지 않는 것이 좋습니다.

(define mock 
    (lambda (s) 
    (letrec ([splice (lambda (l m r)  ; or: (define (splice l m r) ... 
         (append 
         (map (lambda (x) (cons m x)) r) 
         (if (null? r) '() 
          (splice (cons m l) (car r) (cdr r)))))]) 
     (splice '() (car s) (cdr s))))) 

이름에서 그것을 쓰기가 한 곳에서 정의 않아도 방법은 하나의 저장하자

그래서, 일반적인 방법이

(define mock        ; or: (define (mock s) ... 
    (lambda (s) 
     (let splice ([l '()] [m (car s)] [r (cdr s)]) 
     (append 
     (map (lambda (x) (cons m x)) r) 
     (if (null? r) '() 
      (splice (cons m l) (car r) (cdr r))))))) 

를 다시 작성하는 것은 이것이다 잠재적으로 멀리있는 다른 곳에서 전화를 걸었습니다. 호출은 처음부터 본문에 들어가며, 이름이 을 더 잘 반영하도록합니다.

이것은 아주 자명합니다. 하나의 형식에서 다른 형식으로의 변환은 순전히 구문 론적이며, 둘 다 상호 교환 적으로 사용될 수 있습니다.

+0

포인터를 사용하여 마침내 http://www.gnu.org/software/mit-scheme/documentation/mit-scheme-ref/Iteration.html 문서를 찾았습니다. 프로 시저에 이름을 바인딩하는 특별한 형태 인 것처럼 보입니다. do와 함께 할 수있는 일인가요? – PieOhPah

+0

다시 쓰기는'do'와 훨씬 더 관련이 있습니다. 어쨌든 매크로 그 자체 일 것입니다. 'letrec'은 Scheme의 가장 기본적인 빌딩 블록 중 하나로 간주됩니다. –