因此,对于一项大学作业,我们被要求使用宏,但我发现很难理解如何在方案中实现代码(我们在一个类中从反转字符串到构建解释器)。
(define macro-alist
`((and ,(λ (e)
(let ((forms (cdr e)))
(cond ((null? forms) '#t)
((null? (cdr forms)) (car forms))
(else `(if ,(car forms) (and ,@(cdr forms)) #f))))))
;(or ,error)
;(let ,error)
;(cond ,error)
(if ,(λ (e) (let ((guard (cadr e))
(then-part (caddr e))
(else-part (cadddr e)))
`((%if ,guard (λ () ,then-part) (λ () ,else-part))))))
))
我们被要求在周末“填写 macro-alist 中的错误保留”,我发现这很难。 我找到了一些资源并将它们与我自己的简要知识相结合:
`((or ,(lambda (e)
(and (list-strictly-longer-than? e 0)
(equal? (list-ref e 0) 'or)
(letrec ([visit (lambda (i)
(if(null? i)
#t
(and (is-exression? (car i))
(visit (cdr i)))))])
(visit (cdr e)))))))
`((let ,(lambda (e)
(and (proper-list-of-given-length? e 3)
(equal? (car e) 'let)
(list? (cadr e))
(is-expression? (list-ref e 2))
(lectrec ([visit (trace-lambda visit (i a)
(if(null? i)
#t
(and (proper-list-of-given-length? (car i) 2)
(is-identifier? (caar i))
(is-expression? (cadar i))
(not (member (caar i) a))
(visit (cdr i) (cons (caar i) a)))))])
(visit (cadr e) '()))))))
`((cond ,(lambda (e)
(and (list-strictly-longer-than? e 1)
(equal? (car v) 'cond)
(lectrec ([visit (lambda (i)
(if (null? (cdr i))
(is-else-clause? (car i))
(if (pair? (cdr i))
(and (cond? (car i))
(visit (cdr i))))))])
(visit (cdr e)))))))
对于 or、let 和 cond。我想知道这些是否正确或者我是否接近。我不太了解一般的宏或方案,因此我将不胜感激一些有关如何操作的信息/帮助。
最佳答案
如果您查看和
的实现:
(define expand-and
(λ (e)
(let ((forms (cdr e)))
(cond ((null? forms) '#t)
((null? (cdr forms)) (car forms))
(else `(if ,(car forms) (and ,@(cdr forms)) #f))))))
(expand-and '(and)) ; ==> #t
(expand-and '(and a)) ; ==> a
(expand-and '(and a b)) ; ==> (if a (and b) #f)
我注意到两件事。它并没有真正仔细检查第一个元素是 和
或者它是否是一个列表。也许解释器不会使用它,除非它已经检查过了?
其次,您似乎不需要扩展所有内容。如您所见,您最终可能会得到一些代码 + 和
以及更少的参数。无需递归,因为评估器会为您完成。
我认为您想多了。对于 或
它应该非常相似:
(expand-or '(or)) ; ==> #f
(expand-and '(or a b c)) ; ==> (let ((unique-var a)) (if unique-var unique-var (or b c)))
let 绑定(bind)可防止对 a
进行双重评估,但如果您没有副作用,您可以将其重写为 (if a a (or b))
。与 and
一样,or
可能会扩展为使用 or
,参数比原来的少。这个技巧你也可以用 cond
来做:
(cond (a b c)
...) ; ==>
(if a
(begin b c)
(cond ...))
let
不需要这个,因为如果你掌握了 map
,它可能是最简单的:
(let ((a x) (c y))
body ...) ; ==>
((lambda (a c) body ...) x y)
The report有examples of how the macros for these are made ,但它们可能不是最简单的重写为像您的 interpeter 那样将代码作为结构的函数。但是,使用报告来理解表格可能与在此处发布问题一样有效。
关于macros - 方案;宏列表中的错误漏洞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40193352/