方案:模式匹配语法

发布于 2024-10-22 02:18:16 字数 2006 浏览 6 评论 0原文

这是对之前帖子的编辑。我重新发布它是因为我认为原件没有得到更多的浏览,因为我已经接受了部分答案。

我编写了一个函数 ma​​tch-rewriter ,它只是 match-lambda ,只不过如果没有找到匹配项,它会返回其参数。

使用匹配重写器,我希望能够编写可以传递给另一个函数rewrite的规则,如下所示:

#| (rewrite rule s) repeatedly calls unary function 'rule' on every "part" 
    of s-expr s, in unspecified order, replacing each part with result of rule, 
    until calling rule makes no more changes to any part. 
     Parts are s, elements of s, and (recursively) parts of the elements of s. (define (rewrite rule s) |#

  (let* ([with-subparts-rewritten
          (if (list? s) (map (λ (element) (rewrite rule element)) s) s)]
         [with-also-rule-self (rule with-subparts-rewritten)])
    (if (equal? with-also-rule-self with-subparts-rewritten)
        with-also-rule-self
        (rewrite rule with-also-rule-self))))

这是正确用法的示例:

(define arithmetic 
   (match-rewriter (`(+ ,a ,b) (+ a b)) 
                (`(* ,a ,b) (* a b)) 
                ))
(rewrite arithmetic '(+ (* 2 (+ 3 4)) 5))

==>

19

现在我已经写了:

(define let→λ&call
  (match-rewriter (`(let ((,<var> ,<val>) . (,<vars> ,<vals>)) ,<expr> . ,<exprs>)
                   `((λ (,<var> . ,<vars>) ,<expr> . ,<exprs>) ,<val> . ,<vals>))))

将 let 实现为 lambda 调用,但这就是它的行为方式:

(rewrite let→λ&call '(let((x 1) (y 2) (z 3)) (displayln x) (displayln y) (displayln z)))
'((λ (x y 2)
    (displayln x)
    (displayln y)
    (displayln z))
  1
  z
  3)

我不得不说,这真的让我难住了。奇怪的是,这个调用:

(rewrite let→λ&call '(let((w 0) (x 1) (y 2) (z 3)) (displayln w) (displayln x) (displayln y) (displayln z)))
'(let ((w 0) (x 1) (y 2) (z 3))
   (displayln w)
   (displayln x)
   (displayln y)
   (displayln z))

只返回它的参数,这意味着匹配重写器没有找到该模式的匹配项。

任何建议表示赞赏。

谢谢。

This was an edit to an earlier post. I am reposting it because I think the original isn't getting any more views since I accepted a partial answer already.

I have written a function match-rewriter which is just match-lambda except that it returns its argument if no match is found.

Using match rewriter I want to be able to write rules that can be passed to another function rewrite which is this:

#| (rewrite rule s) repeatedly calls unary function 'rule' on every "part" 
    of s-expr s, in unspecified order, replacing each part with result of rule, 
    until calling rule makes no more changes to any part. 
     Parts are s, elements of s, and (recursively) parts of the elements of s. (define (rewrite rule s) |#

  (let* ([with-subparts-rewritten
          (if (list? s) (map (λ (element) (rewrite rule element)) s) s)]
         [with-also-rule-self (rule with-subparts-rewritten)])
    (if (equal? with-also-rule-self with-subparts-rewritten)
        with-also-rule-self
        (rewrite rule with-also-rule-self))))

Here is an example of proper usage:

(define arithmetic 
   (match-rewriter (`(+ ,a ,b) (+ a b)) 
                (`(* ,a ,b) (* a b)) 
                ))
(rewrite arithmetic '(+ (* 2 (+ 3 4)) 5))

==>

19

Now I have written:

(define let→λ&call
  (match-rewriter (`(let ((,<var> ,<val>) . (,<vars> ,<vals>)) ,<expr> . ,<exprs>)
                   `((λ (,<var> . ,<vars>) ,<expr> . ,<exprs>) ,<val> . ,<vals>))))

to implement lets as lambda calls, but this is how it is behaving:

(rewrite let→λ&call '(let((x 1) (y 2) (z 3)) (displayln x) (displayln y) (displayln z)))
'((λ (x y 2)
    (displayln x)
    (displayln y)
    (displayln z))
  1
  z
  3)

which, I have to say, really has me stumped. Strangely this call:

(rewrite let→λ&call '(let((w 0) (x 1) (y 2) (z 3)) (displayln w) (displayln x) (displayln y) (displayln z)))
'(let ((w 0) (x 1) (y 2) (z 3))
   (displayln w)
   (displayln x)
   (displayln y)
   (displayln z))

Just returns its argument, meaning that match-rewriter did not find a match for this pattern.

Any advice is appreciated.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

金兰素衣 2024-10-29 02:18:16

这种模式:

((,<var> ,<val>) . (,<vars> ,<vals>))

不做你想做的事。特别是,它相当于:

((,<var> ,<val>) ,<vars> ,<vals>)

我建议您使用常规的匹配模式,而不是准模式,直到您更好地了解它们的工作原理。其模式是:

(list (list <var> <val>) (list <vars> <vals>) ...)

This pattern:

((,<var> ,<val>) . (,<vars> ,<vals>))

does not do what you want. In particular, it's equivalent to:

((,<var> ,<val>) ,<vars> ,<vals>)

I recommend that you use regular match patterns, rather than quasi-patterns, until you have a better sense of how they work. The pattern for this would be:

(list (list <var> <val>) (list <vars> <vals>) ...)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文