I have been reading Peter Norvig's (excellent so far) book "Paradigms of AI
Programming". I have been struggling with a problem that has arisen from the
pattern matcher in Chapter 6 Section 2 (page 186 actually). The question I
have is about the function MATCH-IF.
It took me quite awhile to figure out what it was trying to do. I really
wanted to be sure that I understood the use of EVAL and especially the
PROGV, which I have never come across before. The function is as follows:
(defun match-if (pattern input bindings)
"Test an arbitrary expression involving variables
The pattern looks like ((?if code) . rest)"
(and (progv (mapcar #'car bindings)
(mapcar #'cdr bindings)
(eval (second (first pattern))))
(pat-match (rest pattern) input bindings)))
I have read the directly relevant material in the excellent HyperSpec(tm), but
this didn't offer me the solution to my problem. In an attempt to understand
what it is trying to accomplish I tried a few things in the interpreter of
my ACL 4.3 for the Linux operating system.
To my surprise, I thought understood it. It wasn't until I tried to run the
pattern matcher that the problem started. The interpreter gave me the
following error message:
USER(2): (pat-match '(?x ?op ?y is ?z (?if (eql (?op ?x ?y) ?z)))
'(6 + 6 is 12))
Error: attempt to call `?OP' which is an undefined function.
[condition type: UNDEFINED-FUNCTION]
Since I had made a few modifications to the original program and I am unable
to spell correctly and tend to omit pages of material when copying, I
decided to download the source; I ran that with the same error resulting.
I would rather not post the source code in it's entirety, for fear of
angering someone who doesn't want to (re-) read it. Though if someone could
please help me with understanding the following examples (or just how to get
the pattern matcher to work, if they have the book handy) I would be most
appreciative. Thanks.
(let ((this '(a b c)))
(progv '(a b c) '(+ 1 2)
(eval this)))
Is an error. I think I might know why, but some clarification would be
really great. These all result in error:
(progv '(a b c) '(list 1 2)
(eval (a b c)))
(progv '(a b c) '(+ 1 2)
(eval '(a b c)))
(progv '(a b c) '(list 1 2)
(a b c))
(progv '(a b c) '(values 1 2)
(a b c)),
and of course the following work fine:
(progv '(a b c) '(values 1 2)
(eval (list a b c)))
(progv '(a b c) '(values 1 2)
(funcall a b c))
(progv '(a b c) '(+ 1 2)
(eval (list a b c))).
Just what is so special about LIST (or cons)? Why aren't the symbols bound
within the PROGV? Is QUOTE that "powerful"? Am I asking how do you "undo"
QUOTE, or when do the symbols get evaluated (or do they never get evaluated
"underneath" of QUOTE, ever)? The dynamic environment for the PROGV ends at
the closing parenthesis, but encapsulation brings these values out past the
environment, but then how to evaluate it (without eval, or the backtick of
course):
(setf me (progv '(a b c) '(+ 1 2)
#'(lambda () (list a b c))))
(funcall me) => (+ 1 2).
I am reading the HyperSpec(tm), but it is proving to be a rough read, (a
big/detailed document that is). So please accept my apologies for those
answers that are stated in the forementioned (most likely all of them). I
didn't see anything in the FAQ(s) about PROGV.
I know that in the pattern matcher I quote the INPUT. This seems like a job
for the backtick function (or is it macro, probably neither), but I'd really
rather not use it. I know funcall and apply will work, but the solution
offered by Norvig is so elegant I just can't let it go. If anyone could
please help me get to the next page I would be extremely grateful.
I am somewhat regretful for having to resort to actually asking someone for
help, as I usually come up with the solution - however long that may take
(usually very long). I have been trying various things for several days and
can't seem to give it a rest and just use apply or what have you.
The reason for my lack of "trying harder" and "giving up" so soon, so to
speak, is that I am just dying to get to the next page (this is a lie, what
I really want to do is get to the next chapter). So any help would be
greatly appreciated, and please feel free to ignore this entirely too long
of a message. Thanks for your time.
One more question (the nerve of this kid, huh?), why can't you apply the
special DEFUN, this isn't a macro is it (probably implementation specific)?
Steve
(I'll have to go look up the stuff in Norvig: PAIP before I answer the
application-level part, but the language part is easy.)
* Steve Gonedes
| (let ((this '(a b c)))
| (progv '(a b c) '(+ 1 2)
| (eval this)))
|
| Is an error. I think I might know why, but some clarification would be
| really great.
simply put: because a symbol has both a function and a value slot, used in
very distinct contexts. e.g., (a a) is a call to the function binding of
`a' with the variable binding of `a' as the only argument. you can
establish both with a form like this:
(flet ((a (x) (* x x)))
(let ((a 7))
(values #'a a (a a))))
| These all result in error:
|
| (progv '(a b c) '(list 1 2)
| (eval (a b c)))
you're trying to use `a' as a function, which it (probably) isn't. also,
you would send the _result_ of this call to `eval'. if `a' actually was a
function of two arguments, this would probably be even harder to debug.
| (progv '(a b c) '(+ 1 2)
| (eval '(a b c)))
again, you're trying to use `a' as a function, but this is the correct use
of `progv': the variable bindings for `b' and `c' are in effect
dynamically.
| (progv '(a b c) '(list 1 2)
| (a b c))
again, calling `a' as a function, but at a very different time than above.
| and of course the following work fine:
|
| (progv '(a b c) '(values 1 2)
| (eval (list a b c)))
you capture the variable binding of `a' in this case.
| (progv '(a b c) '(values 1 2)
| (funcall a b c))
and here you call `a' directly.
| Just what is so special about LIST (or cons)?
`eval' takes a list as argument.
| Why aren't the symbols bound within the PROGV?
oh, they are. you're just not referring the proper binding.
also try
(progv '(a b c) '(1 2 3)
(eval '(list a b c)))
| I am somewhat regretful for having to resort to actually asking someone
| for help, as I usually come up with the solution - however long that may
| take (usually very long). I have been trying various things for several
| days and can't seem to give it a rest and just use apply or what have
| you.
sometimes, asking for help is the _only_ right thing. usually, however,
it's more important to establish what you already know before you ask for
help, or others will have a hard time actually helping you. in the process
of establishing what I know and what I can't figure out, I have often found
the answer myself, but it's somewhat easier for me to do this when I'm
writing a request for help or (customer) support that I subsequently don't
need to send. if I also felt that asking for help would be bad, I wouldn't
even try this venue.
| One more question (the nerve of this kid, huh?), why can't you apply the
| special DEFUN, this isn't a macro is it (probably implementation
| specific)?
DEFUN is a macro.
#\Erik
--
if you think this year is "97", _you_ are not "year 2000 compliant".
see http://www.naggum.no/emacs/ for Emacs-20-related material.
Steve Gonedes <········@mixcom.com> wrote:
+---------------
| ...some clarification would be really great. These all result in error:
|
| (progv '(a b c) '(list 1 2)
| (eval (a b c)))
+---------------
Try it this way:
> (progv '(a b c) `(,#'list 1 2) ; or (list (function list) 1 2)
(funcall a b c))
==> (1 2)
>
+---------------
| (progv '(a b c) '(values 1 2)
| (funcall a b c))
+---------------
Weird. This one works fine for me. CLtL2 says that "funcall" can take
either a symbol [as in this case] or a function, so it should work for
you, too:
> (progv '(a b c) '(values 1 2)
(funcall a b c))
==> 1
==> 2
>
Could your Lisp be having trouble with "values" in a "progv" (or a "funcall)?
Try it this way [with variable "a" containing a function value instead of a
symbol], and see what happens:
> (progv '(a b c) `(,#'values 1 2)
(funcall a b c))
==> 1
==> 2
>
+---------------
| (progv '(a b c) '(+ 1 2)
| (eval '(a b c)))
+---------------
This one fails for the same reason your very first one did -- "a" doesn't
have a function value, only a variable value (the symbol "+"). Compare:
> (defun a (x y) (* x y)) ; or (setf (symbol-function 'a) #'*)
==> A ; ==> #<SYSTEM-FUNCTION *>
> (progv '(a b c) '(+ 3 4)
(a b c))
==> 12
> (progv '(a b c) '(+ 3 4)
(eval '(a b c))) ; eval still gets the fcn, not symb
==> 12
> (progv '(a b c) `(,#'+ 3 4) ; or (list (function +) 3 4)
(funcall a b c))
==> 7
>
-Rob
-----
Rob Warnock, 7L-551 ····@sgi.com http://reality.sgi.com/rpw3/
Silicon Graphics, Inc. Phone: 650-933-1673 [New area code!]
2011 N. Shoreline Blvd. FAX: 650-933-4392
Mountain View, CA 94043 PP-ASEL-IA