From: neo88
Subject: Understanding Macro DOLIST
Date: 
Message-ID: <6a73bb68.0407261210.1da40ef7@posting.google.com>
I have rencently covered the macro dolist in my Lisp textbook, and I
am having some trouble understanding exacly how it works, or how the
eval function evaluates it. So naturally, I turned to the HyperSpec to
gain greater understanding. The HyperSpec gives:

dolist (var list-form [result-form]) declaration* {tag | statement}*

=> result*

So I tryed something similar to:

(defun foo (result)
  (let ((result nil))
    (dolist (result '(1 2 3))
     ;; more ))

and CMUCL returns the error:
variable "result" defined but never used.

Why is that? It looks to me that I have followed the syntax
fathifully.
I also do not understand what eval does when it encounters this macro.
Does it try to bind the variable to the list then return the list? Or
does it work the other way around parsing the list first, the binding
the variable to it?
One last thing: How does a variable get used after it has been
defined? Does it have to be bound to something first? In that case, I
don't understand why the above code doesn't work right. Thanks for any
assitence.

neo88

From: Thomas A. Russ
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <ymifz7etps6.fsf@sevak.isi.edu>
······@truevine.net (neo88) writes:

> 
> I have rencently covered the macro dolist in my Lisp textbook, and I
> am having some trouble understanding exacly how it works, or how the
> eval function evaluates it. So naturally, I turned to the HyperSpec to
> gain greater understanding. The HyperSpec gives:
> 
> dolist (var list-form [result-form]) declaration* {tag | statement}*
> 
> => result*

The quick description of what DOLIST does is that it binds "var" to
successive elements of "list-form" for the body of the DOLIST form.  In
other words, it provides a simple way to iterate over the elements of a
list.  Normally, DOLIST is invoked for side effects, but if provided
with the optional "result-form" it will return that instead of NIL.

> 
> So I tryed something similar to:
> 
> (defun foo (result)
>   (let ((result nil))
>     (dolist (result '(1 2 3))
>      ;; more ))
> 
> and CMUCL returns the error:
> variable "result" defined but never used.
> 
> Why is that? It looks to me that I have followed the syntax
> fathifully.

The reason is that the LET introduces one binding of the variable
RESULT, and the DOLIST introduces another binding of the same variable.
The first binding is the one that is not being used.

The simplest way to work out how forms work in Lisp is often to just try
out the forms at the top-level listener.  Unlike some other languages,
you don't necessarily need to write functions first.  In this case, the
following is one of the simpler examples of using dolist:

(dolist (i '(1 2 3))
  (print i))

Which will produce the following output (and return value):

1
2
3
NIL

If you want, you can get silly with the return value:

(dolist (i '(4 3 2) 1)
  (print i))

==>
4
3
2
1

where "1" is the return value, rather than being printed.

Perhaps a more useful example of using dolist is the following.  It also
involves the use of another bound variable:

(defun my-reverse (list-argument)
  (let ((result nil))
    (dolist (element list-argument result)
       (setq result (cons element result)))))


> I also do not understand what eval does when it encounters this macro.
> Does it try to bind the variable to the list then return the list? Or
> does it work the other way around parsing the list first, the binding
> the variable to it?
> One last thing: How does a variable get used after it has been
> defined? 

A variable is used when it is evaluated (referenced, read).

> Does it have to be bound to something first? 

Well, yes.  Otherwise you get an unbound variable error.

> In that case, I
> don't understand why the above code doesn't work right. Thanks for any
> assitence.
> 
> neo88

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Hannah Schroeter
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <ce3p29$fhi$2@c3po.use.schlund.de>
Hello!

neo88 <······@truevine.net> wrote:
>I have rencently covered the macro dolist in my Lisp textbook, and I
>am having some trouble understanding exacly how it works, or how the
>eval function evaluates it. So naturally, I turned to the HyperSpec to
>gain greater understanding. The HyperSpec gives:

>dolist (var list-form [result-form]) declaration* {tag | statement}*

>=> result*

>So I tryed something similar to:

>(defun foo (result)
>  (let ((result nil))
>    (dolist (result '(1 2 3))
>     ;; more ))

>and CMUCL returns the error:
>variable "result" defined but never used.

It's a warning, not an error, pointing out that you don't use the
2 *different* outer lexical bindings of result (formal parameter
of defun foo, and let binding).

>Why is that? It looks to me that I have followed the syntax
>fathifully.

You have. But dunno whether the code would do what you actually intend.

>[...]

Kind regards,

Hannah.
From: Chris Perkins
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <6cb6c81f.0407262220.787f707d@posting.google.com>
I accidentally hit the "Post" button before I finished on my last
message.  My apologies.


Anyway, you probably see the direction I am heading.  You are defining
three different nested variables called "result", but only using one
of them.

*I also had a parenthetical comment I was going to make.  But since I
can't view my post for 3 to 9 hours (thanks Google!) I can't remember
what I was saying that needed a footnote.  Oh well.

Good Luck,

Chris Perkins
From: neo88
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <6a73bb68.0407271738.f260a82@posting.google.com>
········@medialab.com (Chris Perkins) wrote in message news:<····························@posting.google.com>...
> I accidentally hit the "Post" button before I finished on my last
> message.  My apologies.
> 
> 
> Anyway, you probably see the direction I am heading.  You are defining
> three different nested variables called "result", but only using one
> of them.
> 
> *I also had a parenthetical comment I was going to make.  But since I
> can't view my post for 3 to 9 hours (thanks Google!) I can't remember
> what I was saying that needed a footnote.  Oh well.
> 
> Good Luck,
> 
> Chris Perkins

You could have it emailed to you when you write it.
Regards
Philip Haddad
From: Chris Perkins
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <6cb6c81f.0407262215.37451f32@posting.google.com>
······@truevine.net (neo88) wrote in message news:<····························@posting.google.com>...
> I have rencently covered the macro dolist in my Lisp textbook,
[...snip...]
> 
> So I tryed something similar to:
> 
> (defun foo (result)
>   (let ((result nil))
>     (dolist (result '(1 2 3))
>      ;; more ))
> 
> and CMUCL returns the error:
> variable "result" defined but never used.
> 
> Why is that? It looks to me that I have followed the syntax
> fathifully.

CMUCL is saying that variable "result" is defined but not used,
because you have defined result 3 times in the above example, but are
probably using one at most.

You can think of the dolist macro as taking a variable _name_ as its
first argument*.

For instance, try the following:

(defun foo ()
 (dolist (result '(1 2 3))
   (format T "~A" result)))

(foo)

The above works fine.   


Let's look at your example again:


> (defun foo (result)  ;; <---  The first binding of a variable called result
>   (let ((result nil))  ;; <----   A second, different "result".
>     (dolist (result '(1 2 3)) ;;<---  A third variable called "result".
>      ;; more ))




> I also do not understand what eval does when it encounters this macro.
> Does it try to bind the variable to the list then return the list? Or
> does it work the other way around parsing the list first, the binding
> the variable to it?
> One last thing: How does a variable get used after it has been
> defined? Does it have to be bound to something first? In that case, I
> don't understand why the above code doesn't work right. Thanks for any
> assitence.
> 
> neo88
From: neo88
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <6a73bb68.0407270500.21b6b76f@posting.google.com>
········@medialab.com (Chris Perkins) wrote in message news:<····························@posting.google.com>...
> ······@truevine.net (neo88) wrote in message news:<····························@posting.google.com>...
> > I have rencently covered the macro dolist in my Lisp textbook,
>  [...snip...]
> > 
> > So I tryed something similar to:
> > 
> > (defun foo (result)
> >   (let ((result nil))
> >     (dolist (result '(1 2 3))
> >      ;; more ))
> > 
> > and CMUCL returns the error:
> > variable "result" defined but never used.
> > 
> > Why is that? It looks to me that I have followed the syntax
> > fathifully.
> 
> CMUCL is saying that variable "result" is defined but not used,
> because you have defined result 3 times in the above example, but are
> probably using one at most.
> 
> You can think of the dolist macro as taking a variable _name_ as its
> first argument*.
> 
> For instance, try the following:
> 
> (defun foo ()
>  (dolist (result '(1 2 3))
>    (format T "~A" result)))
> 
> (foo)
> 
> The above works fine.   
> 
> 
> Let's look at your example again:
> 
> 
> > (defun foo (result)  ;; <---  The first binding of a variable called result
> >   (let ((result nil))  ;; <----   A second, different "result".
> >     (dolist (result '(1 2 3)) ;;<---  A third variable called "result".
> >      ;; more ))

Ah, I think I see. Each of those "results" is a different variable,
all lexially scoped, I'd imagine. And since I hear it is rather ugly
to define a variable globally in Lisp, I won't :)
What if I did:

(defun foo (result)
  (let ((final nil))
    (dolist (element '(1 2 3))
    ;; more ))

Would that work, or am I heading down the wrong track? 
BTW, slightly OT, but is there any way that I can look at the code of
inbuild functions and macros such as let or dolist??

neo88 (Philip Haddad)
From: David Douthitt
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <ce64m3$87g$2@grandcanyon.binc.net>
neo88 wrote:

> Ah, I think I see. Each of those "results" is a different variable,
> all lexially scoped, I'd imagine. And since I hear it is rather ugly
> to define a variable globally in Lisp, I won't :)
> What if I did:
> 
> (defun foo (result)
>   (let ((final nil))
>     (dolist (element '(1 2 3))
>     ;; more ))
> 
> Would that work, or am I heading down the wrong track? 

I would think that would work, but if you didn't use the variable, it 
would still report it as unused, whether it was called "result", 
"final", or "element" ...
From: Barry Margolin
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <barmar-7E7CBF.00501428072004@comcast.dca.giganews.com>
In article <············@grandcanyon.binc.net>,
 David Douthitt <·····@mailbag.com> wrote:

> neo88 wrote:
> 
> > Ah, I think I see. Each of those "results" is a different variable,
> > all lexially scoped, I'd imagine. And since I hear it is rather ugly
> > to define a variable globally in Lisp, I won't :)
> > What if I did:
> > 
> > (defun foo (result)
> >   (let ((final nil))
> >     (dolist (element '(1 2 3))
> >     ;; more ))
> > 
> > Would that work, or am I heading down the wrong track? 
> 
> I would think that would work, but if you didn't use the variable, it 
> would still report it as unused, whether it was called "result", 
> "final", or "element" ...

But at least this time you'll know *which* variable it's complaining 
about.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Chris Perkins
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <6cb6c81f.0407271312.1a5ade0d@posting.google.com>
> > ······@truevine.net (neo88) wrote in message news:<6a73bb68.0407261210.
> 
> Ah, I think I see. Each of those "results" is a different variable,
> all lexially scoped, I'd imagine. And since I hear it is rather ugly
> to define a variable globally in Lisp, I won't :)
> What if I did:
> 
> (defun foo (result)
>   (let ((final nil))
>     (dolist (element '(1 2 3))
>     ;; more ))
> 
> Would that work, or am I heading down the wrong track? 
> BTW, slightly OT, but is there any way that I can look at the code of
> inbuild functions and macros such as let or dolist??
> 
> neo88 (Philip Haddad)


Your example will work.  But CMUCL may still warn about unused
variables, it really depends upon what you do in the  ";; more"
section of your code.

My alternative from the previous post avoided this problem my not
defining any arguments and avoided the let statement entirely.


In general, unnecessary use of global variables is a bad programming
practice.  But, they are needed sometimes and should be in every
programmers toolbox.  There is nothing hard or awkward about them in
Lisp:

(defvar *some-global* 6)  
;; Placing * at the beginning and end of a global variablename is a
common practice, it is not required.

;;later
(setf *some-global* 14)

Along with defvar, you should also read up about defconstant and
defparameter in the Hyperspec.  And, when you eventually come to worry
about name conflicts and namespaces, read about packages.


dolist is a macro, and on many Lisp systems it can be macro-expanded. 
I believe that let is a special form, and is usually not expandable. 
However, some books on Scheme** show examples of using lambda forms to
create let.  This is educational and possibly interesting, but it is
not how let is actually implemented in most Common Lisp systems.


Hope this helps.

Happy Lisping!

Chris


** Abelson and Sussman's "The Structure and Interpretation of Computer
Programming" aka SICP
Kent Dybvig's  "The Scheme Programming Language"
I believe both of these texts may be available online.
From: neo88
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <6a73bb68.0407280551.2322d5ad@posting.google.com>
> My alternative from the previous post avoided this problem my not
> defining any arguments and avoided the let statement entirely.

Don't you have to use the let statement when useing dolist? My
textbook always has a call to it before starting dolist, so I thought
that you always had to "let" a varaible before dolist. I guess it make
sense if you don't, but it is an interesting little tidbit :)
 
> Along with defvar, you should also read up about defconstant and
> defparameter in the Hyperspec.  And, when you eventually come to worry
> about name conflicts and namespaces, read about packages.
> Hope this helps.

I actually just asked about packages in #lisp last night ;) I was
wondering if they were similar to C++ header files, and found that
they were closer to namespaces.
> Happy Lisping!
> 
> Chris

Philip Haddad
From: Pascal Bourguignon
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <87pt6g89ln.fsf@thalassa.informatimago.com>
······@truevine.net (neo88) writes:

> > My alternative from the previous post avoided this problem my not
> > defining any arguments and avoided the let statement entirely.
> 
> Don't you have to use the let statement when useing dolist? My
> textbook always has a call to it before starting dolist, so I thought
> that you always had to "let" a varaible before dolist. I guess it make
> sense if you don't, but it is an interesting little tidbit :)

Often in Common-Lisp, variables names (symbols) given to macros or
special operators are used just as that, names, to be bound inside the
body of the macro or special operator. That is, there is an implicit
LET around the body.  Hence the use of MACROEXPAND-1, to see the
explicit LET.  Sometimes you have to use MACROEXPAND-1 several times
thought, because for example in clisp, DOLIST expands to a DO which
itself expands to a TAGBODY with a LET inside.  But the LET is there.

Now, you may still need a LET around a DO or DOLIST if the purpose of
your iteration is to modify some variable bound outside of your
iteration.

    (let ((counter 0))
       (dolist (item (some-list))
          (when (listp item) (incf counter)))
       (format t "There was ~A sub-lists in that list~%" counter))

[But, I would consider this other style:

    (format t "There was ~A sub-lists in that list~%"
        (count-if (function listp) (some-list)))            ]

Actually, I often replace a (LET (...) (~some-iteration~ ...)) 
with a plain (DO (..) (...) ...):


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: Chris Perkins
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <6cb6c81f.0407271324.59f7ad62@posting.google.com>
······@truevine.net (neo88) wrote in message news:<····························@posting.google.com>...

> BTW, slightly OT, but is there any way that I can look at the code of
> inbuild functions and macros such as let or dolist??
> 
> neo88 (Philip Haddad)


I forgot, Paul Graham's most excellent book ANSI Common Lisp has an
Appendix where he defines quite a bit of Lisp in Lisp.  And, in there,
you can most certainly find an example of dolist.  But I don't know
about let.

This book also has an appendix with every Common Lisp keyword,
function, macro, and form documented.  It's a handy addition to the
HyperSpec.

Distressingly, I cannot find my copy.

Chris
From: Chris Perkins
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <6cb6c81f.0407271324.24f1520c@posting.google.com>
······@truevine.net (neo88) wrote in message news:<····························@posting.google.com>...

> BTW, slightly OT, but is there any way that I can look at the code of
> inbuild functions and macros such as let or dolist??
> 
> neo88 (Philip Haddad)


I forgot, Paul Graham's most excellent book ANSI Common Lisp has an
Appendix where he defines quite a bit of Lisp in Lisp.  And, in there,
you can most certainly find an example of dolist.  But I don't know
about let.

This book also has an appendix with every Common Lisp keyword,
function, macro, and form documented.  It's a handy addition to the
HyperSpec.

Distressingly, I cannot find my copy.

Chris
From: Alan Crowe
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <863c3dvzh9.fsf@cawtech.freeserve.co.uk>
Philip Haddad asked:
> What if I did:
> 
> (defun foo (result)
>   (let ((final nil))
>     (dolist (element '(1 2 3))
>     ;; more ))
>
> Would that work, or am I heading down the wrong track? 

I'm puzzled by the choice of name for the argument to foo. I
would expect foo to return a result, not be passed
a result. Suppose foo was intended to add up the numbers on the
list and return the total. You might write

(defvar result)

(defun foo () ; no parameters, very unusual
  (let ((sum 0)) ;initialise accumulator
    (dolist (x '(1 2 3))
      (setf sum (+ x sum))) ; using incf would be slicker
      ;; return the total by flowing off the end of the
      ;; CL is very different from C
      sum))
          

(setf result (foo))

then result => 6

What I'm trying to say is that you return a result by
flowing off the end of a function. You do not need an
out-parameter to let you pass a result back and CL only
provides in-parameters.

Alan Crowe
Edinburgh
Scotland
From: Pascal Bourguignon
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <87fz7ecvv7.fsf@thalassa.informatimago.com>
······@truevine.net (neo88) writes:

> I have rencently covered the macro dolist in my Lisp textbook, and I
> am having some trouble understanding exacly how it works, or how the
> eval function evaluates it. So naturally, I turned to the HyperSpec to
> gain greater understanding. The HyperSpec gives:
> 
> dolist (var list-form [result-form]) declaration* {tag | statement}*
> 
> => result*
> 
> So I tryed something similar to:
> 
> (defun foo (result)
>   (let ((result nil))
>     (dolist (result '(1 2 3))
>      ;; more ))
> 
> and CMUCL returns the error:
> variable "result" defined but never used.
> 
> Why is that? It looks to me that I have followed the syntax
> fathifully.

> I also do not understand what eval does when it encounters this macro.

Ask it!

(macroexpand-1 '(dolist (result '(1 2 3))  (print result)))

(DO* ((#:G1024 '(1 2 3) (CDR #:G1024)) (RESULT NIL)) ((ENDP #:G1024) NIL)
 (DECLARE (LIST #:G1024)) (SETQ RESULT (CAR #:G1024)) (PRINT RESULT))
T

Of course, you could then ask what it does when it encounters DO*:

(macroexpand-1 (macroexpand-1 '(dolist (result '(1 2 3))  (print result))))

(BLOCK NIL
 (LET* ((#:G1025 '(1 2 3)) (RESULT NIL)) (DECLARE (LIST #:G1025))
  (TAGBODY #:G1026 (IF (ENDP #:G1025) (GO #:G1027)) (SETQ RESULT (CAR #:G1025))
   (PRINT RESULT) (SETQ #:G1025 (CDR #:G1025)) (GO #:G1026) #:G1027
   (RETURN-FROM NIL (PROGN NIL)))))
T


> Does it try to bind the variable to the list then return the list? 
> Or
> does it work the other way around parsing the list first, the binding
> the variable to it?
> One last thing: How does a variable get used after it has been
> defined? Does it have to be bound to something first? In that case, I
> don't understand why the above code doesn't work right. Thanks for any
> assitence.

Did you read: http://www.lispworks.com/reference/HyperSpec/Body/m_dolist.htm ?

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: neo88
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <6a73bb68.0407271737.1649eb6a@posting.google.com>
Pascal Bourguignon <····@thalassa.informatimago.com> wrote in message news:<··············@thalassa.informatimago.com>...
> ······@truevine.net (neo88) writes:
> 
> 
> Ask it!
> 
> (macroexpand-1 '(dolist (result '(1 2 3))  (print result)))
> 
> (DO* ((#:G1024 '(1 2 3) (CDR #:G1024)) (RESULT NIL)) ((ENDP #:G1024) NIL)
>  (DECLARE (LIST #:G1024)) (SETQ RESULT (CAR #:G1024)) (PRINT RESULT))
> T
> 
I think I understand most of what is going on here, however, I don't
know what

((#:G1024...)

is supposed to be. Is that the address of the function? I see that it
has the hash "#" sign in front of it, which I know is a read-specfic
function ie it is handled before it gets passed to eval. But if this
is ouput from eval, I'm not sure how it works that way.
> Of course, you could then ask what it does when it encounters DO*:
> 
> (macroexpand-1 (macroexpand-1 '(dolist (result '(1 2 3))  (print result))))
> 
> (BLOCK NIL
>  (LET* ((#:G1025 '(1 2 3)) (RESULT NIL)) (DECLARE (LIST #:G1025))
>   (TAGBODY #:G1026 (IF (ENDP #:G1025) (GO #:G1027)) (SETQ RESULT (CAR #:G1025))
>    (PRINT RESULT) (SETQ #:G1025 (CDR #:G1025)) (GO #:G1026) #:G1027
>    (RETURN-FROM NIL (PROGN NIL)))))
> T
That stuff is weirder. Kinda compilcated me for a minute or two :P I
think I get the basic jist of it know though :)
> Did you read: http://www.lispworks.com/reference/HyperSpec/Body/m_dolist.htm ?

Yes I did :) 

neo88 (Philip Haddad)
From: Jeff
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <87FNc.182883$JR4.135584@attbi_s54>
neo88 wrote:

> Pascal Bourguignon <····@thalassa.informatimago.com> wrote in message
> news:<··············@thalassa.informatimago.com>...
> > ······@truevine.net (neo88) writes:
> > 
> > 
> > Ask it!
> > 
> > (macroexpand-1 '(dolist (result '(1 2 3))  (print result)))
> > 
> > (DO* ((#:G1024 '(1 2 3) (CDR #:G1024)) (RESULT NIL)) ((ENDP
> > #:G1024) NIL)  (DECLARE (LIST #:G1024)) (SETQ RESULT (CAR #:G1024))
> > (PRINT RESULT)) T
> > 
> I think I understand most of what is going on here, however, I don't
> know what
> 
> ((#:G1024...)
> 
> is supposed to be. 

It is a generated variable for the macro. See chapter 10 of PG's ANSI
Common Lisp for an explanation. I know I'll butcher this, but here it
goes..

Takes the following [trivial and stupid] macro:

(defmacro set-sq (x)
  (let ((y))
    `(setf ,y (* ,x ,x)))

This is bad, because consider the following use:

(defun magnitude (x y)
  (sqrt (+ (sq x) (sq y))))

One would expect the macro to use the 'y' variable that it created, but
that isn't the case. In fact, it will use the 'y' variable from the
magnitude function. To fix this, we use (gensym) to create an
uninterned generated variable (like #:G1024):

(defmacro sq (x)
  (let ((y (gensym)))
    `(setf ,y (* ,x ,x))))

Now 'y' from the macro is bound to a generated symbol and so 'y' is not
the same 'y' from the magnitude function. I'm sure others would have
better examples of this. I just wanted to show a very, very simple
example. But PG did it best -- chapter 10, ANSI Common Lisp :)

Jeff
From: Kalle Olavi Niemitalo
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <87acxm4ed3.fsf@Astalo.kon.iki.fi>
······@truevine.net (neo88) writes:

> I also do not understand what eval does when it encounters this macro.

It expands the macro, of course.  On CMUCL:

* (macroexpand-1 '(dolist (element '(one two three))
                    (print element)))

(DO* ((#:G1043 '(ONE TWO THREE) (CDR #:G1043)))
     ((ENDP #:G1043) NIL)
  (LET ((ELEMENT (CAR #:G1043)))
    (TAGBODY (PRINT ELEMENT))))
T

On CLISP:

[1]> (macroexpand-1 '(dolist (element '(one two three))
                       (print element)))
(DO* ((#:G9393 '(ONE TWO THREE) (CDR #:G9393))
      (ELEMENT NIL))
     ((ENDP #:G9393) NIL)
 (DECLARE (LIST #:G9393))
 (SETQ ELEMENT (CAR #:G9393))
 (PRINT ELEMENT)) ;
T
From: neo88
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <6a73bb68.0407261835.58f3b95d@posting.google.com>
Kalle Olavi Niemitalo <···@iki.fi> wrote in message news:<··············@Astalo.kon.iki.fi>...
> ······@truevine.net (neo88) writes:
> 
> > I also do not understand what eval does when it encounters this macro.
> 
> It expands the macro, of course.  On CMUCL:
> 
> * (macroexpand-1 '(dolist (element '(one two three))
>                     (print element)))
> 
> (DO* ((#:G1043 '(ONE TWO THREE) (CDR #:G1043)))
>      ((ENDP #:G1043) NIL)
>   (LET ((ELEMENT (CAR #:G1043)))
>     (TAGBODY (PRINT ELEMENT))))
> T
> 
> On CLISP:
> 
> [1]> (macroexpand-1 '(dolist (element '(one two three))
>                        (print element)))
> (DO* ((#:G9393 '(ONE TWO THREE) (CDR #:G9393))
>       (ELEMENT NIL))
>      ((ENDP #:G9393) NIL)
>  (DECLARE (LIST #:G9393))
>  (SETQ ELEMENT (CAR #:G9393))
>  (PRINT ELEMENT)) ;
> T

I never knew you could actually expand functions to see what eval was
doing to them. That's really neat! I noticed in the Lisp Primer
http://grimpeur.tamu.edu/~colin/lp/node36.html
that they do something unusual in the sense I've never seen it with
dolist before.

(defun num-sublists-i (lis)
        (let ((result 0))
           (dolist (next lis result)
              (if (listp next) 
                  (setf result (1+ result))))))

Is the code. Note that
(let ((result 0))
is not the same thing as 
(let ((result nil))
I compile the (result 0) and it compiles and loads with no errors.
But
(num-sublists-i '(1 2 3))
=> 0
no matter what you use for the list. Is that because the line
(let ((result 0))
is not 
(let ((result nil))
?
If it is, then I just found my first unelegent solution in a Lisp
manuel :)
I will play around with (macroexpand-1) expression, I think I'll learn
a lot from it.

neo88 (Philip Haddad)
From: Pascal Bourguignon
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <87smbeayh1.fsf@thalassa.informatimago.com>
······@truevine.net (neo88) writes:
> > On CLISP:
> > 
> > [1]> (macroexpand-1 '(dolist (element '(one two three))
> >                        (print element)))
> > (DO* ((#:G9393 '(ONE TWO THREE) (CDR #:G9393))
> >       (ELEMENT NIL))
> >      ((ENDP #:G9393) NIL)
> >  (DECLARE (LIST #:G9393))
> >  (SETQ ELEMENT (CAR #:G9393))
> >  (PRINT ELEMENT)) ;
> > T
> 
> I never knew you could actually expand functions to see what eval was
> doing to them. That's really neat! I noticed in the Lisp Primer
> http://grimpeur.tamu.edu/~colin/lp/node36.html
> that they do something unusual in the sense I've never seen it with
> dolist before.

It's not functionexpand-1, it's macroexpand-1 !

To know if something is a function or a macro, check CLHS, 
or if your implementation give useful results:

CL-USER> (type-of (symbol-function 'do))
SYSTEM::MACRO
CL-USER> (type-of (symbol-function 'if))
EXT:SPECIAL-OPERATOR
CL-USER> (type-of (symbol-function 'list))
COMPILED-FUNCTION


> (defun num-sublists-i (lis)
>         (let ((result 0))
>            (dolist (next lis result)
>               (if (listp next) 
>                   (setf result (1+ result))))))
> 
> Is the code. Note that
> (let ((result 0))
> is not the same thing as 
> (let ((result nil))
> I compile the (result 0) and it compiles and loads with no errors.
> But
> (num-sublists-i '(1 2 3))
> => 0
> no matter what you use for the list. Is that because the line
> (let ((result 0))
> is not 
> (let ((result nil))
> ?

Try it with: (num-sublists-i '((1) 2 (a))) 

And then, READ again the defun, and think about the MEANING of each
word, and sub-words.


> If it is, then I just found my first unelegent solution in a Lisp
> manuel :)
> I will play around with (macroexpand-1) expression, I think I'll learn
> a lot from it.
> 
> neo88 (Philip Haddad)


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: neo88
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <6a73bb68.0407271742.ffc85b6@posting.google.com>
> 
> It's not functionexpand-1, it's macroexpand-1 !
>
Is there a functionexpand-1? I tried passing it to top-level in CMUCL,
and got a bunch or errors which would lead me to conclude that there
is no such macro/function.
> To know if something is a function or a macro, check CLHS, 
> or if your implementation give useful results:
>
 
> CL-USER> (type-of (symbol-function 'do))
> SYSTEM::MACRO
> CL-USER> (type-of (symbol-function 'if))
> EXT:SPECIAL-OPERATOR
> CL-USER> (type-of (symbol-function 'list))
> COMPILED-FUNCTION
> 
> 
Interesting, I never knew you could do that either. Then again,
there's a lot I don't know... yet. :)

Philip Haddad
From: Pascal Bourguignon
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <87pt6g9vki.fsf@thalassa.informatimago.com>
······@truevine.net (neo88) writes:

> > 
> > It's not functionexpand-1, it's macroexpand-1 !
> >
> Is there a functionexpand-1? I tried passing it to top-level in CMUCL,
> and got a bunch or errors which would lead me to conclude that there
> is no such macro/function.

No, there's no functionexpand-1.

The point was that macroexpand-1 does not substitute functions, but
macros, as its name implies.


> > To know if something is a function or a macro, check CLHS, 
> > or if your implementation give useful results:
> >
>  
> > CL-USER> (type-of (symbol-function 'do))
> > SYSTEM::MACRO
> > CL-USER> (type-of (symbol-function 'if))
> > EXT:SPECIAL-OPERATOR
> > CL-USER> (type-of (symbol-function 'list))
> > COMPILED-FUNCTION
> > 
> > 
> Interesting, I never knew you could do that either. Then again,
> there's a lot I don't know... yet. :)
> 
> Philip Haddad

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: Barry Margolin
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <barmar-A0052E.18574228072004@comcast.dca.giganews.com>
In article <··············@thalassa.informatimago.com>,
 Pascal Bourguignon <····@thalassa.informatimago.com> wrote:

> ······@truevine.net (neo88) writes:
> 
> > > 
> > > It's not functionexpand-1, it's macroexpand-1 !
> > >
> > Is there a functionexpand-1? I tried passing it to top-level in CMUCL,
> > and got a bunch or errors which would lead me to conclude that there
> > is no such macro/function.
> 
> No, there's no functionexpand-1.
> 
> The point was that macroexpand-1 does not substitute functions, but
> macros, as its name implies.

In my mind, the analogue of MACROEXPAND for functions would be TRACE.  
They both let you see the actual behavior of what they're "expanding".

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: David Douthitt
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <ce9e37$3gq$1@grandcanyon.binc.net>
Pascal Bourguignon wrote:

> To know if something is a function or a macro, check CLHS, 
> or if your implementation give useful results:
> 
> CL-USER> (type-of (symbol-function 'do))
> SYSTEM::MACRO
> CL-USER> (type-of (symbol-function 'if))
> EXT:SPECIAL-OPERATOR
> CL-USER> (type-of (symbol-function 'list))
> COMPILED-FUNCTION

What about this?

* (type-of #'do)

FUNCTION
* (type-of #'if)

FUNCTION
* (type-of #'list)

FUNCTION
* (type-of (symbol-function 'do))

FUNCTION
* (type-of (symbol-function 'if))

FUNCTION
* (type-of (symbol-function 'list))

FUNCTION
*

 From SBCL....
From: Pascal Bourguignon
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <871xiv8tv4.fsf@thalassa.informatimago.com>
David Douthitt <·····@mailbag.com> writes:

> Pascal Bourguignon wrote:
> 
> > To know if something is a function or a macro, check CLHS, or if
> > your implementation give useful results:
> > CL-USER> (type-of (symbol-function 'do))
> > SYSTEM::MACRO
> > CL-USER> (type-of (symbol-function 'if))
> > EXT:SPECIAL-OPERATOR
> > CL-USER> (type-of (symbol-function 'list))
> > COMPILED-FUNCTION
> 
> What about this?
> 
> * (type-of #'do)
> 
> FUNCTION
> * (type-of #'if)
> 
> FUNCTION
> * (type-of #'list)
> 
> FUNCTION
> * (type-of (symbol-function 'do))
> 
> FUNCTION
> * (type-of (symbol-function 'if))
> 
> FUNCTION
> * (type-of (symbol-function 'list))
> 
> FUNCTION
> *
> 
>  From SBCL....

Well, as I wrote, these results are implementation specific.  The joys
of using an underspecified language!


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: ·········@random-state.net
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <ce9snm$4bp8o$1@midnight.cs.hut.fi>
David Douthitt <·····@mailbag.com> wrote:
> Pascal Bourguignon wrote:

>> CL-USER> (type-of (symbol-function 'do))
>> SYSTEM::MACRO
>> CL-USER> (type-of (symbol-function 'if))
>> EXT:SPECIAL-OPERATOR
>> CL-USER> (type-of (symbol-function 'list))
>> COMPILED-FUNCTION

> What about this?
> * (type-of (symbol-function 'do))
> FUNCTION
> * (type-of (symbol-function 'if))
> FUNCTION
> * (type-of (symbol-function 'list))

To do this kind of thing portably:

 (defun op-type-of (symbol &optional env)
   (if (fboundp symbol)
       (cond ((macro-function symbol env) 
              'macro)
             ((special-operator-p symbol) 
              'special-operator)
             ((compiled-function-p (symbol-function symbol))
              'compiled-function)
             (t
              'interpreted-function))
       (error "Symbol ~S is not an operator." symbol)))

* (op-type-of 'do)
MACRO
* (op-type-of 'if)
SPECIAL-OPERATOR
* (op-type-of 'list)
COMPILED-FUNCTION

Generally speaking referring to CLHS is a better idea, though...

Cheers,

 -- Nikodemus                   "Not as clumsy or random as a C++ or Java. 
                             An elegant weapon for a more civilized time."
From: Pascal Costanza
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <ce4tql$r0o$1@f1node01.rhrz.uni-bonn.de>
neo88 wrote:

> I noticed in the Lisp Primer
> http://grimpeur.tamu.edu/~colin/lp/node36.html
> that they do something unusual in the sense I've never seen it with
> dolist before.
> 
> (defun num-sublists-i (lis)
>         (let ((result 0))
>            (dolist (next lis result)
>               (if (listp next) 
>                   (setf result (1+ result))))))

Hm, I have skimmed through that primer, and although I am not completely 
sure since I haven't read it in detail, this primer doesn't look too 
good to me. It actually reads more like a tutorial for Scheme than for Lisp.

Take a look at http://alu.cliki.net/Education - there are a number of 
good resources for learning Lisp. Maybe you will find them more helpful. 
Just my 0.02$


Pascal

-- 
Pascal Costanza               University of Bonn
···············@web.de        Institute of Computer Science III
http://www.pascalcostanza.de  R�merstr. 164, D-53117 Bonn (Germany)
From: Kalle Olavi Niemitalo
Subject: Re: Understanding Macro DOLIST
Date: 
Message-ID: <874qnt4j61.fsf@Astalo.kon.iki.fi>
······@truevine.net (neo88) writes:

> (defun num-sublists-i (lis)
>         (let ((result 0))
>            (dolist (next lis result)
>               (if (listp next) 
>                   (setf result (1+ result))))))

Some other ways to write this function:

  ;; Use INCF, and move the result form out of the DOLIST,
  ;; to make it more obvious when it will be evaluated.
  (defun num-sublists-i (lis)
    (let ((result 0))
      (dolist (next lis)
        (when (listp next)
          (incf result)))
      result))

  ;; The same logic, written as a LOOP.
  (defun num-sublists-i (lis)
    (loop with result = 0
          for next in lis
          do (when (listp next)
               (incf result))
          finally (return result)))

  ;; LOOP can count on its own.
  (defun num-sublists-i (lis)
    (loop for next in lis
          count (listp next)))

  ;; COUNT-IF can examine vectors as well.
  (defun num-sublists-i (lis)
    (count-if #'listp lis))

Also, in Common Lisp, the parameter should be called LIST rather
than LIS.

> Is the code. Note that
> (let ((result 0))
> is not the same thing as 
> (let ((result nil))

Consider the form (1+ result) at the end of the original function.
That would be an error if the value of RESULT were NIL.