Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macros 规范匹配letrec实现是如何工作的?_Macros_Pattern Matching_Scheme_Metaprogramming - Fatal编程技术网

Macros 规范匹配letrec实现是如何工作的?

Macros 规范匹配letrec实现是如何工作的?,macros,pattern-matching,scheme,metaprogramming,Macros,Pattern Matching,Scheme,Metaprogramming,我目前正在将几乎所有Scheme实现都使用的方法移植到另一个Lisp 我在match-letrec中遇到了一堵墙。在中,定义如下: (定义语法匹配let) (语法规则() ((((帕特解释))正文) (匹配表达式(零件正文))) (((pat expr)…正文) (匹配(列表expr…((pat….body))) (uuu.rest) (匹配名为let loop().rest)) )) (定义语法匹配letrec (语法规则() ((vars.body)(匹配letrec helper()var

我目前正在将几乎所有Scheme实现都使用的方法移植到另一个Lisp

我在
match-letrec
中遇到了一堵墙。在中,定义如下:

(定义语法匹配let)
(语法规则()
((((帕特解释))正文)
(匹配表达式(零件正文)))
(((pat expr)…正文)
(匹配(列表expr…((pat….body)))
(uuu.rest)
(匹配名为let loop().rest))
))
(定义语法匹配letrec
(语法规则()
((vars.body)(匹配letrec helper()vars.body)))
(定义语法匹配letrec帮助程序
(语法规则()
(((pat expr var)…)正文)
(letrec((var expr)…)
(匹配let((帕特变量)…)
(见正文)
(v…)身体)
(匹配letrec辅助对象(v…(pat expr tmp))静止体)
))
下面是一个使用时的外观示例(Guile 1.8):

我很难理解这到底是怎么回事。当我用手将其展开到
匹配
时,我得到以下代码(带有由
{g..}
指示的自动符号):

(letrec(#{g1}(列表1(lambda()(列表a x)))
(#{g2}(列表2(lambda()(列表xaЮЮЮ)))
(匹配(列表{g1}{g2})(((xy)(ab))(附加(y)(b)))
自动符号由
match letrec helper
第二条规则中的
tmp
替换生成。此扩展意味着lambda表达式在绑定
x
a
之前进行计算,因此无法捕获它们

有人能解释一下这个语法应该如何正确扩展吗?我遗漏了什么?

你的例子

(match-letrec (((x y) (list 1 (lambda () (list a x))))
               ((a b) (list 2 (lambda () (list x a)))))
  (append (y) (b))
=> (2 1 1 2)
缺少一个紧括号

修复后,会发生以下情况:

> (match-letrec (((x y) (list 1 (lambda () (list a x))))
               ((a b) (list 2 (lambda () (list x a)))))
  (append (y) (b)))
. match: syntax error in pattern in: ((x y) (a b))
连火柴都不行

> (match-let (((x y) (list 1 2)))
    x)
. match: syntax error in pattern in: (x y)
> (match-letrec (((list x y) (list 1 (lambda () (list a x))))
                 ((list a b) (list 2 (lambda () (list x a)))))
  (append (y) (b)))
. match: syntax error in pattern in: ((list x y) (list a b))
以下是修复方法:

(define-syntax match-let
  (syntax-rules (list)
    ((_ ((pat expr)) . body)
     (match expr (pat . body)))
    ((_ ((pat expr) ...) . body)
     (match (list expr ...) ((pat ...) . body)))
    ((_ loop . rest)
     (match-named-let loop () . rest))
    ))
现在您可以执行以下操作:

> (match-let (((list x y) (list 1 2)))
    (list x y))
'(1 2)
letrec仍不工作

> (match-let (((x y) (list 1 2)))
    x)
. match: syntax error in pattern in: (x y)
> (match-letrec (((list x y) (list 1 (lambda () (list a x))))
                 ((list a b) (list 2 (lambda () (list x a)))))
  (append (y) (b)))
. match: syntax error in pattern in: ((list x y) (list a b))

但这会让你更进一步,一旦你理解了这些变化,就可以用工作代码示例问一个新问题。

这在Racket 7.4、Chicken 4.13或Guile 2.2.4中都不起作用。它看起来与你链接的实现完全不同。谢谢。我更新了这个问题,以澄清我引用了simpli在这个问题中,我对Alex Shinn的matcher进行了详细的解释,并添加了一个链接。我将构建最新的Guile并进行查看。