 | | From: | Michael Beattie | | Subject: | a noob question | | Date: | Sun, 23 Jan 2005 17:41:29 -0500 |
|
|
 | Why is it that some macros or whatever have double parens around them? Like...
(let ((x 2))) ; this has 2 parens around the x=2 assignment
or
(do ((i 0 (+ i 1))) ; there's 2 parens around the i=0 and the increment ((> i 10) 'done) ; 2 parens around the "end" condition (print i))
I guess part of the question is "what exactly is the template for the do or let macro?"
Mike Beattie
|
|
 | | From: | Tayssir John Gabbour | | Subject: | Re: a noob question | | Date: | 23 Jan 2005 16:07:12 -0800 |
|
|
 | Tayssir John Gabbour wrote: > . (defmacro let- ((&rest inits) &body body) > . `(let ,(loop for i on inits by #'cddr > . collect (list (first i) (second i))) > . ,@body))
Hmm, a nicer version of LET- would be something like:
.. (defmacro let- (inits &body body) .. "Like LET, except does away with a redundant level of parens. .. .. The syntax is: let ({pair}*) declaration* form* => result* .. pair::= var initform .. .. Unlike LET, no var may be without an initform." .. (unless (listp inits) .. (error "let-: init forms need to be within a list. ~S is not a list." inits)) .. (unless (evenp (length inits)) .. (error "let-: an even number of init forms is needed. Found only ~A forms.~%~S" (length inits) inits)) .. `(let ,(loop for i on inits by #'cddr .. collect (list (first i) (second i))) .. ,@body))
Wrestling with Google Groups was a bit frustrating in my last post... Incidentally, that's why there's all those dots prefixing my code, since GG won't indent my posts as I wish.
MfG, Tayssir
|
|
 | | From: | Paul F. Dietz | | Subject: | Re: a noob question | | Date: | Sun, 23 Jan 2005 16:38:48 -0600 |
|
|
 | Michael Beattie wrote: > Why is it that some macros or whatever have double parens around them? > Like... > > (let ((x 2))) ; this has 2 parens around the x=2 assignment > > or > > (do ((i 0 (+ i 1))) ; there's 2 parens around the i=0 and the increment > ((> i 10) 'done) ; 2 parens around the "end" condition > (print i)) > > I guess part of the question is "what exactly is the template for the do > or let macro?"
Because these can have more than one binding.
(let ((x 1) (y 2)) (+ x y)) ==> 3
The end condition of DO is grouped with the end form(s), so it doesn't get confused with the body of the DO.
Paul
|
|
 | | From: | Michael Beattie | | Subject: | Re: a noob question | | Date: | Sun, 23 Jan 2005 18:25:54 -0500 |
|
|
 | Paul F. Dietz wrote: > Michael Beattie wrote: > >> Why is it that some macros or whatever have double parens around them? >> Like... >> >> (let ((x 2))) ; this has 2 parens around the x=2 assignment >> >> or >> >> (do ((i 0 (+ i 1))) ; there's 2 parens around the i=0 and the increment >> ((> i 10) 'done) ; 2 parens around the "end" condition >> (print i)) >> >> I guess part of the question is "what exactly is the template for the >> do or let macro?" > > > Because these can have more than one binding. > > (let ((x 1) (y 2)) (+ x y)) ==> 3 > > The end condition of DO is grouped with the end form(s), so it doesn't get > confused with the body of the DO. > > Paul
Sure, but you can have more than one grouping as such:
(let (x 1) (y 2)) (+ x y)
though that isnt going to work since x and y wont exist outside of that last paren I guess... It makes sense to me, but it just seems odd... like why wouldnt it try to evaluate that (x 1) which is invalid in itself.
Maybe I am just thinking too much.
As for the do... I think it's weird that it would take 3 arguments, where the first one is actually 3 arguments, and the second one is like 2 or whatever and then the last one is the body. I would think it more intuitive to be like:
(do (i 1 (+ i 1) (> i 10) 'done) (print i))
|
|
 | | From: | Pascal Bourguignon | | Subject: | Re: a noob question | | Date: | 24 Jan 2005 01:02:43 +0100 |
|
|
 | Michael Beattie writes:
> Paul F. Dietz wrote: > > Michael Beattie wrote: > > > >> Why is it that some macros or whatever have double parens around > >> them? Like... > >> > >> (let ((x 2))) ; this has 2 parens around the x=2 assignment > >> > >> or > >> > >> (do ((i 0 (+ i 1))) ; there's 2 parens around the i=0 and the increment > >> ((> i 10) 'done) ; 2 parens around the "end" condition > >> (print i)) > >> > >> I guess part of the question is "what exactly is the template for > >> the do or let macro?"
Read the reference: CLHS http://www.lispworks.com/reference/HyperSpec/Body/s_let_l.htm http://www.lispworks.com/reference/HyperSpec/Body/m_do_do.htm
You must not think "parenthesis" (there is absolutely NO parenthesis in lisp!), but _lists_.
Ok, I hear you people not believing me that there's no parenthesis in lisp. Try this:
(defun dump-p (p &optional (level "")) (if (atom p) (format t "~AATOM: ~A~%" level p) (progn (format t "~ALIST:~%" level) (mapcar (lambda (x) (dump-p x (concatenate 'string level " "))) p))))
[2]> (dump-p '(if (zerop x) 1 (1- x)))
LIST: ATOM: IF LIST: ATOM: ZEROP ATOM: X ATOM: 1 LIST: ATOM: 1- ATOM: X
Where are the parentheses?
Or try this:
[47]> (com.informatimago.common-lisp.cons-to-ascii:draw-list '(if (zerop x) 1 (1- x)))
+-----------------------------------------------------------+ | | | | | +---+---+ +---+---+ +---+---+ +---+---+ | | | * | * |-->| * | * |-->| * | * |-->| * |NIL| | | +---+---+ +---+---+ +---+---+ +---+---+ | | | | | | | | v | v v | | +----+ | +---+ +---+---+ +---+---+ | | | IF | | | 1 | | * | * |-->| * |NIL| | | +----+ | +---+ +---+---+ +---+---+ | | | | | | | | v v | | | +----+ +---+ | | | | 1- | | X | | | | +----+ +---+ | | v | | +---+---+ +---+---+ | | | * | * |-->| * |NIL| | | +---+---+ +---+---+ | | | | | | v v | | +-------+ +---+ | | | ZEROP | | X | | | +-------+ +---+ | +-----------------------------------------------------------+
Can you see any parenthesis?
> > Because these can have more than one binding. > > (let ((x 1) (y 2)) (+ x y)) ==> 3 > > The end condition of DO is grouped with the end form(s), so it > > doesn't get > > confused with the body of the DO. > > Paul > > Sure, but you can have more than one grouping as such: > > (let (x 1) (y 2)) (+ x y) > > though that isnt going to work since x and y wont exist outside of > that last paren I guess... It makes sense to me, but it just seems > odd... like why wouldnt it try to evaluate that (x 1) which is invalid > in itself. > > Maybe I am just thinking too much.
Yes you are. Try to parse: (let (f 1) (g (f 1)) (x 1))
> As for the do... I think it's weird that it would take 3 arguments, > where the first one is actually 3 arguments, and the second one is > like 2 or whatever and then the last one is the body. I would think > it more intuitive to be like: > > (do (i 1 (+ i 1) (> i 10) 'done) (print i))
How could you write the following loop then?
(defun 2^n (n) (do ((i 0 (1+ i)) (j 1 (* 2 j))) ((= i n) j)))
-- __Pascal Bourguignon__ http://www.informatimago.com/ Our enemies are innovative and resourceful, and so are we. They never stop thinking about new ways to harm our country and our people, and neither do we. -- Georges W. Bush
|
|
 | | From: | Bruce Stephens | | Subject: | Re: a noob question | | Date: | Sun, 23 Jan 2005 23:41:26 +0000 |
|
|
 | Michael Beattie writes:
[...]
> Sure, but you can have more than one grouping as such: > > (let (x 1) (y 2)) (+ x y)
That would more clearly be written:
(let (x 1) (y 2)) (+ x y)
> though that isnt going to work since x and y wont exist outside of > that last paren I guess... It makes sense to me, but it just seems > odd... like why wouldnt it try to evaluate that (x 1) which is > invalid in itself.
(let (x y) ...)
is valid. I guess let could be hacked such that (x 1) worked, but then it's only invalid because 1 isn't a symbol, so the idea would only work for a limited set of things.
[...]
|
|
 | | From: | Edi Weitz | | Subject: | Re: a noob question | | Date: | Sun, 23 Jan 2005 23:50:16 +0100 |
|
|
 | On Sun, 23 Jan 2005 17:41:29 -0500, Michael Beattie wrote:
> I guess part of the question is "what exactly is the template for > the do or let macro?"
You know where to find the ANSI spec, don't you?
Edi.
--
Lisp is not dead, it just smells funny.
Real email: (replace (subseq "spamtrap@agharta.de" 5) "edi")
|
|
 | | From: | Tayssir John Gabbour | | Subject: | Re: a noob question | | Date: | 23 Jan 2005 15:36:46 -0800 |
|
|
 | Michael Beattie wrote: > Why is it that some macros or whatever have double parens around > them? Like... > > (let ((x 2))) ; this has 2 parens around the x=2 assignment > > or > > (do ((i 0 (+ i 1))) ; there's 2 parens around the i=0 and the increment > ((> i 10) 'done) ; 2 parens around the "end" condition > (print i)) > > I guess part of the question is "what exactly is the template for > the do or let macro?"
Good questiron. LET's syntax is:
let ({var | (var [init-form])}*) declaration* form* => result*
If we did away with having a single "var" without an initform, which is probably sucky practice anyway, we could do without the multiple parens:
.. (let (blah 10 .. foo 20 .. bar 30) .. (+ blah foo bar))
I'm guessing the Ancients didn't think of it, or really liked tacitly initting stuff to nil. I recall Paul Graham complaining about this once while talking about Arc. And if you think about it, setf actually is like this when you're setting multiple things at once.
.. (defmacro let- ((&rest inits) &body body) .. `(let ,(loop for i on inits by #'cddr .. collect (list (first i) (second i))) .. ,@body))
At the prompt:
.. CL-USER> (macroexpand '(let- (blah 10 .. foo 20 .. bar 30) .. (list blah foo bar))) .. .. (let ((blah 10) .. (foo 20) .. (bar 30)) .. (list blah foo bar)) .. t
MfG, Tayssir
|
|
 | | From: | Surendra Singhi | | Subject: | Re: a noob question | | Date: | Sun, 23 Jan 2005 21:33:01 -0700 |
|
|
 | Tayssir John Gabbour wrote: > At the prompt: > > . CL-USER> (macroexpand '(let- (blah 10 > . foo 20 > . bar 30) > . (list blah foo bar))) > . > . (let ((blah 10) > . (foo 20) > . (bar 30)) > . (list blah foo bar)) > . t
What if one doesn't wants to intitialise the variables? Should one be forced to write!! (blah nil foo nil bar nil)
We need a better solution.
-- Surendra Singhi
www.public.asu.edu/~sksinghi/
|
|
 | | From: | drewc | | Subject: | Re: a noob question | | Date: | Mon, 24 Jan 2005 06:52:40 GMT |
|
|
 | Surendra Singhi wrote: > Tayssir John Gabbour wrote: > >> At the prompt: >> >> . CL-USER> (macroexpand '(let- (blah 10 >> . foo 20 >> . bar 30) >> . (list blah foo bar))) >> . >> . (let ((blah 10) >> . (foo 20) >> . (bar 30)) >> . (list blah foo bar)) >> . t > > > What if one doesn't wants to intitialise the variables? > Should one be forced to write!! > (blah nil > foo nil > bar nil) > > We need a better solution.
Isn't that called 'LET' ?
CL-USER> (let (a b c d) (values a b c d)) NIL NIL NIL NIL CL-USER>
perhaps i'm confused as to what we are trying to do here. A general let that does both types of declaration? how would you parse that?
Personally, i prefer the LET- macro to let, as i think we should be forced to explicitly initialize to nil (or an actual value of the type the variable will hold so DECLARE and the like will work).
Then again, a couple extra parens don't bother me much.
drewc
> > -- > Surendra Singhi > > www.public.asu.edu/~sksinghi/
|
|