如何使宏观卫生的一部分
我想要一个名为 lambda-r
的 lambda
版本,您可以在其中返回
。示例:
(+ ((lambda-r ()
(return 1)
2)) 5)
这将给出值 6
。尽管您可能期望该值为 7,但实际上是 6,因为 lambda 表达式在达到 2 之前返回了 1。
这是我正在寻找的转变的一个例子。假设要使用 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 表达式而不是内部定义来表达,但我使用的是为了清楚起见定义。
请注意,上面的代码实际上确实按预期工作。 问题是我无法将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
不是有效的标识符。
编辑:感谢内森·桑德斯的回答,我更接近理解我在这里必须做什么。但是我不完全理解以下过程,因此还无法使其正常工作。如果您能解释/引导我找到解释以下内容的资源,我将非常感激:
syntax
过程datum->syntax
/syntax->; datum
程序
编辑:没关系 - 我现在已经得到了:)
I'd like to have a version of lambda
, called lambda-r
, from within which you can return
. An example:
(+ ((lambda-r ()
(return 1)
2)) 5)
This would give the value 6
. Although you might expect the value to be 7, it's 6 because 1 is returned from the lambda-expression before 2 is reached.
Here's an example of the kind of transformation I'm looking for. Let's say one were to use lambda-r
as follows:
(lambda-r (a b)
(return a)
(+ a b))
I want it to be transformed like this:
(call/cc (lambda (k)
(define return (lambda (v)
(k (lambda (a b)
v))))
(lambda (a b)
(return a)
(+ a b))))
That could also be expressed with a let-expression instead of an internal define, but I'm using the define for clarity's sake.
Note that the above code does actually work as expected. The problem is that I'm having trouble expressing lambda-r
as a macro. The reason is that I want k
and v
to be hygienic, but I don't want return
to be hygienic.
My macro at the moment is this:
(define-syntax lambda-r
(syntax-rules (return)
[(_ (var ...) body ...)
(call/cc (lambda (k)
(define return (lambda (v)
(k (lambda (var ...)
v))))
(lambda (var ...)
body ...)))
]))
Which doesn't work because return
is treated hygienically, and as a result isn't directly visible when using lambda-r
. So (lambda-r () (return 1))
gives an error which says that return
isn't a valid identifier.
Edit: Thanks to Nathan Sanders' answer, I'm closer to understanding what I have to do here. However I don't fully understand the following procedures, and as a result haven't been able to get this working yet. I'd really appreciate if you could explain/direct me to resources which explain the following:
- the
syntax
procedure - the
datum->syntax
/syntax->datum
procedures
Edit: Nevermind - I've got it now :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您想要的是
syntax-case
而不是syntax-rules
。R6RS 定义给出了一些示例,特别是语法部分-对象和数据转换,这就是你想要的。您应该能够将带有
break
的loop
示例调整为您的return
。What you want is
syntax-case
instead ofsyntax-rules
.The R6RS definition gives some examples, notably a section on syntax-object and datum conversions, which is what you want. You should be able to adapt the
loop
w/break
example to yourreturn
.