From: Sacha
Subject: sequence iteration
Date: 
Message-ID: <3jCSf.321341$cQ4.10305578@phobos.telenet-ops.be>
Yet another "newbie needs help" post !

I tried to find a way to iterate over a sequence (trying to stay generic 
here)
It seems the only way would be to use the map function. Is this correct ?

If that is the case how would i go about interrupting iteration ?

Sacha 

From: Eric Lavigne
Subject: Re: sequence iteration
Date: 
Message-ID: <1142617977.443107.228350@v46g2000cwv.googlegroups.com>
> Yet another "newbie needs help" post !
>
> I tried to find a way to iterate over a sequence (trying to stay generic
> here)
> It seems the only way would be to use the map function. Is this correct ?
>
> If that is the case how would i go about interrupting iteration ?
>
> Sacha

Maybe you could use "do" and "elt". This will tend to be inefficient
when dealing with long lists, but it should be generic as you wish. In
that case, one of the clauses in "do" is meant for indicating when
iteration will stop.

You could also look into "loop" instead of "do".
From: Sacha
Subject: Re: sequence iteration
Date: 
Message-ID: <i_CSf.321408$g04.10222702@phobos.telenet-ops.be>
"Eric Lavigne" <············@gmail.com> wrote in message 
·····························@v46g2000cwv.googlegroups.com...
>
>> Yet another "newbie needs help" post !
>>
>> I tried to find a way to iterate over a sequence (trying to stay generic
>> here)
>> It seems the only way would be to use the map function. Is this correct ?
>>
>> If that is the case how would i go about interrupting iteration ?
>>
>> Sacha
>
> Maybe you could use "do" and "elt". This will tend to be inefficient
> when dealing with long lists, but it should be generic as you wish. In
> that case, one of the clauses in "do" is meant for indicating when
> iteration will stop.
>
> You could also look into "loop" instead of "do".
>

I am to use this in a tight loop, i'd rather look into the efficient ways.
On a side note, i didn't see a way to use loop for that purpose.
May i ask how you'd do that ?

thanks for your answers,
Sacha 
From: Eric Lavigne
Subject: Re: sequence iteration
Date: 
Message-ID: <1142621726.491765.80910@u72g2000cwu.googlegroups.com>
> I am to use this in a tight loop, i'd rather look into the efficient ways.
> On a side note, i didn't see a way to use loop for that purpose.
> May i ask how you'd do that ?
>

   (loop
     for element in sequence
     collect (do-something-to element)
     until (> element 5))

This performs some action on each element (do-something-to) and
collects the results in a list (the return value of loop). If it runs
into an element that is greater than 5, it will terminate early and
return whatever it collected so far.
From: Sacha
Subject: Re: sequence iteration
Date: 
Message-ID: <WQDSf.321502$fT4.10336421@phobos.telenet-ops.be>
"Eric Lavigne" <············@gmail.com> wrote in message 
····························@u72g2000cwu.googlegroups.com...
>
>> I am to use this in a tight loop, i'd rather look into the efficient 
>> ways.
>> On a side note, i didn't see a way to use loop for that purpose.
>> May i ask how you'd do that ?
>>
>
>   (loop
>     for element in sequence
>     collect (do-something-to element)
>     until (> element 5))
>
> This performs some action on each element (do-something-to) and
> collects the results in a list (the return value of loop). If it runs
> into an element that is greater than 5, it will terminate early and
> return whatever it collected so far.


Oh but this won't work with all types of sequences :

(loop for char in "coucou" do (print char))

Error: "coucou" is not of type LIST.
  1 (abort) Return to level 0.
  2 Return to top loop level 0.

Type :b for backtrace, :c <option number> to proceed,  or :? for other 
options

Sacha 
From: Wade Humeniuk
Subject: Re: sequence iteration
Date: 
Message-ID: <2EISf.265$%S3.101@clgrps12>
Sacha wrote:
> "Eric Lavigne" <············@gmail.com> wrote in message 
> ····························@u72g2000cwu.googlegroups.com...
>>> I am to use this in a tight loop, i'd rather look into the efficient 
>>> ways.
>>> On a side note, i didn't see a way to use loop for that purpose.
>>> May i ask how you'd do that ?
>>>
>>   (loop
>>     for element in sequence
>>     collect (do-something-to element)
>>     until (> element 5))
>>
>> This performs some action on each element (do-something-to) and
>> collects the results in a list (the return value of loop). If it runs
>> into an element that is greater than 5, it will terminate early and
>> return whatever it collected so far.
> 
> 
> Oh but this won't work with all types of sequences :
> 
> (loop for char in "coucou" do (print char))
> 

