From: fix on 6 Feb 2005 16:16 Hi all, I am writing a program to take derivative of a function and evaluate if given a value. "deriv" is the function to do symbolic derivatives, the signiture is defun deriv (expr var) and the function take derivative of expr with respect to var. so if I do (deriv '(* x x) 'x), it returns (+ x x). (Same as 2x, but it doesn't matter.) And I want (deriv-eval '(* x x) 'x 5) to return 10. This is what I have written for deriv-eval: (defun deriv-eval (expr var val) (setf derivans (deriv expr var)) (setf var val) (eval derivans) ) But it doesn't work for the last line, here is the error: Error in KERNEL::UNBOUND-SYMBOL-ERROR-HANDLER: the variable X is unbound. [Condition of type UNBOUND-VARIABLE] I was thinking of, in the first line, get the answer, then give the variable a value, and evaulate. Am I wrong? Thanks. fix.
From: David Sletten on 6 Feb 2005 17:08 fix wrote: > Hi all, > > I am writing a program to take derivative of a function and evaluate if > given a value. > > "deriv" is the function to do symbolic derivatives, the signiture is > defun deriv (expr var) > and the function take derivative of expr with respect to var. > so if I do > (deriv '(* x x) 'x), it returns (+ x x). (Same as 2x, but it doesn't > matter.) > > And I want (deriv-eval '(* x x) 'x 5) to return 10. > > This is what I have written for deriv-eval: > (defun deriv-eval (expr var val) > (setf derivans (deriv expr var)) > (setf var val) > (eval derivans) > ) > > But it doesn't work for the last line, here is the error: > Error in KERNEL::UNBOUND-SYMBOL-ERROR-HANDLER: the variable X is unbound. > [Condition of type UNBOUND-VARIABLE] > > I was thinking of, in the first line, get the answer, then give the > variable a value, and evaulate. Am I wrong? > > Thanks. > fix. > You misunderstand the macro SETF. However, you should be able to see that something is wrong just by looking closely at your code. First, you use SETF to assign a value to a variable named DERIVANS. In other words, you expect SETF to directly use the symbol you provide it to name a variable. In the second case you are trying to use SETF to assign a value not to the variable named VAR but rather to the symbol that VAR refers to. Clearly this is an inconsistency--SETF can't possibly know that you intend indirection in one case but not the other. SETF does not evaluate its first argument, which identifies the 'place' where it is to store the value of the second argument. Here, to indicate that the place is the global variable named by VAR's value, you should use SYMBOL-VALUE. Furthermore, it is better to create a local variable DERIVANS using LET rather than relying on another global variable: (defun deriv-eval (expr var val) (let ((derivans (deriv expr var))) (setf (symbol-value var) val) (eval derivans))) David Sletten
From: Kalle Olavi Niemitalo on 6 Feb 2005 17:54 fix <fix(a)tamu.edu> writes: > And I want (deriv-eval '(* x x) 'x 5) to return 10. I think you mean 25. Here are a few ways to do it. (defun deriv-eval (form variable value) (eval `(let ((,variable ',value)) ,form))) (defun deriv-eval (form variable value) (funcall (coerce `(lambda (,variable) ,form) 'function) value)) If you need to evaluate the expression with multiple different values for the variable (e.g. for a graph), you can modify the latter definition to generate the function just once, hopefully speeding up the process. You could also COMPILE the function at runtime, although that may actually be slower if you then call it just a few times. > (defun deriv-eval (expr var val) > (setf derivans (deriv expr var)) > (setf var val) Suppose the value of VAR is X, and the value of VAL is 5. Then, this (setf var val) will just set VAR to 5, rather than modify X in any way. (setf (symbol-value var) val) would be closer to what you need, but it has two problems: 1. The changed value persists even after the function returns, so it can cause errors if some other part of the program is using the variable X for another purpose. 2. I think, in principle, the form evaluated with EVAL should explicitly declare any special variables it uses. However, the dictionary entry for EVAL says SYMBOL-VALUE is equivalent to it, so I'm not sure the declarations are required in this context. You could fix the first problem with (progv `(,var) `(,val) ...) and the second with (eval `(locally (declare (special ,var)) ,expr)), but that's so much typing that you could as well use one of the lexical-variable solutions I showed above.
From: fix on 6 Feb 2005 19:13 David Sletten wrote: > fix wrote: > >> Hi all, >> >> I am writing a program to take derivative of a function and evaluate >> if given a value. >> >> "deriv" is the function to do symbolic derivatives, the signiture is >> defun deriv (expr var) >> and the function take derivative of expr with respect to var. >> so if I do >> (deriv '(* x x) 'x), it returns (+ x x). (Same as 2x, but it doesn't >> matter.) >> >> And I want (deriv-eval '(* x x) 'x 5) to return 10. >> >> This is what I have written for deriv-eval: >> (defun deriv-eval (expr var val) >> (setf derivans (deriv expr var)) >> (setf var val) >> (eval derivans) >> ) >> >> But it doesn't work for the last line, here is the error: >> Error in KERNEL::UNBOUND-SYMBOL-ERROR-HANDLER: the variable X is >> unbound. >> [Condition of type UNBOUND-VARIABLE] >> >> I was thinking of, in the first line, get the answer, then give the >> variable a value, and evaulate. Am I wrong? >> >> Thanks. >> fix. >> > > You misunderstand the macro SETF. However, you should be able to see > that something is wrong just by looking closely at your code. First, you > use SETF to assign a value to a variable named DERIVANS. In other words, > you expect SETF to directly use the symbol you provide it to name a > variable. In the second case you are trying to use SETF to assign a > value not to the variable named VAR but rather to the symbol that VAR > refers to. Clearly this is an inconsistency--SETF can't possibly know > that you intend indirection in one case but not the other. > > SETF does not evaluate its first argument, which identifies the 'place' > where it is to store the value of the second argument. Here, to indicate > that the place is the global variable named by VAR's value, you should > use SYMBOL-VALUE. Furthermore, it is better to create a local variable > DERIVANS using LET rather than relying on another global variable: > (defun deriv-eval (expr var val) > (let ((derivans (deriv expr var))) > (setf (symbol-value var) val) > (eval derivans))) > > David Sletten I got it. Thanks so much. But is there any website that has all the built-in function of LISP? I am actually using LISP in an AI course, but neither the prof nor the textbook talk much about LISP. Or should I go get another book? Thanks! fix.
From: David Sletten on 7 Feb 2005 00:13
fix wrote: >> (defun deriv-eval (expr var val) >> (let ((derivans (deriv expr var))) >> (setf (symbol-value var) val) >> (eval derivans))) >> This could be even simpler: (defun deriv-eval (expr var val) (setf (symbol-value var) val) (eval (deriv expr val))) > I got it. Thanks so much. But is there any website that has all the > built-in function of LISP? I am actually using LISP in an AI course, but > neither the prof nor the textbook talk much about LISP. Or should I go > get another book? Thanks! > Your one-stop reference is the Common Lisp HyperSpec: http://www.lispworks.com/documentation/HyperSpec/Front/index.htm If you would like to read a helpful text: http://www.gigamonkeys.com/book/ David Sletten |