From: John Connors
Subject: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <43cd9cfe$0$2697$ed2619ec@ptn-nntp-reader02.plus.net>
Yet Another Noob Question.

What are the characteristics of each implementation?

How can I tell which I should be writing in what context...

(defun find-indicies (lst tst)
   (let ((li 0))
	(labels ((qpred (a)
			   (incf li)
			   (if (funcall tst a)
				   (1- li)
				   nil)))
	  (remove nil (mapcar #'qpred lst)))))

(defun find-indices (lst tst)
   (loop
    for el in lst
    counting t into index
    if (funcall tst el)
    collect index))


CL-USER> (find-indices '(1 2 1 3) (lambda (x) (= 1 x)))
(1 3)

Hmm. Personally I'd prefer the second form for readability, but are tricks
like that closure in the first find-indices valid in some circumstances? From
reading around, I get the impression that a lot of experienced Lisp coders
would prefer the first. Is it just LOOP allergy, or is there something deeper?

I guess I'm asking - when do I map, when do I iterate   (and when do I
recurse?) ? CL's mapping constructs seem powerful enough to do the job of a
lot of iteration constructs in other languagesis it just a matter of taste,
or are there contexts where one or the other is usually preferred for
readability/portability/space/speed reasons?

And does LOOP have a more concise way of collecting the index of the element
being iterated over? And is there a way of avoiding the 1- in the first form?

Yes, it's a big question, but if you have a language that lets you do things
in so many ways, you have to be prepared for us noobs asking questions like
this, while blinking in the unaccustomed sunlight and getting slitghtly
agoraphobic, missing the confines of our nice, safe Java straightjacket..


And why did people create CLOS when a lisp function is perfectly capable of
encapsulating data and methods, and being what an "object" would be in
other OO langages?

John "noob" Connors

From: Eric Lavigne
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <1137550525.029952.302710@g47g2000cwa.googlegroups.com>
>And why did people create CLOS when a lisp function is
>perfectly capable of encapsulating data and methods, and
>being what an "object" would be in other OO langages?

Paul Graham has occassionally asked the same question. CLOS isn't
necessary. Most things in Common Lisp aren't necessary. Like Perl,
Common Lisp took the strategy of taking anything that looked useful and
tossing it into the blender to see what would come out. If you prefer
to ignore half the language, feel free.

http://paulgraham.com/noop.html

On the other hand, I think it is easier to just use CLOS than to
constantly reinvent it from closures :-)
From: Wade Humeniuk
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <Bmizf.96264$6K2.88604@edtnps90>
John Connors wrote:
> 
> Yet Another Noob Question.
> 
> What are the characteristics of each implementation?
> 
> How can I tell which I should be writing in what context...
> 
> (defun find-indicies (lst tst)
>   (let ((li 0))
>     (labels ((qpred (a)
>                (incf li)
>                (if (funcall tst a)
>                    (1- li)
>                    nil)))
>       (remove nil (mapcar #'qpred lst)))))
> 
> (defun find-indices (lst tst)
>   (loop
>    for el in lst
>    counting t into index
>    if (funcall tst el)
>    collect index))

You are allergic to loop

(defun find-indices (list test)
   (loop for element in list
         for index from 1
         when (funcall test element) collect index))

Wade
From: Pascal Bourguignon
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <87oe2as1kq.fsf@thalassa.informatimago.com>
John Connors <·····@yagc.ndo.co.uk> writes:

> Yet Another Noob Question.
>
> What are the characteristics of each implementation?
>
> How can I tell which I should be writing in what context...
>
> (defun find-indicies (lst tst)
>    (let ((li 0))
> 	(labels ((qpred (a)
> 			   (incf li)
> 			   (if (funcall tst a)
> 				   (1- li)
> 				   nil)))
> 	  (remove nil (mapcar #'qpred lst)))))
>
> (defun find-indices (lst tst)
>    (loop
>     for el in lst
>     counting t into index
>     if (funcall tst el)
>     collect index))
>
>
> CL-USER> (find-indices '(1 2 1 3) (lambda (x) (= 1 x)))
> (1 3)

I like this:

(defun find-indices (list pred)
  (mapcan (let ((i 0)) (lambda (e) (incf i) (when (funcall pred e) (list i))))
          list))


> Hmm. Personally I'd prefer the second form for readability, 

I find this one  slightly more readable:

(defun find-indices (list pred)
  (loop
     :for index :from 1       ; (I can't see why you start from 1
     :for element :in list    ;  the first index is 0 (try nth)).
     :when (funcall pred element) :collect index))

(Use of keywords instead of symbols is to prevent name colision when
you use after a package that exports a symbol by the same name).

> but are tricks like that closure in the first find-indices valid in
> some circumstances? 

There's no need to shy away closures.  They're lightweight and useful.

> From reading around, I get the impression that a lot of experienced
> Lisp coders would prefer the first. Is it just LOOP allergy, or is
> there something deeper?

There's also DOLIST, DOTIMES, and DO, not counting libraries like the
ITERATE package.  You use the one that's you like best.

MAPCAR & family may be more indicated when you have a function
argument, like the predicate of find-indices, especially if you can
just pass it to the mapping function without a new LAMBDA.


> I guess I'm asking - when do I map, when do I iterate   (and when do I
> recurse?) ? CL's mapping constructs seem powerful enough to do the job of a
> lot of iteration constructs in other languagesis it just a matter of taste,
> or are there contexts where one or the other is usually preferred for
> readability/portability/space/speed reasons?

You can improve the usability of the MAP  familly of functions by
writting more higher order functions.

For example, you notice for your find-indices that you need to
generate indexes. You can extract this requirement and abstract it
away in a higher order function:


(defun make-indexer (predicate)
  (let ((index 0))
    (lambda (x) (incf index) (when (funcall predicate x) (list index)))))

Then you can write find-indices simply as:

(defun find-indices (list predicate)  (mapcan (make-indexer predicate) list))


Once you have a convenient library of such higher order functions,
you'll be able to think and write your program at a higher level than
writing loops.


> And does LOOP have a more concise way of collecting the index of the element
> being iterated over? And is there a way of avoiding the 1- in the first form?

Just start from -1 instead of 0!


> Yes, it's a big question, but if you have a language that lets you do things
> in so many ways, you have to be prepared for us noobs asking questions like
> this, while blinking in the unaccustomed sunlight and getting slitghtly
> agoraphobic, missing the confines of our nice, safe Java straightjacket..
>
>
> And why did people create CLOS when a lisp function is perfectly capable of
> encapsulating data and methods, and being what an "object" would be in
> other OO langages?

To implement AI programs.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Cats meow out of angst
"Thumbs! If only we had thumbs!
We could break so much!"
From: Tayssir John Gabbour
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <1137600483.918246.108380@z14g2000cwz.googlegroups.com>
Pascal Bourguignon wrote:
> John Connors <·····@yagc.ndo.co.uk> writes:
> > From reading around, I get the impression that a lot of experienced
> > Lisp coders would prefer the first. Is it just LOOP allergy, or is
> > there something deeper?
>
> There's also DOLIST, DOTIMES, and DO, not counting libraries like the
> ITERATE package.  You use the one that's you like best.
>
> MAPCAR & family may be more indicated when you have a function
> argument, like the predicate of find-indices, especially if you can
> just pass it to the mapping function without a new LAMBDA.

Yeah, and at a Lisp meeting when Sven-Olof Nystrom showed off his
iteration package, he did a little poll, and it turned out most people
used loop.  Much more than other stuff like map/reduce and whatnot.

(He didn't ask about Series, but I know at least one person there liked
it...)


> (defun make-indexer (predicate)
>   (let ((index 0))
>     (lambda (x) (incf index) (when (funcall predicate x) (list index)))))
>
> Then you can write find-indices simply as:
>
> (defun find-indices (list predicate)  (mapcan (make-indexer predicate) list))

That's interesting. I've never seen mapping functions used in a way
which depends on their left-to-right guarantees in Common Lisp, though
it makes sense.

Here's a Series version:

(use-package :series)

;; TEST and LIST reversed to be more idiomatic lisp...
(defun find-indices (test list)
  (collect (positions (scan (mapcar test list)))))

I hadn't really used Series before. But the nice thing is at first I
was going to construct an infinite series with indices (0 1 2 3...),
and see if I could filter them. But POSITIONS made this a lot
simpler...


> > And why did people create CLOS when a lisp function is perfectly capable of
> > encapsulating data and methods, and being what an "object" would be in
> > other OO langages?
>
> To implement AI programs.

And I believe to show a real bad-ass OOP system. (To non-US people,
bad-ass is a good thing.)

To the orig poster... Why wouldn't someone create CLOS? In many ways,
Lisp isn't really all that different from other languages. So its users
still want an OOP system. Not an artificially pure language, but a
cosmopolitan one.

My (brief) readings of AI suggest that it has broader influences than
typical software; more than the narrow purview of bizapps and what
might be sold for profit. Instead, AI people seemed to combine
computing with many other disciplines.

So it seems that the AI influence on Lisp was very positive. (Despite
the insane marketing claims made for AI, which even AI researchers
seemed to know were far overblown. If we were to believe the claims for
"Web 1.0", we'd expect to live in a participatory democratic utopia,
where everyone would gladly offer books and movies cheaply online, and
10 year olds would be CEOs.)


Tayssir
From: Tayssir John Gabbour
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <1137602205.069068.193440@g14g2000cwa.googlegroups.com>
Tayssir John Gabbour wrote:
> Pascal Bourguignon wrote:
>
> > (defun make-indexer (predicate)
> >   (let ((index 0))
> >     (lambda (x) (incf index) (when (funcall predicate x) (list index)))))
> >
> > Then you can write find-indices simply as:
> >
> > (defun find-indices (list predicate)  (mapcan (make-indexer predicate) list))
>
> That's interesting. I've never seen mapping functions used in a way
> which depends on their left-to-right guarantees in Common Lisp, though
> it makes sense.
>
> Here's a Series version:
>
> (use-package :series)
>
> ;; TEST and LIST reversed to be more idiomatic lisp...
> (defun find-indices (test list)
>   (collect (positions (scan (mapcar test list)))))

Incidentally, a more principled version would look like:

(defun find-indices (test list)
  (collect (positions (map-fn t test (scan list)))))

I'm guessing I should use T rather than 'BOOLEAN because I don't know
what TEST returns...

I hope that Series can do implicit memoization on things like toy
Fibonacci examples...


Tayssir
From: Peter Seibel
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <m2psmhaas9.fsf@gigamonkeys.com>
Pascal Bourguignon <····@mouse-potato.com> writes:

> (defun find-indices (list pred)
>   (loop
>      :for index :from 1       ; (I can't see why you start from 1
>      :for element :in list    ;  the first index is 0 (try nth)).
>      :when (funcall pred element) :collect index))
>
> (Use of keywords instead of symbols is to prevent name colision when
> you use after a package that exports a symbol by the same name).

What bad consequence of such "name collisions" are you worried about?
I can see maybe wanting to use keywords to make them stand out to the
human eye, but for exactly the same reason you can use keywords you
can use any symbol, from any package, with the right SYMBOL-NAME.
Which I'm sure you know. So I wonder why you're trying to scare the
newbies with this vague threat of bad things possibly happening in the
future that can't actually happen. Or am I totally missing something?

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Thomas A. Russ
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <ymislrdfmfx.fsf@sevak.isi.edu>
Peter Seibel <·····@gigamonkeys.com> writes:

> 
> Pascal Bourguignon <····@mouse-potato.com> writes:
> 
> > (defun find-indices (list pred)
> >   (loop
> >      :for index :from 1       ; (I can't see why you start from 1
> >      :for element :in list    ;  the first index is 0 (try nth)).
> >      :when (funcall pred element) :collect index))
> >
> > (Use of keywords instead of symbols is to prevent name colision when
> > you use after a package that exports a symbol by the same name).
> 
> What bad consequence of such "name collisions" are you worried about?

My guess is that there is some danger that you will write a loop like
  (loop for i from 1 to 5 ...)
And then later use a package that exports the symbol "FROM".  At that
point you have name collision between FROM in your package and in the
imported package.

I agree that this isn't too likely to happen if you follow the practice
of setting up your package in advance with DEFPACKAGE and then not USE
other packages later.  In that case, your namespace is setup properly
from the beginning and you won't have such problems.

It's not an issue I worry about.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Pascal Bourguignon
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <87ek2x2uev.fsf@thalassa.informatimago.com>
···@sevak.isi.edu (Thomas A. Russ) writes:

> Peter Seibel <·····@gigamonkeys.com> writes:
>
>> 
>> Pascal Bourguignon <····@mouse-potato.com> writes:
>> 
>> > (defun find-indices (list pred)
>> >   (loop
>> >      :for index :from 1       ; (I can't see why you start from 1
>> >      :for element :in list    ;  the first index is 0 (try nth)).
>> >      :when (funcall pred element) :collect index))
>> >
>> > (Use of keywords instead of symbols is to prevent name colision when
>> > you use after a package that exports a symbol by the same name).
>> 
>> What bad consequence of such "name collisions" are you worried about?
>
> My guess is that there is some danger that you will write a loop like
>   (loop for i from 1 to 5 ...)
> And then later use a package that exports the symbol "FROM".  At that
> point you have name collision between FROM in your package and in the
> imported package.
>
> I agree that this isn't too likely to happen if you follow the practice
> of setting up your package in advance with DEFPACKAGE and then not USE
> other packages later.  In that case, your namespace is setup properly
> from the beginning and you won't have such problems.
>
> It's not an issue I worry about.

Neither do I worry about it, I just use keywords and free my mind for
other problems.

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

This universe shipped by weight, not volume.  Some expansion may have
occurred during shipment.
From: Pascal Bourguignon
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <87zmll4l5w.fsf@thalassa.informatimago.com>
Peter Seibel <·····@gigamonkeys.com> writes:

> Pascal Bourguignon <····@mouse-potato.com> writes:
>
>> (defun find-indices (list pred)
>>   (loop
>>      :for index :from 1       ; (I can't see why you start from 1
>>      :for element :in list    ;  the first index is 0 (try nth)).
>>      :when (funcall pred element) :collect index))
>>
>> (Use of keywords instead of symbols is to prevent name colision when
>> you use after a package that exports a symbol by the same name).
>
> What bad consequence of such "name collisions" are you worried about?

Name collisions can have catastrophic consequences when they occur in
non-interactive executions.  And anyways, I'm lazy, I don't like to
answer silly questions about what symbols I want by the restart code...


> I can see maybe wanting to use keywords to make them stand out to the
> human eye, but for exactly the same reason you can use keywords you
> can use any symbol, from any package, with the right SYMBOL-NAME.
> Which I'm sure you know. So I wonder why you're trying to scare the
> newbies with this vague threat of bad things possibly happening in the
> future that can't actually happen. Or am I totally missing something?

Well, it actually happened to me.


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

READ THIS BEFORE OPENING PACKAGE: According to certain suggested
versions of the Grand Unified Theory, the primary particles
constituting this product may decay to nothingness within the next
four hundred million years.
From: Coby Beck
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <XQuBf.94956$m05.91701@clgrps12>
"Pascal Bourguignon" <····@mouse-potato.com> wrote in message 
···················@thalassa.informatimago.com...
> Peter Seibel <·····@gigamonkeys.com> writes:
>
>> Pascal Bourguignon <····@mouse-potato.com> writes:
>>
>>> (defun find-indices (list pred)
>>>   (loop
>>>      :for index :from 1       ; (I can't see why you start from 1
>>>      :for element :in list    ;  the first index is 0 (try nth)).
>>>      :when (funcall pred element) :collect index))
>>>
>>> (Use of keywords instead of symbols is to prevent name colision when
>>> you use after a package that exports a symbol by the same name).
>>
>> What bad consequence of such "name collisions" are you worried about?
>
> Name collisions can have catastrophic consequences when they occur in
> non-interactive executions.  And anyways, I'm lazy, I don't like to
> answer silly questions about what symbols I want by the restart code...
>
>
>> I can see maybe wanting to use keywords to make them stand out to the
>> human eye, but for exactly the same reason you can use keywords you
>> can use any symbol, from any package, with the right SYMBOL-NAME.
>> Which I'm sure you know. So I wonder why you're trying to scare the
>> newbies with this vague threat of bad things possibly happening in the
>> future that can't actually happen. Or am I totally missing something?
>
> Well, it actually happened to me.

Please share.  I can't think of what could possibly go wrong either.  And 
given how unidiomatic it is, it is worth knowing if there actually is some 
danger.

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Pascal Bourguignon
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <87mzhl2ymc.fsf@thalassa.informatimago.com>
"Coby Beck" <·····@mercury.bc.ca> writes:

> "Pascal Bourguignon" <····@mouse-potato.com> wrote in message 
> ···················@thalassa.informatimago.com...
>> Peter Seibel <·····@gigamonkeys.com> writes:
>>
>>> Pascal Bourguignon <····@mouse-potato.com> writes:
>>>
>>>> (defun find-indices (list pred)
>>>>   (loop
>>>>      :for index :from 1       ; (I can't see why you start from 1
>>>>      :for element :in list    ;  the first index is 0 (try nth)).
>>>>      :when (funcall pred element) :collect index))
>>>>
>>>> (Use of keywords instead of symbols is to prevent name colision when
>>>> you use after a package that exports a symbol by the same name).
>>>
>>> What bad consequence of such "name collisions" are you worried about?
>>
>> Name collisions can have catastrophic consequences when they occur in
>> non-interactive executions.  And anyways, I'm lazy, I don't like to
>> answer silly questions about what symbols I want by the restart code...
>>
>>
>>> I can see maybe wanting to use keywords to make them stand out to the
>>> human eye, but for exactly the same reason you can use keywords you
>>> can use any symbol, from any package, with the right SYMBOL-NAME.
>>> Which I'm sure you know. So I wonder why you're trying to scare the
>>> newbies with this vague threat of bad things possibly happening in the
>>> future that can't actually happen. Or am I totally missing something?
>>
>> Well, it actually happened to me.
>
> Please share.  I can't think of what could possibly go wrong either.  And 
> given how unidiomatic it is, it is worth knowing if there actually is some 
> danger.

I already explained it.

(defpackage :p1
 (:use :cl) (:export :for))
(in-package :p1)
(defmacro for ((var init limit increment) &body body)
   `(do ((,var ,init ,increment))
        ((not ,limit))
       ,@body))
(in-package :cl-user)
(loop for i from 1 to 10 collect i)
(use-package :p1)


#<PACKAGE P1>
[398]> #<PACKAGE P1>
P1[399]> FOR
P1[400]> #<PACKAGE COMMON-LISP-USER>
[401]> (1 2 3 4 5 6 7 8 9 10)
[402]> 
*** - (USE-PACKAGE (#<PACKAGE P1>) #<PACKAGE COMMON-LISP-USER>): 1 name
      conflicts remain
      Which symbol with name "FOR" should be accessible in
       #<PACKAGE COMMON-LISP-USER>
      ?
The following restarts are available:
P1             :R1      #<PACKAGE P1>
COMMON-LISP-USER :R2    #<PACKAGE COMMON-LISP-USER>
ABORT          :R3      ABORT
Break 1 [403]> 

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

"A TRUE Klingon warrior does not comment his code!"
From: Bill Atkins
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <87y815qq7s.fsf@rpi.edu>
Pascal Bourguignon <····@mouse-potato.com> writes:

> "Coby Beck" <·····@mercury.bc.ca> writes:
>
>> "Pascal Bourguignon" <····@mouse-potato.com> wrote in message 
>> ···················@thalassa.informatimago.com...
>>> Peter Seibel <·····@gigamonkeys.com> writes:
>>>
>>>> Pascal Bourguignon <····@mouse-potato.com> writes:
>>>>
>>>>> (defun find-indices (list pred)
>>>>>   (loop
>>>>>      :for index :from 1       ; (I can't see why you start from 1
>>>>>      :for element :in list    ;  the first index is 0 (try nth)).
>>>>>      :when (funcall pred element) :collect index))
>>>>>
>>>>> (Use of keywords instead of symbols is to prevent name colision when
>>>>> you use after a package that exports a symbol by the same name).
>>>>
>>>> What bad consequence of such "name collisions" are you worried about?
>>>
>>> Name collisions can have catastrophic consequences when they occur in
>>> non-interactive executions.  And anyways, I'm lazy, I don't like to
>>> answer silly questions about what symbols I want by the restart code...
>>>
>>>
>>>> I can see maybe wanting to use keywords to make them stand out to the
>>>> human eye, but for exactly the same reason you can use keywords you
>>>> can use any symbol, from any package, with the right SYMBOL-NAME.
>>>> Which I'm sure you know. So I wonder why you're trying to scare the
>>>> newbies with this vague threat of bad things possibly happening in the
>>>> future that can't actually happen. Or am I totally missing something?
>>>
>>> Well, it actually happened to me.
>>
>> Please share.  I can't think of what could possibly go wrong either.  And 
>> given how unidiomatic it is, it is worth knowing if there actually is some 
>> danger.
>
> I already explained it.
>
> (defpackage :p1
>  (:use :cl) (:export :for))
> (in-package :p1)
> (defmacro for ((var init limit increment) &body body)
>    `(do ((,var ,init ,increment))
>         ((not ,limit))
>        ,@body))
> (in-package :cl-user)
> (loop for i from 1 to 10 collect i)
> (use-package :p1)
>
>
> #<PACKAGE P1>
> [398]> #<PACKAGE P1>
> P1[399]> FOR
> P1[400]> #<PACKAGE COMMON-LISP-USER>
> [401]> (1 2 3 4 5 6 7 8 9 10)
> [402]> 
> *** - (USE-PACKAGE (#<PACKAGE P1>) #<PACKAGE COMMON-LISP-USER>): 1 name
>       conflicts remain
>       Which symbol with name "FOR" should be accessible in
>        #<PACKAGE COMMON-LISP-USER>
>       ?
> The following restarts are available:
> P1             :R1      #<PACKAGE P1>
> COMMON-LISP-USER :R2    #<PACKAGE COMMON-LISP-USER>
> ABORT          :R3      ABORT
> Break 1 [403]> 
>
> -- 
> __Pascal Bourguignon__                     http://www.informatimago.com/
>
> "A TRUE Klingon warrior does not comment his code!"

But why would you export FOR from a package?  If you're exporting FOR
or FROM or some other loop keyword, shouldn't you expect the same
consequences as, say, exporting CONS?

--

Bill Atkins
From: Tayssir John Gabbour
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <1138151638.340272.17160@z14g2000cwz.googlegroups.com>
Bill Atkins wrote:
> Pascal Bourguignon <····@mouse-potato.com> writes:
> > (defpackage :p1
> >  (:use :cl) (:export :for))
> > (in-package :p1)
> > (defmacro for ((var init limit increment) &body body)
> >    `(do ((,var ,init ,increment))
> >         ((not ,limit))
> >        ,@body))
> > (in-package :cl-user)
> > (loop for i from 1 to 10 collect i)
> > (use-package :p1)
> >
> >
> > #<PACKAGE P1>
> > [398]> #<PACKAGE P1>
> > P1[399]> FOR
> > P1[400]> #<PACKAGE COMMON-LISP-USER>
> > [401]> (1 2 3 4 5 6 7 8 9 10)
> > [402]>
> > *** - (USE-PACKAGE (#<PACKAGE P1>) #<PACKAGE COMMON-LISP-USER>): 1 name
> >       conflicts remain
> >       Which symbol with name "FOR" should be accessible in
> >        #<PACKAGE COMMON-LISP-USER>
> >       ?
> > The following restarts are available:
> > P1             :R1      #<PACKAGE P1>
> > COMMON-LISP-USER :R2    #<PACKAGE COMMON-LISP-USER>
> > ABORT          :R3      ABORT
> > Break 1 [403]>
>
>
> But why would you export FOR from a package?  If you're exporting FOR
> or FROM or some other loop keyword, shouldn't you expect the same
> consequences as, say, exporting CONS?

Series uses a function called COLLECT.

Tayssir
From: Thomas A. Russ
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <ymilkx5f2tu.fsf@sevak.isi.edu>
Bill Atkins <············@rpi.edu> writes:
> 
> But why would you export FOR from a package?  If you're exporting FOR
> or FROM or some other loop keyword, shouldn't you expect the same
> consequences as, say, exporting CONS?

No, because the symbols FROM and FOR are not present in the Common Lisp
package.  The absence of the loop keywords from the Common Lisp package
is what makes this potentially troublesome, since they won't be the same
across all packages that use COMMON-LISP.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Pascal Bourguignon
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <8764o83fpw.fsf@thalassa.informatimago.com>
Bill Atkins <············@rpi.edu> writes:

> But why would you export FOR from a package?  If you're exporting FOR
> or FROM or some other loop keyword, shouldn't you expect the same
> consequences as, say, exporting CONS?

I have a C-like FOR and a emacs-lisp-like WHILE.  Legacy code...


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

READ THIS BEFORE OPENING PACKAGE: According to certain suggested
versions of the Grand Unified Theory, the primary particles
constituting this product may decay to nothingness within the next
four hundred million years.
From: Ivan Boldyrev
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <26pja3-8m.ln1@ibhome.cgitftp.uiggm.nsc.ru>
On 9365 day of my life Bill Atkins wrote:
> But why would you export FOR from a package?  If you're exporting FOR
> or FROM or some other loop keyword, shouldn't you expect the same
> consequences as, say, exporting CONS?

Loop keywords are not real keywords (and name identity is used, not
symbol identity).  And they are are not exported (or even interned) in
COMMON-LISP package, unlike CONS.  It is not sensible: programmer may
use symbols from any package for loop keywords: CL-USER, KEYWORD or
FOOBAR.

I prefer KEYWORD because Emacs highlights it differently :)

-- 
Ivan Boldyrev

                                                  Is 'morning' a gerund?
From: Coby Beck
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <iCwBf.94978$m05.25365@clgrps12>
"Pascal Bourguignon" <····@mouse-potato.com> wrote in message 
···················@thalassa.informatimago.com...
> "Coby Beck" <·····@mercury.bc.ca> writes:
>
>> "Pascal Bourguignon" <····@mouse-potato.com> wrote in message
>> ···················@thalassa.informatimago.com...
>>> Peter Seibel <·····@gigamonkeys.com> writes:
>>>
>>>> Pascal Bourguignon <····@mouse-potato.com> writes:
>>>>
>>>>> (defun find-indices (list pred)
>>>>>   (loop
>>>>>      :for index :from 1       ; (I can't see why you start from 1
>>>>>      :for element :in list    ;  the first index is 0 (try nth)).
>>>>>      :when (funcall pred element) :collect index))
>>>>>
>>>>> (Use of keywords instead of symbols is to prevent name colision when
>>>>> you use after a package that exports a symbol by the same name).
>>>>
>>>> What bad consequence of such "name collisions" are you worried about?
>>>
>>> Name collisions can have catastrophic consequences when they occur in
>>> non-interactive executions.  And anyways, I'm lazy, I don't like to
>>> answer silly questions about what symbols I want by the restart code...
>>>
>>>> I can see maybe wanting to use keywords to make them stand out to the
>>>> human eye, but for exactly the same reason you can use keywords you
>>>> can use any symbol, from any package, with the right SYMBOL-NAME.
>>>> Which I'm sure you know. So I wonder why you're trying to scare the
>>>> newbies with this vague threat of bad things possibly happening in the
>>>> future that can't actually happen. Or am I totally missing something?
>>>
>>> Well, it actually happened to me.
>>
>> Please share.  I can't think of what could possibly go wrong either.  And
>> given how unidiomatic it is, it is worth knowing if there actually is 
>> some
>> danger.
>
> I already explained it.
>
> (defpackage :p1
> (:use :cl) (:export :for))
> (in-package :p1)
> (defmacro for ((var init limit increment) &body body)
>   `(do ((,var ,init ,increment))
>        ((not ,limit))
>       ,@body))
> (in-package :cl-user)
> (loop for i from 1 to 10 collect i)
> (use-package :p1)
>
>
> #<PACKAGE P1>
> [398]> #<PACKAGE P1>
> P1[399]> FOR
> P1[400]> #<PACKAGE COMMON-LISP-USER>
> [401]> (1 2 3 4 5 6 7 8 9 10)
> [402]>
> *** - (USE-PACKAGE (#<PACKAGE P1>) #<PACKAGE COMMON-LISP-USER>): 1 name
>      conflicts remain
>      Which symbol with name "FOR" should be accessible in
>       #<PACKAGE COMMON-LISP-USER>
>      ?
> The following restarts are available:
> P1             :R1      #<PACKAGE P1>
> COMMON-LISP-USER :R2    #<PACKAGE COMMON-LISP-USER>
> ABORT          :R3      ABORT
> Break 1 [403]>

Sure, but no matter what restart you chose, is something broken?

Besides, the biggest lesson to learn here is do not call USE-PACKAGE from 
CL-USER, that is a very bad idea on its own, isn't it?

Does anybody out there work this way?  (Not rhetorical, I am curious)

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Pascal Bourguignon
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <87irs92ugp.fsf@thalassa.informatimago.com>
"Coby Beck" <·····@mercury.bc.ca> writes:
>> I already explained it.
>>
>> (defpackage :p1
>> (:use :cl) (:export :for))
>> (in-package :p1)
>> (defmacro for ((var init limit increment) &body body)
>>   `(do ((,var ,init ,increment))
>>        ((not ,limit))
>>       ,@body))
>> (in-package :cl-user)
>> (loop for i from 1 to 10 collect i)
>> (use-package :p1)
>>
>>
>> #<PACKAGE P1>
>> [398]> #<PACKAGE P1>
>> P1[399]> FOR
>> P1[400]> #<PACKAGE COMMON-LISP-USER>
>> [401]> (1 2 3 4 5 6 7 8 9 10)
>> [402]>
>> *** - (USE-PACKAGE (#<PACKAGE P1>) #<PACKAGE COMMON-LISP-USER>): 1 name
>>      conflicts remain
>>      Which symbol with name "FOR" should be accessible in
>>       #<PACKAGE COMMON-LISP-USER>
>>      ?
>> The following restarts are available:
>> P1             :R1      #<PACKAGE P1>
>> COMMON-LISP-USER :R2    #<PACKAGE COMMON-LISP-USER>
>> ABORT          :R3      ABORT
>> Break 1 [403]>
>
> Sure, but no matter what restart you chose, is something broken?

Yes.  All my programs that used plain symbols instead of keywords in
LOOP.


> Besides, the biggest lesson to learn here is do not call USE-PACKAGE from 
> CL-USER, that is a very bad idea on its own, isn't it?

You can substitute :cl-user for whatever package you want.

> Does anybody out there work this way?  (Not rhetorical, I am curious)

What way?  

Interactively, you may see me type (loop for ...), but in sources I
only use keywords: (LOOP :FOR ...).

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

This universe shipped by weight, not volume.  Some expansion may have
occurred during shipment.
From: Peter Seibel
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <m2lkx59nqd.fsf@gigamonkeys.com>
Pascal Bourguignon <····@mouse-potato.com> writes:

> "Coby Beck" <·····@mercury.bc.ca> writes:
>>> I already explained it.
>>>
>>> (defpackage :p1
>>> (:use :cl) (:export :for))
>>> (in-package :p1)
>>> (defmacro for ((var init limit increment) &body body)
>>>   `(do ((,var ,init ,increment))
>>>        ((not ,limit))
>>>       ,@body))
>>> (in-package :cl-user)
>>> (loop for i from 1 to 10 collect i)
>>> (use-package :p1)
>>>
>>>
>>> #<PACKAGE P1>
>>> [398]> #<PACKAGE P1>
>>> P1[399]> FOR
>>> P1[400]> #<PACKAGE COMMON-LISP-USER>
>>> [401]> (1 2 3 4 5 6 7 8 9 10)
>>> [402]>
>>> *** - (USE-PACKAGE (#<PACKAGE P1>) #<PACKAGE COMMON-LISP-USER>): 1 name
>>>      conflicts remain
>>>      Which symbol with name "FOR" should be accessible in
>>>       #<PACKAGE COMMON-LISP-USER>
>>>      ?
>>> The following restarts are available:
>>> P1             :R1      #<PACKAGE P1>
>>> COMMON-LISP-USER :R2    #<PACKAGE COMMON-LISP-USER>
>>> ABORT          :R3      ABORT
>>> Break 1 [403]>
>>
>> Sure, but no matter what restart you chose, is something broken?
>
> Yes.  All my programs that used plain symbols instead of keywords in
> LOOP.
>
>
>> Besides, the biggest lesson to learn here is do not call
>> USE-PACKAGE from CL-USER, that is a very bad idea on its own, isn't
>> it?
>
> You can substitute :cl-user for whatever package you want.

Okay, I see what problem you are avoiding. On the other hand, nobody
will have this problem who follows what I think of as the first rule
of Common Lisp package sanity:

  Completely define a package, and all its package use relationships
  before you read any code/data in that package.

If you choose to not follow this rule, yes you could run into this
problem. As you could if you did this:

  CL-USER> (defpackage :p1 (:use :cl) (:export :a :b :c))
  #<The P1 package>
  CL-USER> (defpackage :p2 (:use :cl))
  #<The P2 package>
  CL-USER> (in-package :p2)
  #<The P2 package>
  P2> '(a b c)
  (A B C)
  P2> (use-package :p1)
  < off to the debugger because of name conflicts >

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: John Thingstad
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <op.s3xpf9k2pqzri1@mjolner.upc.no>
On Wed, 25 Jan 2006 01:04:41 +0100, Peter Seibel <·····@gigamonkeys.com>  
wrote:

>   Completely define a package, and all its package use relationships
>   before you read any code/data in that package.
>

I might add use the shadow option of defpackage when a conflict aries.

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: Thomas F. Burdick
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <xcvr76wy9mr.fsf@conquest.OCF.Berkeley.EDU>
Pascal Bourguignon <····@mouse-potato.com> writes:

> "Coby Beck" <·····@mercury.bc.ca> writes:
>
> > Sure, but no matter what restart you chose, is something broken?
> 
> Yes.  All my programs that used plain symbols instead of keywords in
> LOOP.

But what's broken?  All your loops will still work.  Your symbols
don't have to be in any package at all:

  (loop #:for x #:from 1 #:to 10 #:collect x)

> > Does anybody out there work this way?  (Not rhetorical, I am curious)
> 
> What way?  
> 
> Interactively, you may see me type (loop for ...), but in sources I
> only use keywords: (LOOP :FOR ...).

This seems exactly backwards to me.  The problem you had was because
you interactively used a new package.  Since you presumably don't
programattically use random packages at runtime, the only time you'll
get this problem is in interactive sessions.

Anyhow, please don't use the keyword variation in postings to c.l.l.
A lot of newbies think the package system is impenetrable black magic,
and I think this will only further confuse them, because the potential
for error is so obscure.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Joe Marshall
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <1138207326.440631.257100@o13g2000cwo.googlegroups.com>
Thomas F. Burdick wrote:
>
> But what's broken?  All your loops will still work.  Your symbols
> don't have to be in any package at all:
>
>   (loop #:for x #:from 1 #:to 10 #:collect x)

This is, of course, less efficient because the gensyms aren't shared.

> Anyhow, please don't use the keyword variation in postings to c.l.l.
> A lot of newbies think the package system is impenetrable black magic,
> and I think this will only further confuse them, because the potential
> for error is so obscure.

It is important to confuse newbies only with the obscure errors they
are likely to make rather than preventing errors they are unlikely to
encounter.
From: Ivan Boldyrev
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <4phma3-3km.ln1@ibhome.cgitftp.uiggm.nsc.ru>
On 9365 day of my life Joe Marshall wrote:
>> But what's broken?  All your loops will still work.  Your symbols
>> don't have to be in any package at all:
>>
>>   (loop #:for x #:from 1 #:to 10 #:collect x)
>
> This is, of course, less efficient because the gensyms aren't shared.

What are you smoking?

Runtime efficiency is same.  Compilation speed is same.  Readtime
efficiency is even better: reader avoids hashtable lookups, just
creates new symbol, and it is constant-time operation, while hashtable
lookup is little slower than O(1).

-- 
Ivan Boldyrev

                  Sorry my terrible English, my native language is Lisp!
From: Duncan Harvey
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <1h9rvg4.1r1i5vpu9aq6aN%usenet-2006-01@abbrvtd.org.uk>
Ivan Boldyrev <···············@cgitftp.uiggm.nsc.ru> wrote:

> On 9365 day of my life Joe Marshall wrote:
> >> But what's broken?  All your loops will still work.  Your symbols
> >> don't have to be in any package at all:
> >>
> >>   (loop #:for x #:from 1 #:to 10 #:collect x)
> >
> > This is, of course, less efficient because the gensyms aren't shared.
> 
> What are you smoking?

I suspect Joe was impressing us with his wit.  I'll admit it's difficult
to tell.

> Runtime efficiency is same.  Compilation speed is same.  Readtime
> efficiency is even better: [...]

But that's not a complete enumeration of the efficiency space.  Other
dimensions might include: space efficiency;  package size efficiency;
garbage collector invocation efficiency;  number of hash characters in
printed representation efficiency;  and so on.  The list is pointless.

-- 
Duncan Harvey
From: Pascal Bourguignon
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <87ek2w1ksl.fsf@thalassa.informatimago.com>
···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:

> Pascal Bourguignon <····@mouse-potato.com> writes:
>
>> "Coby Beck" <·····@mercury.bc.ca> writes:
>>
>> > Sure, but no matter what restart you chose, is something broken?
>> 
>> Yes.  All my programs that used plain symbols instead of keywords in
>> LOOP.
>
> But what's broken?  

Read the thread.


> All your loops will still work.  Your symbols
> don't have to be in any package at all:
>
>   (loop #:for x #:from 1 #:to 10 #:collect x)
>
>> > Does anybody out there work this way?  (Not rhetorical, I am curious)
>> 
>> What way?  
>> 
>> Interactively, you may see me type (loop for ...), but in sources I
>> only use keywords: (LOOP :FOR ...).
>
> This seems exactly backwards to me.  The problem you had was because
> you interactively used a new package.  Since you presumably don't
> programattically use random packages at runtime, the only time you'll
> get this problem is in interactive sessions.

Interactively, this is not a problem because I'm here to choose which
symbol should be imported.  In unattended execution (scripts or
programs) it's a problem.


> Anyhow, please don't use the keyword variation in postings to c.l.l.
> A lot of newbies think the package system is impenetrable black magic,
> and I think this will only further confuse them, because the potential
> for error is so obscure.

Please, deliver 10 tn of sand, we have some newbie heads to bury.


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

HANDLE WITH EXTREME CARE: This product contains minute electrically
charged particles moving at velocities in excess of five hundred
million miles per hour.
From: Thomas F. Burdick
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <xcvd5igxufa.fsf@conquest.OCF.Berkeley.EDU>
Pascal Bourguignon <····@mouse-potato.com> writes:

> ···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:
> 
> > Pascal Bourguignon <····@mouse-potato.com> writes:
> >
> >> "Coby Beck" <·····@mercury.bc.ca> writes:
> >>
> >> > Sure, but no matter what restart you chose, is something broken?
> >> 
> >> Yes.  All my programs that used plain symbols instead of keywords in
> >> LOOP.
> >
> > But what's broken?  
> 
> Read the thread.

Read the question.  Or better yet, grow some manners.

> > All your loops will still work.  Your symbols
> > don't have to be in any package at all:

So are you saying that with any of the available restarts your LOOPs
don't work?  Or are you maybe avoiding the question by rudely
dismissing anyone who asks it.

> > This seems exactly backwards to me.  The problem you had was because
> > you interactively used a new package.  Since you presumably don't
> > programattically use random packages at runtime, the only time you'll
> > get this problem is in interactive sessions.
> 
> Interactively, this is not a problem because I'm here to choose which
> symbol should be imported.  In unattended execution (scripts or
> programs) it's a problem.

What???  You write unattended scripts that randomly use other packages
programatically at runtime?  Only perverse code could possibly run
into this as a problem in unattended code.  Do you also call
check-type on all arguments you pass to + before doing so, because you
might have an unattended program that randomly recompiles itself at
(safety 0)?

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Pascal Bourguignon
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <87irs8z89i.fsf@thalassa.informatimago.com>
···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:
> What???  You write unattended scripts that randomly use other packages
> programatically at runtime?  Only perverse code could possibly run
> into this as a problem in unattended code.  Do you also call
> check-type on all arguments you pass to + before doing so, because you
> might have an unattended program that randomly recompiles itself at
> (safety 0)?

Even with non random code, when you use M-x compile RET in emacs you
only have output, you cannot input anything to respond to a restart.

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

PLEASE NOTE: Some quantum physics theories suggest that when the
consumer is not directly observing this product, it may cease to
exist or will exist only in a vague and undetermined state.
From: Thomas F. Burdick
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <xcv4q3rxpd5.fsf@conquest.OCF.Berkeley.EDU>
Pascal Bourguignon <····@mouse-potato.com> writes:

> ···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:
> > What???  You write unattended scripts that randomly use other packages
> > programatically at runtime?  Only perverse code could possibly run
> > into this as a problem in unattended code.  Do you also call
> > check-type on all arguments you pass to + before doing so, because you
> > might have an unattended program that randomly recompiles itself at
> > (safety 0)?
> 
> Even with non random code, when you use M-x compile RET in emacs you
> only have output, you cannot input anything to respond to a restart.

So it comes down to this: you're advocating using keywords in loops to
make it easier to not screw up when developing Lisp in a batch
compiled manner?  What the hell?

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Pascal Bourguignon
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <87y813xfdl.fsf@thalassa.informatimago.com>
···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:

> Pascal Bourguignon <····@mouse-potato.com> writes:
>
>> ···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:
>> > What???  You write unattended scripts that randomly use other packages
>> > programatically at runtime?  Only perverse code could possibly run
>> > into this as a problem in unattended code.  Do you also call
>> > check-type on all arguments you pass to + before doing so, because you
>> > might have an unattended program that randomly recompiles itself at
>> > (safety 0)?
>> 
>> Even with non random code, when you use M-x compile RET in emacs you
>> only have output, you cannot input anything to respond to a restart.
>
> So it comes down to this: you're advocating using keywords in loops to
> make it easier to not screw up when developing Lisp in a batch
> compiled manner?  What the hell?

I don't advocate anything, you do as you want.  I was asked why I used
keywords and I answered.  Simple as that.


(Another reason, but not serrious, is that it makes it look more lispy
with the keywords arguments, like (any-fun :k1 x :k2 y :k3 z)).

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
You never feed me.
Perhaps I'll sleep on your face.
That will sure show you.
From: Bill Atkins
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <871wyvek8j.fsf@rpi.edu>
···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:

> Anyhow, please don't use the keyword variation in postings to c.l.l.
> A lot of newbies think the package system is impenetrable black magic,
> and I think this will only further confuse them, because the potential
> for error is so obscure.

It certainly confused me when I was new to Lisp and would see loop
code posted here with keywords.  And yes, it made the packaging system
seem much more kludgy and difficult than it actually is.

--

Bill Atkins
From: Thomas A. Russ
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <ymid5idr37a.fsf@sevak.isi.edu>
Bill Atkins <············@rpi.edu> writes:

> ···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:
> 
> > Anyhow, please don't use the keyword variation in postings to c.l.l.
> > A lot of newbies think the package system is impenetrable black magic,
> > and I think this will only further confuse them, because the potential
> > for error is so obscure.
> 
> It certainly confused me when I was new to Lisp and would see loop
> code posted here with keywords.  And yes, it made the packaging system
> seem much more kludgy and difficult than it actually is.

My main objection to using keywords in LOOP is that to my eyes, it makes
the LOOP keywords become much more prominent, when I would prefer to
have them blend in more with the background (kind of like parentheses).
I don't want the LOOP syntax markers drawing my attention away from my
own code, which is what is the main variant part of LOOP invocations.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Coby Beck
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <DaFBf.95827$m05.68667@clgrps12>
"Pascal Bourguignon" <····@mouse-potato.com> wrote in message 
···················@thalassa.informatimago.com...
> "Coby Beck" <·····@mercury.bc.ca> writes:
>>> I already explained it.
>>
>> Sure, but no matter what restart you chose, is something broken?
>
> Yes.  All my programs that used plain symbols instead of keywords in
> LOOP.

Really?  Why, loop uses the symbol-name, it does not care what package it 
comes from.

CL-USER 28 > (defpackage "FOO")
#<PACKAGE FOO>

CL-USER 29 > (loop foo::for i foo::below 5 foo::do (print i))

0
1
2
3
4
NIL


-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Pascal Bourguignon
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <87acdk3fry.fsf@thalassa.informatimago.com>
"Coby Beck" <·····@mercury.bc.ca> writes:

> "Pascal Bourguignon" <····@mouse-potato.com> wrote in message 
> ···················@thalassa.informatimago.com...
>> "Coby Beck" <·····@mercury.bc.ca> writes:
>>>> I already explained it.
>>>
>>> Sure, but no matter what restart you chose, is something broken?
>>
>> Yes.  All my programs that used plain symbols instead of keywords in
>> LOOP.
>
> Really?  Why, loop uses the symbol-name, it does not care what package it 
> comes from.

Read the thread!

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

READ THIS BEFORE OPENING PACKAGE: According to certain suggested
versions of the Grand Unified Theory, the primary particles
constituting this product may decay to nothingness within the next
four hundred million years.
From: Jason Kantz
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <1137613778.780929.53970@f14g2000cwb.googlegroups.com>
John Connors writes:
> I guess I'm asking - when do I map, when do I iterate   (and when do I
> recurse?)

In trivial cases, whether to use loop or not is likely a matter of
taste.  A common rule of thumb is: if you are a new to loop, keep it
simple, avoid complex inter-related loop clauses.

Your problem will probably dictate your approach to iteration. For
example, tree structured data usually lends itself to recursion.  You
have many options because CL is meant to be adaptable to many
programming paradigms.  A functional programming nerd might write:

(defun bind (f &rest bound-args)
  (lambda (&rest args)
    (apply f (append bound-args args))))

(defun fold (f acc list)
  (reduce f list :initial-value acc))

(defun find-indices (test list)
  (reverse
   (cdr
    (fold (lambda (acc list-elt)
            (cons (1+ (car acc))
                  (if (funcall test list-elt)
                      acc
                      (cdr acc))))
          '(0 . nil)
          list))))

(find-indices (bind #'= 1) '(1 2 1 3))

But if you're just hacking up some basic code, you would go by the
principle of least astonishment and use loop or mapcan as others have
suggested:

(defun find-indices (test list)
  (loop for index from 0
        for element in list
        when (funcall test element)
        collect index))

To learn more about loop there is a tutorial at
http://www.ai.sri.com/~pkarp/loop.html

Here is a summary of loop clauses:
http://www.lisp.org/HyperSpec/Body/sec_6-1-1-5.html

The use of mapcan as an idiom for filtering is noted on The ALU's
programming style page: http://www.lisp.org/table/style.htm

A very good resource for learning more lisp idioms:
Tutorial on Good Lisp Programming Style 
http://norvig.com/luv-slides.ps
From: ··········@gmail.com
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <1138130488.878107.303880@g44g2000cwa.googlegroups.com>
Jason Kantz wrote:
 A functional programming nerd might write:
>
> (defun bind (f &rest bound-args)
>   (lambda (&rest args)
>     (apply f (append bound-args args))))
>
> (defun fold (f acc list)
>   (reduce f list :initial-value acc))
>
> (defun find-indices (test list)
>   (reverse
>    (cdr
>     (fold (lambda (acc list-elt)
>             (cons (1+ (car acc))
>                   (if (funcall test list-elt)
>                       acc
>                       (cdr acc))))
>           '(0 . nil)
>           list))))
>
> (find-indices (bind #'= 1) '(1 2 1 3))


An fp nerd could do a little better:

(defun find-indices (list pred)
  (labels ((lp (list n)
	       (cond ((null list) '())
		     ((funcall pred (car list))
		      (cons n (lp (cdr list) (1+ n))))
		     (t (lp (cdr list) (1+ n))))))
	  (lp list 0)))

I wonder how a real fp nerd (which I'm not) would do it, given a decent
library like you would get in an fp language like Scheme (real
implementations, not R5RS), ML, or Haskell.
From: Jason Kantz
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <1138137118.474248.310190@g49g2000cwa.googlegroups.com>
I'm not a real fp nerd either--just an interested outside observer of
that approach.

If you're going for readability, this recursive version is it.  But as
with anything, better depends on context & purpose.  Depending on your
lisp and its settings, the recursive formulation might run into a stack
overflow on very big lists, but the use of fold will not.

We could also have some fun with a version that uses pattern matching.
A fun and challenging exercise for a beginner might be to write a macro
and support code that makes the following work.  [Hint: CL-UNIFICATION
would be a good helper library.]

(defun* find-indices (test list)
  (find-indices test list 0))

(defun* find-indices (test (first . rest) i)
  (if (funcall test first)
      (cons i (find-indices test rest (1+ i)))
      (find-indices test rest (1+ i))))

(defun* find-indices (test '() i)
  '())
From: Thomas A. Russ
Subject: Re: YANQ - When to map, when to iterate, when to recurse? And why CLOS?
Date: 
Message-ID: <ymimzhtgvgc.fsf@sevak.isi.edu>
John Connors <·····@yagc.ndo.co.uk> writes:

I might take only the easy questions. ;)

> Yet Another Noob Question.
> 
> What are the characteristics of each implementation?
> 
> How can I tell which I should be writing in what context...
> 
> (defun find-indicies (lst tst)
>    (let ((li 0))
> 	(labels ((qpred (a)
> 			   (incf li)
> 			   (if (funcall tst a)
> 				   (1- li)
> 				   nil)))
> 	  (remove nil (mapcar #'qpred lst)))))
> 
> (defun find-indices (lst tst)
>    (loop
>     for el in lst
>     counting t into index
>     if (funcall tst el)
>     collect index))
> 
> 
> CL-USER> (find-indices '(1 2 1 3) (lambda (x) (= 1 x)))
> (1 3)
> 
> Hmm. Personally I'd prefer the second form for readability, but are tricks
> like that closure in the first find-indices valid in some circumstances? From
> reading around, I get the impression that a lot of experienced Lisp coders
> would prefer the first. Is it just LOOP allergy, or is there something deeper?
> 
> I guess I'm asking - when do I map, when do I iterate   (and when do I
> recurse?) ? CL's mapping constructs seem powerful enough to do the job of a
> lot of iteration constructs in other languagesis it just a matter of taste,
> or are there contexts where one or the other is usually preferred for
> readability/portability/space/speed reasons?

Well, I generally prefer the solution that has the best readability, and
I'm presonally partial to LOOP.  It turns out that loop is a somewhat
controversial Common Lisp form, in that there are a fair number of Lisp
programmers who hate it for diverging from normal lisp syntax.  But I
like the readability and flexibility it gives.  It is particularly
useful if you want to to multiple stepping iterations (which just
happens to answer one of the questions you have below).

But other than that, it is mostly a matter of personal style
preference.  There are some cases where if you aren't careful, you can
manage to implement less efficient solutions.  For example, the remove
of the result of the mapcar has to traverse the list a second time.
Pascal Bourguignon gives a MAPCAN solution that avoids that.

Recursion is sometimes required, when you have naturally recursive
algorithms, such as tree-walks where the detailed structure isn't linear
or isn't known in advance.  Other than that, it depends on which seems
the most natural fit.

You'll often see references in this newsgroup to Lisp being a
multi-paradigm language.  The aim is to provide a useful collection of
tools and not to drive people into one particular method of solving a
problem.  With lots of tools, you typically have a number of ways to
solve a given problem, with different tradeoffs.  The art of the
programmer lies in chooseing from among them the most appropriate
solution for his particular task.

> And does LOOP have a more concise way of collecting the index of the element
> being iterated over? And is there a way of avoiding the 1- in the
> first form?

Yes to both.

The first one is just a clever trick that is only a minor change to your
program.  Change the initial value of "li" to be -1 instead of 0.  Then
when you increment it, it will have the value you want.

There's also a more obscure solution involving the PROG1 form, but I
prefer the initial value selection trick.  You can actually get a lot of
mileage out of problem transformation tricks like that. (*)

Anyway, the PROG1 solution involves changing QPRED as follows:
  (qpred (a)
    (prog1 (if (funcall tst a)
               li
               nil)
	   (incf li)))

PROG1 returns the value of the FIRST form it executes, instead of
PROGN's return of the value of the LAST form.  The forms are still
executed in order.  For a simple exercise in macro writing, you could
try writing your own implementation of PROG1.

As for the second loop form, the answer is to use more than one
iteration clause in the loop macro:

  (loop for el in lst
        as index upfrom 0
        if (funcall tst el)
        collect index)

Pascal also has this solution, using keywords for LOOP symbols, but in
spite of the technical points, I find it a bit ugly.  You do run the
risk of inadvertent package collisions, though, if you end up exporting
any symbols that are also LOOP keywords.  The COLLECT and SUM symbols
are potentially the most troubling.

> And why did people create CLOS when a lisp function is perfectly capable of
> encapsulating data and methods, and being what an "object" would be in
> other OO langages?

Well, partly to provide a standard OO methodology.  And also to provide
a model of OO processing that is more extensible and fundamentally
different from the C++/Java OO model.

Multiple dispatch for choosing methods is one major difference, as is
the association of methods with generic functions rather than classes.
This provides more flexibility for the user and also a lot more
extensibility, since you can freely add new methods to existing classes,
even if you don't have the source code for those classes.  This comes in
quite handy when you want to do things with particular objects that the
designers had not envisioned.

-- 
Thomas A. Russ,  USC/Information Sciences Institute