CL-USER 5 > (loop for char across "coucou" do (print char))

#\c
#\o
#\u
#\c
#\o
#\u
NIL

CL-USER 6 >
From: Sacha
Subject: Re: sequence iteration
Date: 
Message-ID: <aoJSf.322038$kp1.10356786@phobos.telenet-ops.be>
>>>   (loop
>>>     for element in sequence
>>>     collect (do-something-to element)
>>>     until (> element 5))
>>>
>>
>> Oh but this won't work with all types of sequences :
>>
>> (loop for char in "coucou" do (print char))
>>
>
> CL-USER 5 > (loop for char across "coucou" do (print char))
>
> #\c
> #\o
> #\u
> #\c
> #\o
> #\u
> NIL
>
> CL-USER 6 >

haha well sure, but now i'm stuck with vectors !
Remember the goal was to make it generic.

I wonder why they didn't allow the loop macro to genericaly iterate over a 
sequence.
Can't be much more of a syntactic mess than it is right now anyways =P

Sacha 
From: Sacha
Subject: Re: sequence iteration
Date: 
Message-ID: <ZrJSf.322044$0e4.10257555@phobos.telenet-ops.be>
> I wonder why they didn't allow the loop macro to genericaly iterate over a
> sequence.
> Can't be much more of a syntactic mess than it is right now anyways =P
>


Well actually i think i know why.
Might be because the macro doesn't know what's the actual
type of the sequence. This is only known at best after compilation,
at worst at runtime.

Sacha 
From: Pascal Bourguignon
Subject: Re: sequence iteration
Date: 
Message-ID: <87ek10bjuy.fsf@thalassa.informatimago.com>
"Sacha" <··@address.spam> writes:
> I wonder why they didn't allow the loop macro to genericaly iterate over a 
> sequence.

Because there's no efficient generic iteration operator.

You can use ELT, but it's O(N) on lists, for each access, therefore
O(N�) for the loop.


> Can't be much more of a syntactic mess than it is right now anyways =P

This is not a syntax problem.  You get the sequence at run time, so
you have to choose between CDR or AREF at run time.

You can do your own GLOOP (or checkout ITERATE or some similar package)
which would map:

   (gloop for item inside sequence do (stuff item))

to:

  (if (listp sequence)
     (loop for item in seqeunce do (stuff item))
     (loop for item on seqeunce do (stuff item)))





Or you can write:

  (loop with iterator = (iterator container)
        for item = (iterator-next iterator)
        while item
        do (stuff item))


(defun iterator-next (iterator) (funcall iterator))
    
(defmethod iterator ((self null))
  (lambda () (values nil t)))

(defmethod iterator ((self cons))
  (lambda () (let ((done (not self))) (values (pop self) done))))

(defmethod iterator ((self vector))
  (let ((i 0))
    (lambda () 
        (if (< i (length self))
           (multiple-values-prog1 (values (aref self i) nil) (incf i))
           (values nil t)))))

;; and you can add a method of any kind of container...

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

"By filing this bug report you have challenged the honor of my
family. Prepare to die!"
From: Sacha
Subject: Re: sequence iteration
Date: 
Message-ID: <0LKSf.322153$1F4.10282046@phobos.telenet-ops.be>
> You can do your own GLOOP (or checkout ITERATE or some similar package)
> which would map:
>
>   (gloop for item inside sequence do (stuff item))
>
> to:
>
>  (if (listp sequence)
>     (loop for item in seqeunce do (stuff item))
>     (loop for item on seqeunce do (stuff item)))
>
>
> Or you can write:
>
>  (loop with iterator = (iterator container)
>        for item = (iterator-next iterator)
>        while item
>        do (stuff item))
>
>
> (defun iterator-next (iterator) (funcall iterator))
>
> (defmethod iterator ((self null))
>  (lambda () (values nil t)))
>
> (defmethod iterator ((self cons))
>  (lambda () (let ((done (not self))) (values (pop self) done))))
>
> (defmethod iterator ((self vector))
>  (let ((i 0))
>    (lambda ()
>        (if (< i (length self))
>           (multiple-values-prog1 (values (aref self i) nil) (incf i))
>           (values nil t)))))
>

Very nice indeed.

It strikes me that an hypothetical statically typed lisp would allow for
a macro specialization.

Like this :
;;we know the type of sequence (through some kind of a pre-compilation step)
(defmacro my-loop (var sequence &body body)
  (if (listp sequence)
     `(loop for ,var in ,sequence ....)
     `(loop for ,var on ,sequence ...)))

