macros - 方案;宏列表中的错误漏洞

标签 macros scheme lisp

因此,对于一项大学作业,我们被要求使用宏,但我发现很难理解如何在方案中实现代码(我们在一个类中从反转字符串到构建解释器)。

(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 reportexamples of how the macros for these are made ,但它们可能不是最简单的重写为像您的 interpeter 那样将代码作为结构的函数。但是,使用报告来理解表格可能与在此处发布问题一样有效。

关于macros - 方案;宏列表中的错误漏洞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40193352/

相关文章:

c++ - 如何在 C 宏中连接变量字符串和文字字符串?

c++ - C/C++ 防止宏在宏内展开

vector - 通过附加向量来改变方案中的向量

algorithm - Miller-Rabin Scheme 实现不可预测的输出

recursion - clojure 递归 conj 列表

list - Lisp 列表中的不完整输出,# 给出的列表深度超过 4

c++ - '_T' 未在此范围内声明?

emacs - 如何避免 emacs 宏中急切的宏扩展失败?

scheme - “continuation prompt?”到底是什么

lisp - 什么是 "Lisp program that writes other programs"?