【发布时间】:2011-07-04 00:19:45
【问题描述】:
我写了一个函数match-rewriter,它本质上是match-lambda,只是如果没有找到匹配项,它会返回它的参数:
(define-syntax match-rewriter
(syntax-rules ()
((_ (patt body) ...)
(λ (x) (match x (patt body) ... (_ x))))))
现在我想使用match-rewriter 获取代表let* 源代码的字符串并将其重写为嵌套的一元lets:
(define let*→nested-unary-lets
(match-rewriter (`(let*((,<var> ,<val>) ...) ,<expr1> ,<expr2> ...)
我真的很困惑如何匹配这个。我需要返回:
`(let((,<var1> ,<val1>)) let((,<var2> ,<val2>)) let((...)) ... )...) ,<expr1> . ,@<expr2>)
但是嵌套让我很难过。任何建议表示赞赏。
好的,这是我最好的尝试:
(define let*→nested-unary-lets
(match-rewriter
(`(let* (()) ,<expr1> ,<expr2> ...)
(`(let () ,<expr1> . ,<expr2>)))
(`(let* ((,<var1> ,<val1>) (,<var2> ,<val2>) ...) ,<expr1> ,<expr2> ...)
`(let ((,<var1> ,<val1>) (let*→nested-unary-lets
'(let* ((,<var2> ,<val2>) ...) ,<expr1> . ,<expr2>)))))
))
但这就是它的行为方式:
(let*→nested-unary-lets '(let* ((a 1) (b (+ a 1)) (c (+ a b))) (displayln c))) '(让((一1) (let*→nested-unary-let '(让* (((b c) ((+ a 1) (+ a b))) ...) (displayln c))))))
我对以下参数的顺序感到困惑:
(let* (((b c) ((+ a 1) (+ a b)))
在我看来应该是:
(let* ((b (+ a 1)) (c (+ a b)))
此外,如果能够执行对let*→nested-unary-lets 的调用而不是仅打印为文本,那就太好了。
【问题讨论】:
-
这将非常复杂。这是可能的,编译器会这样做,但这并不简单。考虑
<val1>是否引用<var2>。您将不得不进行定点分解。希望我有时间向您详细介绍。 -
@luqui:
let*中不允许前向引用——你只能引用更早的变量。如果var1在任何地方使用了变量var2,它将引用let*之外的绑定。 -
@Jeremiah,哦,那应该很容易。
let*是递归的吗?我假设在 Haskell 中像let一样工作。感谢您的澄清。 -
@luqui:是的,
let*是递归的,我同意它应该很容易做到。 -
不,
letrec是递归的。
标签: scheme racket let rewriting