From: JLobato
Subject: macros
Date: 
Message-ID: <a5qs23$i62$1@news.wanadoo.es>
One question,
I'm new on lisp and I have a problem: when I define:

(defmacro while (test do &body body)
  "Execute body while the test is true."
  (assert (eq do 'do))
  `(do () ((not ,test) nil) ,@body))

I try to do that

(setq x 1)

(while (> x 10) do (setq x (- x 1)))

and do not work. could anyone help me?

Thanks
Cosh

From: Kent M Pitman
Subject: Re: macros
Date: 
Message-ID: <sfw7kovq7ei.fsf@shell01.TheWorld.com>
"JLobato" <··········@wanadoo.es> writes:

> One question,
> I'm new on lisp and I have a problem: when I define:
> 
> (defmacro while (test do &body body)
>   "Execute body while the test is true."
>   (assert (eq do 'do))
>   `(do () ((not ,test) nil) ,@body))
>
> I try to do that
> 
> (setq x 1)
> 
> (while (> x 10) do (setq x (- x 1)))
> 
> and do not work. could anyone help me?

[I have some style comments I might make once your other concerns 
 are resolved, but I'll spare you them now so as not to distract.]

You'll need to say how "does not work".

(> x 10), for x = 1, returns false, so this loop does not iterate.
That's as it should be.

Maybe you meant to increment X?  Or maybe you meant a different
initial value for X?

While debugging these things, I'd add some print statements.
Perhaps if you add some 

(let ((x 1))
  (format t "~&Before LOOP, x=~D, x>10=~S~%" x (> x 10))
  (while (> x 10) 
   do (format t "~&Within LOOP, x=~D, x>10=~S~%" x (> x 10))
      (setq x (- x 1)))
  (format t "~&Done looping.~%"))
Before LOOP, x=1, x>10=NIL
Done looping.
=> NIL

If you're not a fan of FORMAT, just use things like
 (print `(before loop, x= ,x x>10= ,(> x 10)))
instead.
From: Raymond Wiker
Subject: Re: macros
Date: 
Message-ID: <86bse76j0y.fsf@raw.grenland.fast.no>
"JLobato" <··········@wanadoo.es> writes:

> One question,
> I'm new on lisp and I have a problem: when I define:
> 
> (defmacro while (test do &body body)
>   "Execute body while the test is true."
>   (assert (eq do 'do))
>   `(do () ((not ,test) nil) ,@body))
> 
> I try to do that
> 
> (setq x 1)
> 
> (while (> x 10) do (setq x (- x 1)))
> 
> and do not work. could anyone help me?
> 
> Thanks
> Cosh

        Your macro seems to work, but the test is wrong :-)
You initialise x to 1, and then run a while loop that runs until x is
less than 10.

        Note that you should probably either declare x as a "special"
variable (using defparameter or defvar), or introduce a lexical
binding for it in your test:

(let ((x 20))
  (while (> x 10)
    do (incf x -1)
       (format t "*")))

-- 
Raymond Wiker                        Mail:  ·············@fast.no
Senior Software Engineer             Web:   http://www.fast.no/
Fast Search & Transfer ASA           Phone: +47 23 01 11 60
P.O. Box 1677 Vika                   Fax:   +47 35 54 87 99
NO-0120 Oslo, NORWAY                 Mob:   +47 48 01 11 60

Try FAST Search: http://alltheweb.com/
From: Kent M Pitman
Subject: Re: macros
Date: 
Message-ID: <sfw1yf2ewik.fsf@shell01.TheWorld.com>
Raymond Wiker <·············@fast.no> writes:

> "JLobato" <··········@wanadoo.es> writes:
> 
> > One question,
> > I'm new on lisp and I have a problem: when I define:
> > 
> > (defmacro while (test do &body body)
> >   "Execute body while the test is true."
> >   (assert (eq do 'do))
> >   `(do () ((not ,test) nil) ,@body))
> > 
> > I try to do that
> > 
> > (setq x 1)
> > 
> > (while (> x 10) do (setq x (- x 1)))
> > 
> > and do not work. could anyone help me?
> > 
> > Thanks
> > Cosh
> 
>         Your macro seems to work, but the test is wrong :-)
> You initialise x to 1, and then run a while loop that runs until x is
> less than 10.
> 
>         Note that you should probably either declare x as a "special"
> variable (using defparameter or defvar), or introduce a lexical
> binding for it in your test:
> 
> (let ((x 20))
>   (while (> x 10)
>     do (incf x -1)

or (decf x)

>        (format t "*")))

Incidentally, back to the style issue I raised earlier:

 * Instead of (ASSERT (EQ DO 'DO)) I might recommend you use
   (ASSERT (AND (SYMBOLP DO) (STRING-EQUAL DO 'DO))), which is the kind
   of thing LOOP does, to allow both for shadowing of DO and/or 
   [more likely] the use of :DO by people who like to use keywords for
   guide words (especially in editors that do syntax coloring).
   There's nothing more annoying than having to make your code's
   clients have to write:

     (while (> x 10) es.wanadoo.coshjaguar::do 
       (decf x))

   if they have for some reason shadowed CL's DO for their own, but have
   imported your DO.

 * Are you conscious of the fact that the following is also allowed
   in your macro:

     (while t do (go foo) (print 'lose) foo (print 'win) (return 'done))
     WIN
     => DONE

   Personally, I don't like to introduce a tagbody or a return point
   accidentally, though I sometimes do it intentionally.  I think most
   people would be fine with a return point being here, but the tagbody
   is much more questionable.  In particular, this result may confuse
   most users:

     (while t do (go do) (print 'lose) do (print 'win) (return 'done))

   The reason this looks weird to me is that DO occurs twice in the
   list, once as a guide word and once as a tag.  If you're going to 
   allow tags, I recommend not requiring the 'do' guide word.

 * Make sure you learn about INCF and DECF.
From: JLobato
Subject: RE: macros
Date: 
Message-ID: <a5r74e$lct$1@news.wanadoo.es>
Thanks Kent, Raymond and Eric

The problem is solved, I understood  my fault, and also I have learn a lot
about debugging in LISP.

Regards


Kent M Pitman <······@world.std.com> escribi� en el mensaje de noticias
···············@shell01.TheWorld.com...
> Raymond Wiker <·············@fast.no> writes:
>
> > "JLobato" <··········@wanadoo.es> writes:
> >
> > > One question,
> > > I'm new on lisp and I have a problem: when I define:
> > >
> > > (defmacro while (test do &body body)
> > >   "Execute body while the test is true."
> > >   (assert (eq do 'do))
> > >   `(do () ((not ,test) nil) ,@body))
> > >
> > > I try to do that
> > >
> > > (setq x 1)
> > >
> > > (while (> x 10) do (setq x (- x 1)))
> > >
> > > and do not work. could anyone help me?
> > >
> > > Thanks
> > > Cosh
> >
> >         Your macro seems to work, but the test is wrong :-)
> > You initialise x to 1, and then run a while loop that runs until x is
> > less than 10.
> >
> >         Note that you should probably either declare x as a "special"
> > variable (using defparameter or defvar), or introduce a lexical
> > binding for it in your test:
> >
> > (let ((x 20))
> >   (while (> x 10)
> >     do (incf x -1)
>
> or (decf x)
>
> >        (format t "*")))
>
> Incidentally, back to the style issue I raised earlier:
>
>  * Instead of (ASSERT (EQ DO 'DO)) I might recommend you use
>    (ASSERT (AND (SYMBOLP DO) (STRING-EQUAL DO 'DO))), which is the kind
>    of thing LOOP does, to allow both for shadowing of DO and/or
>    [more likely] the use of :DO by people who like to use keywords for
>    guide words (especially in editors that do syntax coloring).
>    There's nothing more annoying than having to make your code's
>    clients have to write:
>
>      (while (> x 10) es.wanadoo.coshjaguar::do
>        (decf x))
>
>    if they have for some reason shadowed CL's DO for their own, but have
>    imported your DO.
>
>  * Are you conscious of the fact that the following is also allowed
>    in your macro:
>
>      (while t do (go foo) (print 'lose) foo (print 'win) (return 'done))
>      WIN
>      => DONE
>
>    Personally, I don't like to introduce a tagbody or a return point
>    accidentally, though I sometimes do it intentionally.  I think most
>    people would be fine with a return point being here, but the tagbody
>    is much more questionable.  In particular, this result may confuse
>    most users:
>
>      (while t do (go do) (print 'lose) do (print 'win) (return 'done))
>
>    The reason this looks weird to me is that DO occurs twice in the
>    list, once as a guide word and once as a tag.  If you're going to
>    allow tags, I recommend not requiring the 'do' guide word.
>
>  * Make sure you learn about INCF and DECF.
From: Erik Naggum
Subject: Re: macros
Date: 
Message-ID: <3224079456814111@naggum.net>
* "JLobato" <··········@wanadoo.es>
| could anyone help me?

  What would you expect your code to do that it does not?

  Incidentally, the standard language already has your "while" construct
  built in:

(loop while <condition> do <body>)

  Some old farts are so hysterically opposed to extended loop that they
  re-create it piece by piece with their own while and until looping
  constructs.  It is not a good idea to be a newbie and an old fart at the
  same time.  Do not waste your time re-creating your previous language
  when you move to another.  Learn the new language in its own right --
  otherwise, there was never any point in leaving your old language.

///
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.
From: Harald Hanche-Olsen
Subject: Re: macros
Date: 
Message-ID: <pco664e7yk5.fsf@thoth.math.ntnu.no>
+ Erik Naggum <····@naggum.net>:

|   Do not waste your time re-creating your previous language when you
|   move to another.  Learn the new language in its own right --
|   otherwise, there was never any point in leaving your old language.

Good advice indeed.  The urge to reshape any new environment into a
replica of what you're used to is incredibly strong, and should not be
underestimated.  Back in the days when lots of Pascal (and Modula-
something) programmers discovered they had to start writing C code,
they invented all sorts of horrors like

#define BEGIN {
#define END }
#define IF if (
#define THEN ) {
#define ELSE } {

and so forth, but you get the idea.  Of course, if the urge is brought
on by the presence of C's feeble preprocessor, the powerful macro
facilities of Lisp must increase the urge to the point where it can be
hard to resist.

I think, for the sake of the newbies, we should be glad that they
generally don't know how to modify the reader.  By the time they do,
they'll hopefully have aquired the sense to refrain from doing so
willy-nilly.

(On the other hand, as an exercise in macro writing, creating the
WHILE macro is a worthwhile endeavor.  But then the newbie has to
understand that an exercise is *all* it was, and not fall to the
temptation to begin using his wonderful creation all over the place.
Surely, this is no harder than resisting coffee addiction?)

(Now please excuse me while I go brew a cup...)

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Yes it works in practice - but does it work in theory?