Pergunta

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

Foi útil?

Solução

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top