卫生宏 r7rs : Return 第二个表达式值
Hygienic macro r7rs : Return second expression value
我目前正在学习一些 r7rs,我正在尝试实现一个宏 'begin',如下所示:
(begin0 expr0 expr1 ... expr2)
expr是一个正则表达式(如(set!x(+ x 1)))
并且 begin0 作为一个宏计算所有表达式,但 return 仅计算 expr1 结果。
例如:
(let ((year 2017))
(begin1 (set! year (+ year 1))
year
(set! year (+ year 1))
year))
必须 return 2018
我先创建了一个开始函数:
(define-syntax begin0
(syntax-rules ()
((begin-0 body-expr-0 body-expr-1 ...)
(let ((tmp body-expr-0)) body-expr-1 ... tmp))))
现在,我正在尝试了解如何才能 return "body-expr-1" 的价值?
我已经完成了以下代码,但它说我缺少一些省略号而且我不知道该怎么做。
(define-syntax begin1
(syntax-rules ()
((begin1 body-expr-0 body-expr-1 ... body-expr-2)
(let ((tmp body-expr-0) body-expr-1 ... tmp)
(cond (eq? tmp body-expr-1)
(begin . tmp))))))
我希望它足够理解,感谢您的回答。
所以,我找到了一种可能的方法,虽然我们可以只询问立即值的条件,但我没有找到:
(define-syntax begin1
(syntax-rules ()
((begin1 body-expr-0 body-expr-1 body-expr-2 ...)
(if body-expr-1
(write body-expr-1)))))
这可以做到,但是宏会干扰你不能用 begin1
做所有事情,就像 begin
。
(define-syntax begin1
(syntax-rules ()
((_ expr0 expr1 exprn ...)
(begin
expr0
(let ((result expr1))
exprn ...
result)))))
不起作用的代码是这样的:
(begin1
(define global1 10)
test3
(define global2 20))
原因很明显。它扩展为:
(begin1
(define global1 10)
(let ((result~1 test3))
(define global2 20)
result~1))
第二个 define
将更改为 letrec
,这样变量 global2
仅在 let
期间可用。我没有解决这个问题,因为它要求您能够从闭包中执行 global define
。
begin1
是一个相当奇怪的特征。在 Racket 和其他 Scheme 方言中,我们有 begin0
第一个表达式的结果 returns 。这非常有用。例如。这是一个计数器:
(define (get-counter from)
(lambda ()
(let ((tmp from))
(set! from (+ from 1))
tmp)))
与 begin0
:
(define (get-counter from)
(lambda ()
(begin0
from
(set! from (+ from 1)))))
在 Racket 中 begin0
是原语。所以它是完全扩展程序中支持的一种形式,因此在 C 中实现,就像 begin
..
我目前正在学习一些 r7rs,我正在尝试实现一个宏 'begin',如下所示:
(begin0 expr0 expr1 ... expr2)
expr是一个正则表达式(如(set!x(+ x 1)))
并且 begin0 作为一个宏计算所有表达式,但 return 仅计算 expr1 结果。
例如:
(let ((year 2017))
(begin1 (set! year (+ year 1))
year
(set! year (+ year 1))
year))
必须 return 2018
我先创建了一个开始函数:
(define-syntax begin0
(syntax-rules ()
((begin-0 body-expr-0 body-expr-1 ...)
(let ((tmp body-expr-0)) body-expr-1 ... tmp))))
现在,我正在尝试了解如何才能 return "body-expr-1" 的价值? 我已经完成了以下代码,但它说我缺少一些省略号而且我不知道该怎么做。
(define-syntax begin1
(syntax-rules ()
((begin1 body-expr-0 body-expr-1 ... body-expr-2)
(let ((tmp body-expr-0) body-expr-1 ... tmp)
(cond (eq? tmp body-expr-1)
(begin . tmp))))))
我希望它足够理解,感谢您的回答。
所以,我找到了一种可能的方法,虽然我们可以只询问立即值的条件,但我没有找到:
(define-syntax begin1
(syntax-rules ()
((begin1 body-expr-0 body-expr-1 body-expr-2 ...)
(if body-expr-1
(write body-expr-1)))))
这可以做到,但是宏会干扰你不能用 begin1
做所有事情,就像 begin
。
(define-syntax begin1
(syntax-rules ()
((_ expr0 expr1 exprn ...)
(begin
expr0
(let ((result expr1))
exprn ...
result)))))
不起作用的代码是这样的:
(begin1
(define global1 10)
test3
(define global2 20))
原因很明显。它扩展为:
(begin1
(define global1 10)
(let ((result~1 test3))
(define global2 20)
result~1))
第二个 define
将更改为 letrec
,这样变量 global2
仅在 let
期间可用。我没有解决这个问题,因为它要求您能够从闭包中执行 global define
。
begin1
是一个相当奇怪的特征。在 Racket 和其他 Scheme 方言中,我们有 begin0
第一个表达式的结果 returns 。这非常有用。例如。这是一个计数器:
(define (get-counter from)
(lambda ()
(let ((tmp from))
(set! from (+ from 1))
tmp)))
与 begin0
:
(define (get-counter from)
(lambda ()
(begin0
from
(set! from (+ from 1)))))
在 Racket 中 begin0
是原语。所以它是完全扩展程序中支持的一种形式,因此在 C 中实现,就像 begin
..