or

(defmacromethod my-loop (var (sequence list) &body body)
 ....)
(defmacromethod my-loop (var (sequence vector) &body body)
 ...)

That would be good stuff...
Though this would be at the cost of dynamic typing.
Can't have the best of both worlds i guess.

Sacha
From: Pascal Bourguignon
Subject: Re: sequence iteration
Date: 
Message-ID: <87acbobeov.fsf@thalassa.informatimago.com>
"Sacha" <··@address.spam> writes:
> It strikes me that an hypothetical statically typed lisp would allow for
> a macro specialization.
>
> Like this :
> ;;we know the type of sequence (through some kind of a pre-compilation step)
> (defmacro my-loop (var sequence &body body)
>   (if (listp sequence)
>      `(loop for ,var in ,sequence ....)
>      `(loop for ,var on ,sequence ...)))
>
> or
>
> (defmacromethod my-loop (var (sequence list) &body body)
>  ....)
> (defmacromethod my-loop (var (sequence vector) &body body)
>  ...)
>
> That would be good stuff...
> Though this would be at the cost of dynamic typing.
> Can't have the best of both worlds i guess.

Well, macros are expanded before compilation, before the compiler has
an opportunity to do any type inference.

But this would be theorically possible in a compiler macro.
(see: DEFINE-COMPILER-MACRO).

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

"What is this talk of "release"?  Klingons do not make software
"releases".  Our software "escapes" leaving a bloody trail of
designers and quality assurance people in its wake."
From: jayessay
Subject: Re: sequence iteration
Date: 
Message-ID: <m33bhf38sz.fsf@rigel.goldenthreadtech.com>
"Sacha" <··@address.spam> writes:


> It strikes me that an hypothetical statically typed lisp would allow for
> a macro specialization.

You "just" need type inference.  As part of a system I've built, fully
generic iteration/comprehension utilizes type inference to _typically_
generate the specific code; falling back to runtime dispatch for those
cases which can't be determined.

/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: Sacha
Subject: Re: sequence iteration
Date: 
Message-ID: <XgYSf.323457$cF4.10293400@phobos.telenet-ops.be>
"jayessay" <······@foo.com> wrote in message 
···················@rigel.goldenthreadtech.com...
> "Sacha" <··@address.spam> writes:
>
>
>> It strikes me that an hypothetical statically typed lisp would allow for
>> a macro specialization.
>
> You "just" need type inference.  As part of a system I've built, fully
> generic iteration/comprehension utilizes type inference to _typically_
> generate the specific code; falling back to runtime dispatch for those
> cases which can't be determined.
>
> /Jon

Well i won't ask how you do this, as it would probably fly
a couple miles over my head  =P

Sacha 
From: Frode Vatvedt Fjeld
Subject: Re: sequence iteration
Date: 
Message-ID: <2hd5gkyjo4.fsf@vserver.cs.uit.no>
"Eric Lavigne" <············@gmail.com> writes:

>    (loop
>      for element in sequence
>      collect (do-something-to element)
>      until (> element 5))
> 
> This performs some action on each element

But only if sequence is a list..

-- 
Frode Vatvedt Fjeld
From: Pascal Costanza
Subject: Re: sequence iteration
Date: 
Message-ID: <480bjmFh8djlU1@individual.net>
Sacha wrote:
> Yet another "newbie needs help" post !
> 
> I tried to find a way to iterate over a sequence (trying to stay generic 
> here)
> It seems the only way would be to use the map function. Is this correct ?

Yes.

> If that is the case how would i go about interrupting iteration ?

