方案;宏列表中的错误孔

时间:2016-10-22 14:34:17

标签: 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))))))
    ))

我们被要求填写宏观内容中的错误保留'周末,我发现很难。 我找到了一些资源,并将它们与我自己的简要知识相结合:

`((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)))))))

for or,let and cond。我想知道这些是否正确或我是否关闭。我不太了解宏或计划,所以一些信息/帮助做什么将不胜感激。

1 个答案:

答案 0 :(得分:0)

如果你看一下and的实现:

(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)

我注意到两件事。它并没有真正仔细检查第一个元素是and还是它是一个列表。也许解释器不会使用它,除非它已经检查过这个?

其次,您似乎不需要扩展所有内容。如您所见,最终可能会使用较少的参数+ and。不需要递归,因为评估者会为你做这件事。

我认为你过度思考它。对于or,它应该非常相似:

(expand-or '(or))        ; ==> #f
(expand-and '(or a b c)) ; ==> (let ((unique-var a)) (if unique-var unique-var (or b c))) 

let绑定会阻止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之类的结构。然而,使用报告来理解表格可能与在SO上发布问题一样有效。