From: mmcconnell17704 on
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
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
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
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
First  |  Prev  | 
Pages: 1 2 3
Next: Fas->Lsp Decompiler Project