매크로의 일부만 위생적으로 만드는 방법
문제
다음 버전을 갖고 싶습니다. lambda
, 라고 불리는 lambda-r
, 그 안에서 다음을 수행할 수 있습니다. return
.예:
(+ ((lambda-r ()
(return 1)
2)) 5)
이것은 가치를 줄 것입니다 6
.값이 7일 것으로 예상할 수도 있지만 2에 도달하기 전에 람다 식에서 1이 반환되므로 값은 6입니다.
제가 찾고 있는 변화의 예는 다음과 같습니다.하나가 사용한다고 가정 해 봅시다 lambda-r
다음과 같이:
(lambda-r (a b)
(return a)
(+ a b))
나는 이것을 다음과 같이 변형시키고 싶다.
(call/cc (lambda (k)
(define return (lambda (v)
(k (lambda (a b)
v))))
(lambda (a b)
(return a)
(+ a b))))
내부 정의 대신 let-expression을 사용하여 표현할 수도 있지만 명확성을 위해 정의를 사용하고 있습니다.
위의 코드는 실제로 예상대로 작동합니다. 문제 내가 표현하는 데 문제가 있는 걸까? lambda-r
로서 매크로.이유는 내가 원해서야 k
그리고 v
위생적이지만 그러고 싶지 않아요 return
위생적이게.
현재 내 매크로는 다음과 같습니다.
(define-syntax lambda-r
(syntax-rules (return)
[(_ (var ...) body ...)
(call/cc (lambda (k)
(define return (lambda (v)
(k (lambda (var ...)
v))))
(lambda (var ...)
body ...)))
]))
작동하지 않는 이유는 무엇입니까? return
위생적으로 처리되어 사용시 눈에 직접 띄지 않습니다. lambda-r
.그래서 (lambda-r () (return 1))
다음과 같은 오류가 발생합니다. return
유효한 식별자가 아닙니다.
편집하다:Nathan Sanders의 답변 덕분에 여기서 해야 할 일을 더 잘 이해할 수 있게 되었습니다.그러나 나는 다음 절차를 완전히 이해하지 못하여 아직 이 작업을 수행하지 못했습니다.다음 내용을 설명하는 리소스를 설명하거나 안내해 주시면 정말 감사하겠습니다.
- 그만큼
syntax
절차 - 그만큼
datum->syntax
/syntax->datum
절차
편집하다:신경쓰지 마세요 - 지금 가지고 있어요 :)
해결책
당신이 원하는 것은 syntax-case
대신에 syntax-rules
.
R6RS 정의 특히 몇 가지 예를 제시합니다. 구문 객체 및 데이텀 변환에 관한 섹션, 그것이 당신이 원하는 것입니다.당신은 적응할 수 있어야합니다 loop
/ break
당신의 예 return
.