|
|
 | | From: | Dawgmatix | | Subject: | Help with this code? | | Date: | 22 Jan 2005 16:06:42 -0800 |
|
|
 | Am working through PAIP by Senor Norvig.
1) Could anyone explain this code please
(defun generate-all (phrase) "Generate a list of all possible expansions of this phrase." (cond ((null phrase) (list nil)) ((listp phrase) (combine-all (generate-all (first phrase)) (generate-all (rest phrase)))) ((rewrites phrase) (mappend #'generate-all (rewrites phrase))) (t (list (list phrase)))))
(defun combine-all (xlist ylist) "Return a list of lists formed by appending a y to an x. E.g., (combine-all '((a) (b)) '((1) (2))) -> ((A 1) (B 1) (A 2) (B 2))." (mappend #'(lambda (y) (mapcar #'(lambda (x) (append x y)) xlist)) ylist))
2) Second , could someone tell me in general what happens in tha case of a form (lambda1 (......( lambda2.........))) Ie a lambda placed within a lambda
Thanks.
|
|
 | | From: | John Thingstad | | Subject: | Re: Help with this code? | | Date: | Sun, 23 Jan 2005 02:17:25 +0100 |
|
|
 | On 22 Jan 2005 16:06:42 -0800, Dawgmatix wrote:
> Am working through PAIP by Senor Norvig. > > > 1) Could anyone explain this code please >
I'll give it a shot. First we indent the code correctly.
(defun generate-all (phrase) "Generate a list of all possible expansions of this phrase." (cond ((null phrase) (list nil)) ((listp phrase) (combine-all (generate-all (first phrase)) (generate-all (rest phrase)))) ((rewrites phrase) (mappend #'generate-all (rewrites phrase))) (t (list (list phrase))))) This is a conditional. In the first case phrase is null and we return a empty lisp '()
In the second case we are traversing the list depth first. Say we has (This (is (just)) a silly (sentence))
In a tree form this would look as:
[This [->] a silly [->] [is [->] [sentence] [just] It starts by traversing the first element and continues to go further down in the first recusitivly until it encounters something that is not a list. Then it moves on to the next element (the (generate-all (rest phrase)) So we get "This is just a silly list" as the traversal iorder.
Nor sure exactly what rewites does but it's a fair bet it rewrites the sentence. The last option (t) is chosen is the element is a atom in which case it returns ((atom))
(defun combine-all (xlist ylist) "Return a list of lists formed by appending a y to an x. E.g., (combine-all '((a) (b)) '((1) (2))) -> ((A 1) (B 1) (A 2) (B 2))." (mappend #'(lambda (y) (mapcar #'(lambda (x) (append x y)) xlist)) ylist))
Not entirely sure what mappens does as it is not included. mapcar applies the given lambda function to all the elements in the list. in this case it takes the y from the outer list and combines it the elements xlist in turn.
> > 2) Second , could someone tell me in general what happens > in tha case of a form > (lambda1 (......( lambda2.........))) > Ie a lambda placed within a lambda > > Thanks. >
Not sure what you mean. lambda is just a anonymous function. Nothing spetacular happens. It totally depends on what's in the ...
It's like asking what happens when you call a function within a function.
-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
|
|
 | | From: | Pascal Bourguignon | | Subject: | Re: Help with this code? | | Date: | 23 Jan 2005 07:38:51 +0100 |
|
|
 | "Dawgmatix" writes: > 2) Second , could someone tell me in general what happens > in tha case of a form > (lambda1 (......( lambda2.........))) > Ie a lambda placed within a lambda
It depends on how the second lambda is used.
(lambda (...) ...)
returns an anonymous function.
eg. (lambda (x) (+ (sin x) (cos x)))
(lambda (x) (* x x))
(lambda (f) (funcall f (/ pi 4)))
What you can do with function _values_, is to _call_ them:
(defparameter f1 (lambda (x) (* x x))) (let ((f2 (lambda (x) (+ (sin x) (cos x))))) (funcall f1 (funcall f2 (/ pi 3))))
--> 1.8660254037844386466L0 about: (sin(pi/3)+cos(pi/3))^2
This one is a function that takes a function as argument:
(lambda (f) (funcall f (/ pi 4)))
You could use it like this:
(defparameter g (lambda (f) (funcall f (/ pi 4))))
(funcall g (function sin)) --> 0.70710678118654752444L0 about: sin(pi/4) (funcall g (function cos)) --> 0.70710678118654752444L0 about: cos(pi/4)
Of course instead of an existing named function you could pass it an anonymous function:
(funcall g (lambda (x) (* x x))) --> 0.6168502750680849137L0 about: (pi/4)^2
Also, an anonymous function can return a function: (lambda (x) (lambda (y) (+ x y)))
is an anonymous function that returns a function that increment its argument by the value of the argument to the first function.
(defparameter h (lambda (x) (lambda (y) (+ x y)))) (funcall h 1) --> # (function-lambda-expression (funcall h 1))) --> (LAMBDA (Y) (+ X Y)) (funcall (funcall h 1) 3) --> 4 (funcall g h) --> # (function-lambda-expression (funcall g h)) --> (LAMBDA (Y) (+ X Y)) (funcall (funcall g h) 1) --> 1.7853981633974483096L0 (about 1+pi/4)
Note that sometimes, lambda is only lambda:
(funcall (lambda (x) `(lambda (y) (* y ,x))) 3) --> (LAMBDA (Y) (* Y 3))
which is not a function, but a mere list whose first symbol is LAMBDA. Such a list whose first symbol is LAMBDA, can be used as a function literal, a function designator in the first place of a p:
((lambda (x) `(lambda (y) (* y ,x))) 3) --> (LAMBDA (Y) (* Y 3))
((lambda (x) (* x (1+ x))) 2) --> 6
An anonymous function can call an anonymous function:
(lambda (x) ((lambda (y) (* y y)) (1+ (/ x 2))))
is the function x |--> (1+x/2)^2 :
(funcall (lambda (x) ((lambda (y) (* y y)) (1+ (/ x 2)))) 2) --> 4 ((lambda (x) ((lambda (y) (* y y)) (1+ (/ x 2)))) 2) --> 4 ((lambda (x) ((lambda (y) (* y y)) (1+ (/ x 2)))) 3) --> 25/4
In conclusion, anything can happen when several imbricated s-exp contains the symbol lambda, you have to analyse the meaning of the s-exps.
-- __Pascal Bourguignon__ http://www.informatimago.com/
|
|
|