Discussion:
(newbie) help with 'with-gensyms' required
(too old to reply)
2006-12-24 00:10:41 UTC
Permalink
OK, so I'm a newbie. But I don't think I'm particularly stupid. I'm
working through Practical common lisp. Everything working OK until I start
on the test framework.

What I've typed looks like

----------------
(defmacro combine-results (&body forms)
(with-gensyms (result)
`(let ((,result t))
,@(loop for f in forms collect `(unless ,f (setf ,result nil)))
,result)))

(defmacro check (&body forms)
`(combine-results
,@(loop for f in forms collect `(report-result ,f ',f))))

(defun report-result (result form)
(format t "~:[FAIL~;pass~] ... ~a~%" result form)
result)

(defun test-+ ()
(check
(= (+ 1 2) 3)
(= (+ 1 2 3) 6)
(= (+ -1 -3) -4)))
---------------------

Which I'm pretty sure is correct, upto the point I've reached.

I'm using Cormon lisp, because I've found I 'get it' and emacs/slime doesn't
work for me (which isn't to say I can't get it to work, it does work just
fine, I just prefer corman lisp, so far).

Cormon lisp jacks up about the 'with-gensysms' call. Which results in
'result' being unbound and then of course, nothing works. A quick google
shows that maybe 'with-unique-names' might be a better choice, but that did
the same thing. So, what am I doing wrong here?
Zach Beane
2006-12-24 00:12:08 UTC
Permalink
Post by
What I've typed looks like
----------------
(defmacro combine-results (&body forms)
(with-gensyms (result)
`(let ((,result t))
,result)))
[snip]
Post by
Which I'm pretty sure is correct, upto the point I've reached.
Not quite.
Post by
Cormon lisp jacks up about the 'with-gensysms' call.
WITH-GENSYMS isn't standard, but is defined in PCL chapter 8 (among
other places).
Post by
So, what am I doing wrong here?
Define WITH-GENSYMS before trying to use it. Here's the definition
from PCL:

(defmacro with-gensyms ((&rest names) &body body)
`(let ,(loop for n in names collect `(,n (gensym)))
,@body))

Zach
Kaz Kylheku
2006-12-24 09:28:18 UTC
Permalink
Post by
OK, so I'm a newbie. But I don't think I'm particularly stupid. I'm
working through Practical common lisp. Everything working OK until I start
on the test framework.
What I've typed looks like
----------------
(defmacro combine-results (&body forms)
(with-gensyms (result)
`(let ((,result t))
,result)))
This COMBINE-RESULTS is basically a non-short-circuiting boolean AND.
That is to say, it evaluates the forms from left to right, and does not
stop evaluating the forms when it encounters one which yields false. It
returns T if, and only if, all of the forms yield non-NIL values,
otherwise NIL. Precisely because it's non short-circuiting, it can be
implemented as a function. And in fact, this function can be a thin
wrapper for the EVERY function, which takes a predicate to be applied
to every element, and a sequence. We just want to test the elements
themselves, so the predicate we use is IDENTITY:

(defun combine-results (&rest values)
(every #'identity values))

Now we are closer to what might be legitimately called practical Common
Lisp: not wasting time on writing unnecessary macros. However it can't
go unmentioned that this version of COMBINE-RESULTS is subject to the
implementation's limits on the number of arguments that a function may
take.
Post by
Cormon lisp jacks up about the 'with-gensysms' call. Which results in
'result' being unbound and then of course, nothing works. A quick google
shows that maybe 'with-unique-names' might be a better choice, but that did
the same thing. So, what am I doing wrong here?
Reporting a problem with a macro, without showing the actual definition
of it that you are using.

Based on what I know about WITH-GENSYMS, you're using it correctly.

It's just a trivial keystroke saver which saves you from typing:

(let ((result (gensym))) ...)

or (if the symbol is to be meaningfully named):

(let ((result (gensym "RESULT-"))) ...)

So try these, or get a working WITH-GENSYMS from somewhere.
Bill Atkins
2006-12-24 14:46:16 UTC
Permalink
Post by Kaz Kylheku
This COMBINE-RESULTS is basically a non-short-circuiting boolean AND.
That is to say, it evaluates the forms from left to right, and does not
stop evaluating the forms when it encounters one which yields false. It
returns T if, and only if, all of the forms yield non-NIL values,
otherwise NIL. Precisely because it's non short-circuiting, it can be
implemented as a function. And in fact, this function can be a thin
wrapper for the EVERY function, which takes a predicate to be applied
to every element, and a sequence. We just want to test the elements
(defun combine-results (&rest values)
(every #'identity values))
Now we are closer to what might be legitimately called practical Common
Lisp: not wasting time on writing unnecessary macros. However it can't
go unmentioned that this version of COMBINE-RESULTS is subject to the
implementation's limits on the number of arguments that a function may
take.
But doesn't EVERY short-circuit, too?

CL-USER 1 > (every #'print '(1 2 nil 3 4))

1
2
NIL
NIL
Alex Mizrahi
2006-12-24 14:48:27 UTC
Permalink
(message (Hello 'Bill)
(you :wrote :on '(Sun, 24 Dec 2006 09:46:16 -0500))
(

BA> But doesn't EVERY short-circuit, too?

every does, but arguments of a function are always evaluated. so forms will
be evaluated before every will be called

)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
"People who lust for the Feel of keys on their fingertips (c) Inity")
Bill Atkins
2006-12-24 17:55:47 UTC
Permalink
Post by Alex Mizrahi
BA> But doesn't EVERY short-circuit, too?
every does, but arguments of a function are always evaluated. so forms will
be evaluated before every will be called
Ah, gotcha.
Richard
2007-08-24 01:16:12 UTC
Permalink
Post by Kaz Kylheku
Post by
OK, so I'm a newbie. But I don't think I'm particularly stupid. I'm
working through Practical common lisp. Everything working OK until I start
on the test framework.
What I've typed looks like
----------------
(defmacro combine-results (&body forms)
(with-gensyms (result)
`(let ((,result t))
,result)))
This COMBINE-RESULTS is basically a non-short-circuiting boolean AND.
That is to say, it evaluates the forms from left to right, and does not
stop evaluating the forms when it encounters one which yields false. It
returns T if, and only if, all of the forms yield non-NIL values,
otherwise NIL. Precisely because it's non short-circuiting, it can be
implemented as a function. And in fact, this function can be a thin
wrapper for the EVERY function, which takes a predicate to be applied
to every element, and a sequence. We just want to test the elements
(defun combine-results (&rest values)
(every #'identity values))
Now we are closer to what might be legitimately called practical Common
Lisp: not wasting time on writing unnecessary macros. However it can't
go unmentioned that this version of COMBINE-RESULTS is subject to the
implementation's limits on the number of arguments that a function may
take.
Post by
Cormon lisp jacks up about the 'with-gensysms' call. Which results in
'result' being unbound and then of course, nothing works. A quick google
shows that maybe 'with-unique-names' might be a better choice, but that did
the same thing. So, what am I doing wrong here?
Reporting a problem with a macro, without showing the actual definition
of it that you are using.
Based on what I know about WITH-GENSYMS, you're using it correctly.
(let ((result (gensym))) ...)
(let ((result (gensym "RESULT-"))) ...)
So try these, or get a working WITH-GENSYMS from somewhere.
Thank you so much for the reply to the question. I too was having
trouble with the WITH-GENSYMS in "Practical Common Lisp"
Kaeland Chatman
2020-09-23 05:38:07 UTC
Permalink
Post by Kaz Kylheku
OK, so I'm a newbie. But I don't think I'm particularly stupid. I'm
working through Practical common lisp. Everything working OK until I start
on the test framework.
What I've typed looks like
----------------
(defmacro combine-results (&body forms)
(with-gensyms (result)
`(let ((,result t))
,result)))
This COMBINE-RESULTS is basically a non-short-circuiting boolean AND.
That is to say, it evaluates the forms from left to right, and does not
stop evaluating the forms when it encounters one which yields false. It
returns T if, and only if, all of the forms yield non-NIL values,
otherwise NIL. Precisely because it's non short-circuiting, it can be
implemented as a function. And in fact, this function can be a thin
wrapper for the EVERY function, which takes a predicate to be applied
to every element, and a sequence. We just want to test the elements
(defun combine-results (&rest values)
(every #'identity values))
Now we are closer to what might be legitimately called practical Common
Lisp: not wasting time on writing unnecessary macros. However it can't
go unmentioned that this version of COMBINE-RESULTS is subject to the
implementation's limits on the number of arguments that a function may
take.
Cormon lisp jacks up about the 'with-gensysms' call. Which results in
'result' being unbound and then of course, nothing works. A quick google
shows that maybe 'with-unique-names' might be a better choice, but that did
the same thing. So, what am I doing wrong here?
Reporting a problem with a macro, without showing the actual definition
of it that you are using.
Based on what I know about WITH-GENSYMS, you're using it correctly.
(let ((result (gensym))) ...)
(let ((result (gensym "RESULT-"))) ...)
So try these, or get a working WITH-GENSYMS from somewhere.
Thank you so much for the reply to the question. I too was having
trouble with the WITH-GENSYMS in "Practical Common Lisp"
I also had a bit of trouble with WITH-GENSYMS. Thank you all for the helpful replies.
Loading...