I'm trying to write a function that takes in a list (well, any expression actually), a list of symbols, and a list of values for those symbols, and then evaluates that list as an expression with those symbols assigned to those values. Perhaps my current attempt will explain this better than a description:

This works fairly well, but gives me warnings about undefined variables most of the time (not in the above instance). As I'm new to common lisp, I was wondering if there is a better way of doing this, one that wouldn't produce warnings.

The following gives me warnings (though still returns the correct value):

First, why are you even trying to do that? It is generally recommended that you don't use EVAL, or for that matter PROGV, unless you know exactly what you are doing.

And what are you trying to achieve anyway? PROGV establishes dynamic bindings, and I can't tell if this is what you want... in any case it would almost certainly be better to transform the expression to establish bindings. For lexical bindings:

Maybe it would be better to compile a function and then call it with the arguments. Then it will be possible to reuse the function (in case the expression is needed to be evaluated with many arguments values):

First note: When dealing with things like compiler warnings, its usually good to mention the implementation you are using...

I asked about this on SBCL-help. The response was twofold.

This warning is not issued when SB-EXT:*EVALUATOR-MODE* is :INTERPRET.

When it is :COMPILE, "nontrivial" forms are compiled. The AND macro is trivial; so it was directly interpreted. The OR macro is implemented using LET, and LET is nontrivial. Thus SBCL evaluates (eval '(or p q)) by compiling (lambda () (or p q)) and then FUNCALLing the result. The warning is issued since P and Q were not declared as special variables when the form was compiled.

I made some functions to generate random logical expressions and will write a program that generates programs which take in as input these expressions and output truth values for each of the variables. I need a function that tests the answers the generated programs give to see if they are correct.

Ramarren wrote:It is generally recommended that you don't use EVAL, or for that matter PROGV, unless you know exactly what you are doing.

I know EVAL should generally be avoided, but I wasn't sure how to do it without using EVAL; that's part of what caused me to ask.I did not really understand that about PROGV, so thanks! I was just using it as a LET with a different input format.

dmitry_vk wrote:Maybe it would be better to compile a function and then call it with the arguments.

I was looking for something closer to this. However, in the ultimate program, the expressions sent to this function will contain only logical functions (AND, OR, and NOT), so compiling will probably do more harm than good in this case. Is there a way to get this to work without using COMPILE or EVAL? I tried messing with that code a bit, but I'm pretty new to Lisp and couldn't get it to work.

nuntius wrote:First note: When dealing with things like compiler warnings, its usually good to mention the implementation you are using...

Apologies. I'm using SBCL 1.0.23

nuntius wrote:When it is :COMPILE, "nontrivial" forms are compiled. The AND macro is trivial; so it was directly interpreted. The OR macro is implemented using LET, and LET is nontrivial. Thus SBCL evaluates (eval '(or p q)) by compiling (lambda () (or p q)) and then FUNCALLing the result. The warning is issued since P and Q were not declared as special variables when the form was compiled.

That certainly clears things up. I was very confused about why one worked and not the other. Thanks!

qiemem wrote: However, in the ultimate program, the expressions sent to this function will contain only logical functions (AND, OR, and NOT), so compiling will probably do more harm than good in this case. Is there a way to get this to work without using COMPILE or EVAL?

For constricted languages like that an interpreter or minimal compiler is usually trivial. If you are not going to evaluate the same expression repeatedly, then an interpreter would be better. And a specialized one would likely be faster than one going through entire EVAL machinery. A simple example:

;; if symbol table is very small then an alist might be better(defun build-symbol-table (symbols assignments) (let ((symbol-table (make-hash-table))) (loop for symbol in symbols for assignment in assignments do (setf (gethash symbol symbol-table) assignment)) symbol-table))