Why does SBCL eval function lose the macrolet it's running in?

纵然是瞬间 提交于 2019-12-23 17:58:21

问题


(print x) prints exactly what I want to eval, but (eval x) fails, but if I run x it works! What am I missing?
Please tell me why this doesn't work, or if I'm doing something stupid.
I'm trying to print a table of dynamic size and setting lambda variables to eventually evaluate an expression for each cell in the table.
BTW I figured out why eval fails. (eval x) is losing the macrolet, but WHY?!
This works:

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

and it prints what I want it to:

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

If I change that "print" to "eval" I get

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

but if I run what it printed (inside the macrolet) it works!

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

and it prints

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

I have heard "eval is evil" but I need the backquote to get the right evaluation order and evaluate some arguments but not others. Print is a good debug tool, but then I'm missing something with eval. Does eval lose the macrolet?

! That's it. I defined those two macrolet macros as defmacros and then eval works!

Why?! Eval is losing the macrolet. (I'm new to macrolet and no lisp genius)
Or, how do I do this without eval?
Any general notes on my code would be nice too. Is this over complicated?
Also, errors in macros seem to get awkward error messages. Any help with that?

$ sbcl
This is SBCL 1.1.2-1.fc18, an implementation of ANSI Common Lisp.


回答1:


EVAL in Common Lisp only evaluates in a current dynamic environment and the null lexical environment. Enclosing it in lexical constructs like MACROLET, LET, ... or similar is not going to work.



来源:https://stackoverflow.com/questions/17483503/why-does-sbcl-eval-function-lose-the-macrolet-its-running-in

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!