(defun f (sequence)
   (map 'list (lambda (x)
                (when (> x 5)
                  (return-from f 'foo)))
        sequence))

Something like that?


Pascal

-- 
3rd European Lisp Workshop
July 3-4 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: Sacha
Subject: Re: sequence iteration
Date: 
Message-ID: <q2DSf.321415$rr4.10261536@phobos.telenet-ops.be>
"Pascal Costanza" <··@p-cos.net> wrote in message 
···················@individual.net...
>> I tried to find a way to iterate over a sequence (trying to stay generic 
>> here)
>> It seems the only way would be to use the map function. Is this correct ?
>
> Yes.

Oh, this is slightly disapointing.

>> If that is the case how would i go about interrupting iteration ?
>
> (defun f (sequence)
>   (map 'list (lambda (x)
>                (when (> x 5)
>                  (return-from f 'foo)))
>        sequence))
>
> Something like that?


That would work, though in my specific case, i don't want to exit the 
function alltogether.
I guess it's time to dive in named blocks or maybe throw and catch stuff.

I wonder what's the cost of such things ...

Anyways, thanks for your always helpfull advice Pascal.
Sacha 
From: Frode Vatvedt Fjeld
Subject: Re: sequence iteration
Date: 
Message-ID: <2hlkv8yl2i.fsf@vserver.cs.uit.no>
"Pascal Costanza" <··@p-cos.net> wrote in message 

> > (defun f (sequence)
> >   (map 'list (lambda (x)
> >                (when (> x 5)
> >                  (return-from f 'foo)))
> >        sequence))

"Sacha" <··@address.spam> writes:

> That would work, though in my specific case, i don't want to exit
> the function alltogether.  I guess it's time to dive in named blocks
> or maybe throw and catch stuff.

Block/return is the lexically-scoped variant of catch/throw, and here
it seems that the lexical variant is appropriate. You can also use
tagbody/go (i.e. lisp's version of goto).


I suggest however that you reconsider the requirement of being
"generic". In my experience, it's quite rare that you really need to
accept both lists and vectors: their access characteristics (in terms
of run-time complexity) are so very different that they tend to be
used for separate things. In the rare exceptions, an etypecase and
duplicated code often works well enough.

-- 
Frode Vatvedt Fjeld
From: Sacha
Subject: Re: sequence iteration
Date: 
Message-ID: <huDSf.321462$PS4.10307627@phobos.telenet-ops.be>
> Block/return is the lexically-scoped variant of catch/throw, and here
> it seems that the lexical variant is appropriate. You can also use
> tagbody/go (i.e. lisp's version of goto).

thanks

> I suggest however that you reconsider the requirement of being
> "generic". In my experience, it's quite rare that you really need to
> accept both lists and vectors: their access characteristics (in terms
> of run-time complexity) are so very different that they tend to be
> used for separate things. In the rare exceptions, an etypecase and
> duplicated code often works well enough.

I think i'll just do that, and update the code so that it only accepts 
vectors.
I don't really need to stay generic, that was more for the sake of it =P

Sacha 
From: Thomas F. Burdick
Subject: Re: sequence iteration
Date: 
Message-ID: <xcv64mckpmr.fsf@conquest.OCF.Berkeley.EDU>
"Sacha" <··@address.spam> writes:

> "Pascal Costanza" <··@p-cos.net> wrote in message 
> ···················@individual.net...
> >> I tried to find a way to iterate over a sequence (trying to stay generic 
> >> here)
> >> It seems the only way would be to use the map function. Is this correct ?
> >
> > Yes.
> 
> Oh, this is slightly disapointing.

Don't be too disapointed, DOSEQUENCE is only 4 lines of code:
http://groups.google.com/group/comp.lang.lisp/msg/4e21bb46df444036

It works (almost) just like DOLIST.  So you can write, e.g.:

  (defun foo (sequence)
    (let ((found nil))
      (dosequence (x sequence)
        (when (> x 5)
          (setf found x)
          (return)))
      (when found (format t "I found ~d~%" found))
      found))

  (foo '(1 2 3 4)) => nil
  (foo #(1 2 30 40))
  =>
     I found 30
     30

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Sacha
Subject: Re: sequence iteration
Date: 
Message-ID: <RXWSf.323323$dF4.10294425@phobos.telenet-ops.be>
"Thomas F. Burdick" <···@conquest.OCF.Berkeley.EDU> wrote in message 
····················@conquest.OCF.Berkeley.EDU...
> "Sacha" <··@address.spam> writes:
>
>> "Pascal Costanza" <··@p-cos.net> wrote in message
>> ···················@individual.net...
>> >> I tried to find a way to iterate over a sequence (trying to stay 
>> >> generic
>> >> here)
>> >> It seems the only way would be to use the map function. Is this 
>> >> correct ?
>> >
>> > Yes.
>>
>> Oh, this is slightly disapointing.
>
> Don't be too disapointed, DOSEQUENCE is only 4 lines of code:
> http://groups.google.com/group/comp.lang.lisp/msg/4e21bb46df444036
>
> It works (almost) just like DOLIST.  So you can write, e.g.:
>
>  (defun foo (sequence)
>    (let ((found nil))
>      (dosequence (x sequence)
>        (when (> x 5)
>          (setf found x)
>          (return)))
>      (when found (format t "I found ~d~%" found))
>      found))
>
>  (foo '(1 2 3 4)) => nil
>  (foo #(1 2 30 40))
>  =>
>     I found 30
>     30


Thank you.
It's about time that i start building an utility library.

Sacha