【问题标题】:Scheme rewrite let* as nested unary lets计划将 let* 重写为嵌套的一元让
【发布时间】: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 的调用而不是仅打印为文本,那就太好了。

【问题讨论】:

  • 这将非常复杂。这是可能的,编译器会这样做,但这并不简单。考虑&lt;val1&gt; 是否引用&lt;var2&gt;。您将不得不进行定点分解。希望我有时间向您详细介绍。
  • @luqui:let* 中不允许前向引用——你只能引用更早的变量。如果var1 在任何地方使用了变量var2,它将引用let* 之外的绑定。
  • @Jeremiah,哦,那应该很容易。 let* 是递归的吗?我假设在 Haskell 中像 let 一样工作。感谢您的澄清。
  • @luqui:是的,let* 是递归的,我同意它应该很容易做到。
  • 不,letrec 是递归的。

标签: scheme racket let rewriting


【解决方案1】:

是的,您可以这样做;应该不会太难。具体来说,您需要的关键思想不是尝试一次处理整个列表。相反,您的模式应该将第一个绑定与其他绑定分开,然后将一个 let 包裹在 递归调用 上以调用 let*->nested-unary-lets。

如果您在制定此内容时遇到问题,请告诉我。

【讨论】:

  • 谢谢。我考虑过这一点,但我不确定我是否可以递归地进行模式匹配——我认为它需要某种 letrec 转换。你知道是否有办法使模式匹配的参数成为可选的?我正在尝试将 cond 编写为 if 语句,但我不知道如何在模式匹配中使 else 子句成为可选。
  • 是的,我肯定遇到了麻烦。请参阅我对原始问题的编辑以获得最佳猜测。
  • 好的。我已经弄清楚了模式。我剩下的唯一问题是是否可以递归调用 let*→nested-unary-lets 评估。
  • 嘿:你会考虑选中这个(或其他)答案旁边的“复选框”吗?它会给你一种温暖的模糊感觉,它会让我投票支持 Eli 的同义词提案。
【解决方案2】:

这里是syntax-rules 中的let* 的定义,类似于伪代码,您可以使用它来编写自己的版本:

(let* ((a b) (c d) ...) body ...) === (let ((a b)) (let* ((c d) ...) body ...))
(let* () body ...) === body

您应该能够使用match 将其转换为函数或使用syntax-rules 的宏。

【讨论】:

    猜你喜欢
    • 2011-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2019-02-27
    • 1970-01-01
    • 2015-11-17
    相关资源
    最近更新 更多