2012-04-22 5 views
2

저는 Lisp (코드는 GitHub입니다)을 쓰고 있는데 로컬 바인딩을 구현하고 싶습니다. 한 번에 여러 개의 값을 결합하는 하나의 변수 또는 기능을 결합 용동시 바인딩 구현하기

(let <var> <val> <expr>) 

(with (<var1> <val1> ... <varN> <valN>) <expr>) 

: 현재 I 두 구문을 갖는다.

현재 바인딩은 순차적으로 평가되며 각 새 함수 바인딩은 정의 된 환경의 복사본을 유지하므로 은 <var1>을 참조 할 수 있지만 그 반대는 마찬가지입니다.

한 번에 여러 값을 바인딩 할 때 효과적으로 동시 바인딩을 가질 수 있도록 코드를 수정하고 싶습니다. 예를 들어, 내가 쓸 수 있도록하고 싶습니다 (이것은 사소한 예이지만, 아이디어를 설명한다) : 순간

(define (h y) 
    (with ((f x) (if (eq? x 0) #t (g (- x 1))) 
     (g x) (if (eq? x 0) #f (f (- x 1)))) 
    (f y)) 

이 코드가 실행되지 않습니다 - gf 이상 닫지 만하지 다른 방향으로.

Lisp에서 동시 바인딩을 구현할 수있는 표준 방법이 있습니까?

+0

변수 바인딩 구조체로'with'를 소개하지만, 다음 예제에서는 int가 어휘 함수 바인딩 구조로 변합니다. 그게 사실인가요? 심볼 또는리스트가되는 ''을 구별합니까? – Kaz

+0

댓글을 주셔서 감사합니다. 그래, 내 구현에서'let'과'with'는 두 변수 (''이 기호 인 경우)와 렉시 컬 함수 (' '가 목록 인 경우)를 바인딩합니다.그들은 정확히 동일한 기본 함수를 호출합니다 - 내 github repo에서 EvalApply.hs의 114-139 행을 참조하십시오. –

답변

1

SICP에는 internal definitions에이 주제를 다루는 섹션이 있습니다. 특히, 실습 4.16, 4.18, 4.19에서는 동시 정의를 달성하기위한 다양한 전략을 구현하는 방법을 설명합니다.

구문은 약간 다르지만,이 책의 아이디어는이 코드 변환에 종기 : 당신의 with 특별한에

(lambda <vars> 
    (let ((u '*unassigned*) 
     (v '*unassigned*)) 
    (set! u <e1>) 
    (set! v <e2>) 
    <e3>)) 

같은 아이디어는 적용이 코드에

(lambda <vars> 
    (define u <e1>) 
    (define v <e2>) 
    <e3>) 

을 형태. 자세한 구현 세부 정보는 링크 된 책을 살펴보십시오. (with (a (+ 2 2)))에서

+0

SICP에 대한 포인터를 보내 주셔서 감사합니다. 로컬 바인딩이 코드 변환 일 경우,'let'과'with'는 프리미티브가 아니고 대신 매크로 여야합니다. 어떻게 생각해? –

+0

@ChrisTaylor 좋은 생각입니다. 그런 식으로 언어의 핵심은 간단하게 남아 있으며 매크로를 사용하는 구문 변환으로 다른 특수 형식을 구현할 수 있습니다. 사실, SICP에서'let','let *','letrec' 등은 (매크로가 아닌 인터프리터 레벨에서) 구문 변환으로 구현됩니다. –

1

우리는 그렇게 a 4.된다 그러나 (with ((f x) (+ x x))) 우리가 뭔가 다른 일을하는, 표현 (+ 2 2)의 값 a을 바인딩 : 우리는 함수에 f 바인딩된다. 이것은 (with (f (lambda (x) (+ x x))))에 대한 통사론입니다.

이 상황을 처리하려면 바인딩을 두 번 처리해야합니다. 먼저 모든 변수를 모으고 모든 변수를 포함하는 환경을 만듭니다. 그런 다음 초기화 익스 클루 션을 평가하고 해당 값을 해당 변수에 저장하십시오. 이 표현식의 평가는 해당 환경에서의 에서 이루어 지므로 모든 표현식이 모든 변수에 대해 가시성을 갖습니다. 초기화는 할당에 의해 수행됩니다. 변수는 처음에는 nil이거나 액세스 할 때 약간의 트랩 값을가집니다.

+0

Haskell에서 과제와 함께 행운을 빈다. :) – Kaz

+0

하하, 고마워요 :) –

+0

당신은 오스카와 같은 대답임을 알 수 있습니다. 이것을 상호 재귀 적이지 않은'let' 구조체로의 코드 변환으로 할 수 있습니다; 제가 설명한 것은 똑같은 금액을 직접 해석하는 전략입니다. – Kaz