为什么SBCL eval函数会丢失它运行的宏?

时间:2013-07-05 07:36:28

标签: macros lisp eval common-lisp sbcl

(print x)打印出我想要的eval,但是(eval x)失败, 但如果我运行x它有效!我错过了什么?
请告诉我为什么这不起作用,或者我做了一些愚蠢的事情。 我试图打印一个动态大小的表并设置lambda变量,以最终评估表中每个单元格的表达式。
顺便说一下我弄清楚为什么eval会失败。 (eval x)正在丢失宏,但是为什么?!
这有效:

(defvar varlist '(a b c d))
(defvar vvars   '(c d))
(defvar hvars   '(a b))
(macrolet ((AlternateVariable (var &rest body)
               `(dolist (,var '(nil t)) ,@body))
           (AlternateVariables (varlist &rest body)
               (if (null varlist)
                   (cons 'progn body)
                   `(AlternateVariable  ,(car varlist)
                    (AlternateVariables ,(cdr varlist) ,@body)))))
      (let ((listvarlist (cons 'list varlist)))
        (print
         `(AlternateVariables ,(reverse vvars)
            (AlternateVariables ,(reverse hvars)
              (format t "row=~S~%" ,listvarlist) ))))
      nil)

并打印出我想要的内容:

(alternatevariables (d c)
 (alternatevariables (b a) (format t "row=~S~%" (list a b c d)))) 

如果我改变了那个" print"到" eval"我得到了

; in: alternatevariables (d c)
;     (B A)
; caught warning:
;   undefined variable: a

但如果我运行它打印的内容(在macrolet内部)就可以了!

(macrolet ((AlternateVariable (var &rest body)
               `(dolist (,var '(nil t)) ,@body))
           (AlternateVariables (varlist &rest body)
               (if (null varlist)
                   (cons 'progn body)
                   `(AlternateVariable  ,(car varlist)
                    (AlternateVariables ,(cdr varlist) ,@body)))))
  (alternatevariables (d c)
    (alternatevariables (b a) (format t "row=~S~%" (list a b c d))))
  nil)

并打印

row=(nil nil nil nil)
row=(t nil nil nil)
row=(nil t nil nil)
row=(t t nil nil)
row=(nil nil t nil)
row=(t nil t nil)
row=(nil t t nil)
row=(t t t nil)
row=(nil nil nil t)
row=(t nil nil t)
row=(nil t nil t)
row=(t t nil t)
row=(nil nil t t)
row=(t nil t t)
row=(nil t t t)
row=(t t t t)
nil

我听说" eval是邪恶的"但我需要反引用来获得正确的评估顺序并评估一些参数而不是其他参数。打印是一个很好的调试工具,但后来我错过了eval的东西。 eval会丢失宏吗?

!就是这样。我将这两个宏宏定义为defmacros然后eval工作!

为什么?! Eval正在失去宏。 (我是Macrolet的新手,没有lisp天才)
或者,如何在没有评估的情况下这样做?
我的代码上的任何一般注释都会很好。这太复杂了吗?
另外,宏中的错误似乎得到了尴尬的错误消息。对此有何帮助?

$ sbcl
这是SBCL 1.1.2-1.fc18,ANSI Common Lisp的实现。

1 个答案:

答案 0 :(得分:5)

Common Lisp中的

EVAL仅在当前动态环境和null词法环境中进行求值。将它包含在MACROLETLET,......或类似的词汇结构中是行不通的。