#lang racket
(define (churchify e)
;; Convert expressions in the input language to church-encoded expressions
(match e
[(letrec ([x val] ...) body)
(define expanded-bindings
(append (map (lambda (x-val) `(,x (lambda (v) (quasiquote (,x v))))))
(map churchify (list val ...))))
(quasiquote ((lambda ((unquote-splicing (map cdr expanded-bindings)))
(unquote (churchify body)))
(unquote-splicing (map car expanded-bindings))))]
[(let ([x val] ...) body)
(quasiquote ((lambda ((unquote x) ...)
(unquote (churchify body)))
(unquote-splicing (map churchify (list val ...)))))]
[(lambda (args ...) body)
(quasiquote (lambda ((unquote args) ...)
(unquote (churchify body))))]
[(e1 e2 ...)
(quasiquote (((unquote (churchify e1)))
(unquote (map churchify (list e2 ...)))))]
[(and exprs ...)
(quasiquote ((lambda (x)
(unquote (apply (lambda args
(quasiquote (if (unquote-splicing args) #t #f)))
(map churchify (list exprs ...)))))
#t))]
[(or exprs ...)
(quasiquote ((lambda (x)
(unquote (apply (lambda args
(quasiquote (if (unquote-splicing args) #t #f)))
(map churchify (list exprs ...)))))
#f))]
[(if cond then-expr else-expr)
(quasiquote ((lambda (x)
(unquote (if-then-else (churchify cond)
(churchify then-expr)
(churchify else-expr))))
#t))]
[(prim e1 e2)
(quasiquote ((lambda (x)
(unquote (apply (lookup-prim prim)
(map churchify (list e1 e2)))))
#t))]
[(prim e)
(quasiquote ((lambda (x)
(unquote (lookup-prim prim (churchify e))))
#t))]
[(quote ())
(quote ())]
[datum
datum]
[x
x]))
我尝试运行该代码,但它带来了 chuclify.rkt:6:5: match: 模式中的语法错误 在:(letrec((x val)...)主体) #(130 27) 我不明白如何解决
该错误表明
match
形式中的第一个模式无效。发生这种情况时,解决方法是彻底阅读 match 的文档,以理解它所期望的模式语法。关于符号约定的文档也很重要。
在这种特殊情况下,可以按如下方式纠正第一个模式。
(define (churchify e)
(match e
[`(letrec ([,x ,val] ...) ,body)
(printf "x: ~s~n" x)
(printf "val: ~s~n" val)
(printf "body: ~s~n" body)]))
> (churchify '(letrec ([a 1] [b 2]) (+ a b)))
x: (a b)
val: (1 2)
body: (+ a b)
与
x
匹配的多个值被收集在与匹配选项主体中的 x
绑定的列表中。 val
也会发生同样的情况。因此,您还需要更新代码的其他部分。例如,(map churchify (list val ...))
应该是 (map churchify val)
。
此模式的一个微妙属性是它与
letrec
字面匹配,因为 letrec
出现在准引号 (`
) 中,并且不像 ,
和 x
那样不被引用 (val
)。如果没有此属性,模式将匹配它不应该匹配的表达式,例如以下内容。
(let ([a 1] [b 2]) (+ a b))
(foo ([a 1] [b 2]) (+ a b))