From: mmcconnell17704 on 7 Feb 2005 10:36 For a student in an AI course, one textbook I'd recommend is _Lisp_, 3rd. ed. (or 2nd), by Winston and Horn. It was written partly for students whose next course was going to be AI. As David says, the Hyperspec is the online reference for "all the built-in functions".
From: Alan Crowe on 7 Feb 2005 10:46 fix(a)tamu.edu quested: > And I want (deriv-eval '(* x x) 'x 5) to return 10. CL-USER(116): (defun deriv-eval (expr var val) (progv (list var) (list val) (eval (deriv expr var)))) DERIV-EVAL CL-USER(117): (deriv-eval '(* x x) 'x 5) 10 Although the names are unrelated, PROGV is a variant of LET. You could come to this code in two steps. First we cheat with CL-USER(118): (defun cheating-deriv-eval (expr var val) (declare (ignore var)) (let ((x val)) (declare (special x)) (eval (deriv expr var)))) Which gives the right answer, but only because we are ignoring VAR and hard-coding X as the name of our variable. The issue is that this: CL-USER(113): (let ((x (quote a)) (y (quote b))) (let ((x 5) ;supposed to bind a to 5 (y 7));supposed to bind b to 7 (+ a b))) Error: Attempt to take the value of the unbound variable `A'. [condition type: UNBOUND-VARIABLE] doesn't work, because first LET helps us by not evaluating the variable names, x and y, and then LET thwarts us by not evaluating the variable names, x and y. We need to use PROGV on the inner binding CL-USER(114): (let ((x (quote a)) (y (quote b))) (progv (list x y) (list 5 7) (+ a b))) 12 Success! Why does nobody know about PROGV? Well, take a look at the body form of my example (+ A B). If we know that the varibles are going to be called A and B we can type them directly into a LET, and not bother with PROGV at all. PROGV only makes sense when the variable names are not known until runtime. Hence the comment at the bottom of http://www.franz.com/support/documentation/6.2/ansicl/dictentr/progv.htm Among other things, progv is useful when writing interpreters for languages embedded in Lisp; it provides a handle on the mechanism for binding dynamic variables. Alan Crowe Edinburgh Scotland
From: David Sletten on 7 Feb 2005 12:27 Alan Crowe wrote: > fix(a)tamu.edu quested: > >>And I want (deriv-eval '(* x x) 'x 5) to return 10. > > > CL-USER(116): (defun deriv-eval (expr var val) > (progv (list var) (list val) > (eval (deriv expr var)))) > DERIV-EVAL > CL-USER(117): (deriv-eval '(* x x) 'x 5) > 10 > > Although the names are unrelated, PROGV is a variant of LET. > You could come to this code in two steps. > First we cheat with > > CL-USER(118): (defun cheating-deriv-eval (expr var val) > (declare (ignore var)) > (let ((x val)) > (declare (special x)) > (eval (deriv expr var)))) > > Which gives the right answer, but only because we are > ignoring VAR and hard-coding X as the name of our variable. > > The issue is that this: > > CL-USER(113): (let ((x (quote a)) > (y (quote b))) > (let ((x 5) ;supposed to bind a to 5 > (y 7));supposed to bind b to 7 > (+ a b))) > Error: Attempt to take the value of the unbound variable `A'. > [condition type: UNBOUND-VARIABLE] > > doesn't work, because first LET helps us by not evaluating > the variable names, x and y, and then LET thwarts us by not > evaluating the variable names, x and y. > > We need to use PROGV on the inner binding > > CL-USER(114): (let ((x (quote a)) > (y (quote b))) > (progv (list x y) > (list 5 7) > (+ a b))) > 12 > > Success! > > Why does nobody know about PROGV? Well, take a look at the > body form of my example (+ A B). If we know that the > varibles are going to be called A and B we can type them > directly into a LET, and not bother with PROGV at all. > PROGV only makes sense when the variable names are not known > until runtime. Hence the comment at the bottom of > > http://www.franz.com/support/documentation/6.2/ansicl/dictentr/progv.htm > > Among other things, progv is useful when writing > interpreters for languages embedded in Lisp; it > provides a handle on the mechanism for binding dynamic > variables. > > Alan Crowe > Edinburgh > Scotland > Nice, Alan. That eliminates the need to muck around with a global X. Thanks for the explanation. David Sletten
From: David Sletten on 7 Feb 2005 12:38
fix wrote: > > David Sletten wrote: > >> 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))) >> > > But I am not too sure how it works. > The setf is giving a value to the variable, > and the second line is differentiating expr with respect to a number? > > ... [snip] ... > In the more verbose version we store the value of the derivation in a temporary variable, DERIVANS. This is the derivative expression, e.g., (* x x) -> (* 2 x) [or (+ x x) in your example]. We then assign a value to X and ask Lisp to EVAL the derivative. In the terser example, we simply use the derivative directly rather than storing it temporarily. The fact that we've already assigned a value to X is irrelevant. Your derivative code isn't evaluating variables, is it? It's simply looking for the symbol with respect to which you are differentiating right? In other words, differentiating 3x^2 - 4x wrt x is 6x - 4 regardless of the value of x. Even if you know ahead of time that x = 3 you can't evaluate 3(3^2) - 4(3) and then take the derivative. In any case, take a look at Alan's example. He has a better approach. David Sletten |