From: bradb
Subject: Idiom for gathering pairs from a list?
Date: 
Message-ID: <1161614798.476063.284600@i3g2000cwc.googlegroups.com>
I'm using CL-PPCRE, and some functions return lists of start and end
matches, so a return might be
(0 2 4 7 10 15), three matches.
Right now I loop over the matches like
 (loop :for match :on (all-matches scanner text :start start) :by
#'cddr
          :do (let ((start (first match))
                      (end   (second match)))
  (subseq text start end))

Is there a nicer way to gather the pairs than that?

Cheers
Brad

From: Zach Beane
Subject: Re: Idiom for gathering pairs from a list?
Date: 
Message-ID: <m3ejszhyf2.fsf@unnamed.xach.com>
"bradb" <··············@gmail.com> writes:

> I'm using CL-PPCRE, and some functions return lists of start and end
> matches, so a return might be
> (0 2 4 7 10 15), three matches.
> Right now I loop over the matches like
>  (loop :for match :on (all-matches scanner text :start start) :by
> #'cddr
>           :do (let ((start (first match))
>                       (end   (second match)))
>   (subseq text start end))
> 
> Is there a nicer way to gather the pairs than that?

LOOP destructures. Try this:

   (loop for (start end) on (all-matches ...) by #'cddr do ...)

Zach

         
From: bradb
Subject: Re: Idiom for gathering pairs from a list?
Date: 
Message-ID: <1161616562.425639.64350@e3g2000cwe.googlegroups.com>
Zach Beane wrote:
> "bradb" <··············@gmail.com> writes:
>
> > I'm using CL-PPCRE, and some functions return lists of start and end
> > matches, so a return might be
> > (0 2 4 7 10 15), three matches.
> > Right now I loop over the matches like
> >  (loop :for match :on (all-matches scanner text :start start) :by
> > #'cddr
> >           :do (let ((start (first match))
> >                       (end   (second match)))
> >   (subseq text start end))
> >
> > Is there a nicer way to gather the pairs than that?
>
> LOOP destructures. Try this:
>
>    (loop for (start end) on (all-matches ...) by #'cddr do ...)
>
> Zach
Ah, that is much much nicer.  It is a shame that loop doesn't defualt
to looping by the natural size of the destructure, so you don't need
the BY #'CDDR.

Also, to really start a hot thread,
(loop :for (start end) :on (....) :do)  ; keywords
(loop for (start end) on (...) do)     ; no keywords
which is better and why?  :-)

Brad
From: Pascal Bourguignon
Subject: Re: Idiom for gathering pairs from a list?
Date: 
Message-ID: <87zmbnrra2.fsf@thalassa.informatimago.com>
"bradb" <··············@gmail.com> writes:

> Zach Beane wrote:
>> "bradb" <··············@gmail.com> writes:
>>
>> > I'm using CL-PPCRE, and some functions return lists of start and end
>> > matches, so a return might be
>> > (0 2 4 7 10 15), three matches.
>> > Right now I loop over the matches like
>> >  (loop :for match :on (all-matches scanner text :start start) :by
>> > #'cddr
>> >           :do (let ((start (first match))
>> >                       (end   (second match)))
>> >   (subseq text start end))
>> >
>> > Is there a nicer way to gather the pairs than that?
>>
>> LOOP destructures. Try this:
>>
>>    (loop for (start end) on (all-matches ...) by #'cddr do ...)
>>
>> Zach
> Ah, that is much much nicer.  It is a shame that loop doesn't defualt
> to looping by the natural size of the destructure, so you don't need
> the BY #'CDDR.

(defmacro loop* (&rest stuff)
   ...
   :for ,destructuring-stuff :on ,list by (lambda (list)
                                           (nth-cdr ,(length destructuring-stuff)

> Also, to really start a hot thread,
> (loop :for (start end) :on (....) :do)  ; keywords
> (loop for (start end) on (...) do)     ; no keywords
> which is better and why?  :-)
>
> Brad
>

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

In a World without Walls and Fences, 
who needs Windows and Gates?
From: Rob Warnock
Subject: Re: Idiom for gathering pairs from a list?
Date: 
Message-ID: <2-6dnZNJeMTMEaDYnZ2dnUVZ_qKdnZ2d@speakeasy.net>
Pascal Bourguignon  <···@informatimago.com> wrote:
+---------------
| "bradb" <··············@gmail.com> writes:
| > Zach Beane wrote:
| >> "bradb" <··············@gmail.com> writes:
| >> > Is there a nicer way to gather the pairs than that?
| >> LOOP destructures. Try this:
| >>    (loop for (start end) on (all-matches ...) by #'cddr do ...)
| > Ah, that is much much nicer.  It is a shame that loop doesn't defualt
| > to looping by the natural size of the destructure, so you don't need
| > the BY #'CDDR.
| 
| (defmacro loop* (&rest stuff)
|    ...
|    :for ,destructuring-stuff :on ,list by (lambda (list)
|                                            (nth-cdr ,(length
| destructuring-stuff)
+---------------

The problem with any such automatic sizing is LOOPs like this:

    (loop for (a b c . rest) on list by #'cdddr ...)

or even this:

    (flet ((stepper (list)
	     (case (car list)
	       ((:one)   (cddr list))
	       ((:two)   (cdddr list))
	       ((:three) (cdddr list))
	       (otherwise (cdr list)))))
      (loop for (key a b c) on list by #'stepper ...))

which can parse lists like this:

    (:one 123 :two 234 453 :three 7 5 8 :special :other 99 22 :two 34 54)


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pascal Bourguignon
Subject: Re: Idiom for gathering pairs from a list?
Date: 
Message-ID: <87u01vrr1j.fsf@thalassa.informatimago.com>
"bradb" <··············@gmail.com> writes:

> Zach Beane wrote:
>> "bradb" <··············@gmail.com> writes:
>>
>> > I'm using CL-PPCRE, and some functions return lists of start and end
>> > matches, so a return might be
>> > (0 2 4 7 10 15), three matches.
>> > Right now I loop over the matches like
>> >  (loop :for match :on (all-matches scanner text :start start) :by
>> > #'cddr
>> >           :do (let ((start (first match))
>> >                       (end   (second match)))
>> >   (subseq text start end))
>> >
>> > Is there a nicer way to gather the pairs than that?
>>
>> LOOP destructures. Try this:
>>
>>    (loop for (start end) on (all-matches ...) by #'cddr do ...)
>>
>> Zach
> Ah, that is much much nicer.  It is a shame that loop doesn't defualt
> to looping by the natural size of the destructure, so you don't need
> the BY #'CDDR.

It's but a defmacro away:

(defmacro loop* (&rest stuff)
   ...
  `(cl:loop
      ...
      :for ,destructuring-stuff :on ,list
           :by (lambda (list)  (nthcdr ,(length destructuring-stuff) list))
      ...))

> Also, to really start a hot thread,
> (loop :for (start end) :on (....) :do)  ; keywords
> (loop for (start end) on (...) do)     ; no keywords
> which is better and why?  :-)

Try this at your REPL to see which is better, and why.

   http://paste.lisp.org/display/28420


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

In a World without Walls and Fences, 
who needs Windows and Gates?
"bradb" <··············@gmail.com> writes:
From: Bill Atkins
Subject: Re: Idiom for gathering pairs from a list?
Date: 
Message-ID: <m24ptu9asx.fsf@bertrand.local>
Pascal Bourguignon <···@informatimago.com> writes:

> Try this at your REPL to see which is better, and why.
>
>    http://paste.lisp.org/display/28420

So just treat LOOP keywords as if they were in COMMON-LISP and expect
the same mayhem you would from exporting your own DEFUN.
From: Pascal Bourguignon
Subject: Re: Idiom for gathering pairs from a list?
Date: 
Message-ID: <87lkn6swc8.fsf@thalassa.informatimago.com>
Bill Atkins <······@rpi.edu> writes:

> Pascal Bourguignon <···@informatimago.com> writes:
>
>> Try this at your REPL to see which is better, and why.
>>
>>    http://paste.lisp.org/display/28420
>
> So just treat LOOP keywords as if they were in COMMON-LISP and expect
> the same mayhem you would from exporting your own DEFUN.

No it's not possible, since COMMON-LISP doesn't export WHILE.

And it's much simplier to use keywords (from the KEYWORD package) than
to use SHADOW at the right places and qualify UTILITY:WHILE.

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

"A TRUE Klingon warrior does not comment his code!"
From: Kalle Olavi Niemitalo
Subject: Re: Idiom for gathering pairs from a list?
Date: 
Message-ID: <878xj64ug7.fsf@Astalo.kon.iki.fi>
Pascal Bourguignon <···@informatimago.com> writes:

> "bradb" <··············@gmail.com> writes:
>> Also, to really start a hot thread,
>> (loop :for (start end) :on (....) :do)  ; keywords
>> (loop for (start end) on (...) do)     ; no keywords
>> which is better and why?  :-)
>
> Try this at your REPL to see which is better, and why.
>
>    http://paste.lisp.org/display/28420

That code defines a package EXAMPLE2, causes WHILE to be interned
to it by using it as a loop keyword, and then tries to use the
MYLOOP package which exports another WHILE: 

* (use-package "MYLOOP")

debugger invoked on a SB-INT:NAME-CONFLICT in thread #<THREAD "initial thread" {9003399}>:
  USE-PACKAGE #<PACKAGE "MYLOOP"> causes name-conflicts in
  #<PACKAGE "EXAMPLE2"> between the following symbols:
    MYLOOP:WHILE, WHILE
See also:
  The ANSI Standard, Section 11.1.1.2.5

Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [RESOLVE-CONFLICT] Resolve conflict.
  1: [ABORT           ] Exit debugger, returning to top level.

(SB-INT:NAME-CONFLICT #<PACKAGE "EXAMPLE2"> USE-PACKAGE #<PACKAGE "MYLOOP">)
0] 0

Select a symbol to be made accessible in package EXAMPLE2:
  1. MYLOOP:WHILE
  2. WHILE
  
Enter an integer (between 1 and 2): 1

T
* 

Resolving the conflict doesn't seem very difficult or cumbersome;
prepending colons to all loop keywords would require more typing.
And if this were in a program rather than in the REPL, then you'd
surely avoid USE-PACKAGE and instead put MYLOOP in the DEFPACKAGE
form you already had for EXAMPLE2.

There are other loop keywords for which you could construct
similar conflicts; for example SUM.  That one is also more likely
to occur as the name of a variable than WHILE is.  Which you
cannot solve by using keywords instead.
From: Pascal Bourguignon
Subject: Re: Idiom for gathering pairs from a list?
Date: 
Message-ID: <878xj6soal.fsf@thalassa.informatimago.com>
Kalle Olavi Niemitalo <···@iki.fi> writes:
> There are other loop keywords for which you could construct
> similar conflicts; for example SUM.  That one is also more likely
> to occur as the name of a variable than WHILE is.  Which you
> cannot solve by using keywords instead.

(loop :for i :from 1 :to 100 :sum i) ; perfectly solved, thank you.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay
From: Thomas A. Russ
Subject: Re: Idiom for gathering pairs from a list?
Date: 
Message-ID: <ymi64e9cuir.fsf@sevak.isi.edu>
Pascal Bourguignon <···@informatimago.com> writes:

> Kalle Olavi Niemitalo <···@iki.fi> writes:
> > There are other loop keywords for which you could construct
> > similar conflicts; for example SUM.  That one is also more likely
> > to occur as the name of a variable than WHILE is.  Which you
> > cannot solve by using keywords instead.
> 
> (loop :for i :from 1 :to 100 :sum i) ; perfectly solved, thank you.

But it still doesn't solve:

 (let ((sum (loop :for ...)))
   (print sum))

(use "SOME-PACKAGE-EXPORTING-SUM")


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Pascal Bourguignon
Subject: Re: Idiom for gathering pairs from a list?
Date: 
Message-ID: <877iypqn9q.fsf@thalassa.informatimago.com>
···@sevak.isi.edu (Thomas A. Russ) writes:

> Pascal Bourguignon <···@informatimago.com> writes:
>
>> Kalle Olavi Niemitalo <···@iki.fi> writes:
>> > There are other loop keywords for which you could construct
>> > similar conflicts; for example SUM.  That one is also more likely
>> > to occur as the name of a variable than WHILE is.  Which you
>> > cannot solve by using keywords instead.
>> 
>> (loop :for i :from 1 :to 100 :sum i) ; perfectly solved, thank you.
>
> But it still doesn't solve:
>
>  (let ((sum (loop :for ...)))
>    (print sum))
>
> (use "SOME-PACKAGE-EXPORTING-SUM")

The fundamental difference, is that you can rename sum either in your
let, or in the SOME-PACKAGE-EXPORTING-SUM, but you cannot rename the
LOOP keywords.

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

"You question the worthiness of my code? I should kill you where you
stand!"
From: Kalle Olavi Niemitalo
Subject: Re: Idiom for gathering pairs from a list?
Date: 
Message-ID: <8764e9a19t.fsf@Astalo.kon.iki.fi>
Pascal Bourguignon <···@informatimago.com> writes:

> Kalle Olavi Niemitalo <···@iki.fi> writes:
>> There are other loop keywords for which you could construct
>> similar conflicts; for example SUM.  That one is also more likely
>> to occur as the name of a variable than WHILE is.  Which you
>> cannot solve by using keywords instead.
>
> (loop :for i :from 1 :to 100 :sum i) ; perfectly solved, thank you.

That uses neither SUM nor :SUM as the name of a variable.
From: Wade Humeniuk
Subject: Re: Idiom for gathering pairs from a list?
Date: 
Message-ID: <8dd%g.32958$H7.20548@edtnps82>
bradb wrote:
> I'm using CL-PPCRE, and some functions return lists of start and end
> matches, so a return might be
> (0 2 4 7 10 15), three matches.
> Right now I loop over the matches like
>  (loop :for match :on (all-matches scanner text :start start) :by
> #'cddr
>           :do (let ((start (first match))
>                       (end   (second match)))
>   (subseq text start end))
> 
> Is there a nicer way to gather the pairs than that?
> 

As a side note, what is wrong with using cl-ppcre:do-matches or
cl-ppcre:do-matches-as-strings or cl-ppcre:all-matches-as-strings ?

(defun collect-subseqs (text list)
   (loop while list collect
         (subseq text (pop list) (pop list))))

CL-USER 3 > (collect-subseqs "test 123" '())
NIL

CL-USER 4 > (collect-subseqs "test 123" '(2))
("st 123")

CL-USER 5 > (collect-subseqs "test 123" '(2 7))
("st 12")

CL-USER 6 >

Wade