From: K. Ari Krupnikov
Subject: What's more idiomatic?
Date: 
Message-ID: <86ll0o8xe9.fsf@deb.lib.aero>
Performance issues aside, which one of these expressions is more
idiomatic in Common Lisp?

(mapcar #'foo (mapcar #'bar list))

(mapcar #'(lambda (i) (foo (bar i))) list)

Ari.

-- 
Elections only count as free and trials as fair if you can lose money
betting on the outcome.

From: tichy
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <1129799424.116663.232050@o13g2000cwo.googlegroups.com>
> [...] which one of these expressions is more
> idiomatic in Common Lisp?

I don't know but...

(mapcar (o #'foo #'bar) list)

.
From: Björn Lindberg
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <9mpy84ofryk.fsf@muvclx01.cadence.com>
···@lib.aero (K. Ari Krupnikov) writes:

> Performance issues aside, which one of these expressions is more
> idiomatic in Common Lisp?
> 
> (mapcar #'foo (mapcar #'bar list))
> 
> (mapcar #'(lambda (i) (foo (bar i))) list)

  (mapcar (compose #'foo #'bar) list)

Now write compose. :-)


Bj�rn
From: Peter Scott
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <1129823081.300714.205520@g43g2000cwa.googlegroups.com>
You can use compose from cl-utilities. It works properly, and it's
often optimized.

http://www.cliki.net/COMPOSE
http://www.cliki.net/cl-utilities

-Peter
From: Pascal Costanza
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <3rqcpfFkso14U1@individual.net>
K. Ari Krupnikov wrote:
> Performance issues aside, which one of these expressions is more
> idiomatic in Common Lisp?
> 
> (mapcar #'foo (mapcar #'bar list))
> 
> (mapcar #'(lambda (i) (foo (bar i))) list)

Besides trying to figure out what's more idiomatic, it is also (more?) 
important to note that one of the two expressions traverse the list once 
while the other traverses it twice. Traversing a list more often than 
necessary leads to less efficient code, which may or may not matter.

Apart from that, I tend to prefer LOOP:

(loop for i in list
       collect (foo (bar i)))


Pascal

-- 
OOPSLA'05 tutorial on generic functions & the CLOS Metaobject Protocol
++++ see http://p-cos.net/oopsla05-tutorial.html for more details ++++
From: K. Ari Krupnikov
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <86vezr7h10.fsf@deb.lib.aero>
Pascal Costanza <··@p-cos.net> writes:

> K. Ari Krupnikov wrote:
> > Performance issues aside, which one of these expressions is more
> > idiomatic in Common Lisp?
> > (mapcar #'foo (mapcar #'bar list))
> > (mapcar #'(lambda (i) (foo (bar i))) list)
> 
> Besides trying to figure out what's more idiomatic, it is also (more?)
> important to note that one of the two expressions traverse the list
> once while the other traverses it twice.

Worse than traversing a list twice instead of once, it conses up two
lists instead of one /and/ traverses two lists. I understand that.

> Traversing a list more often than necessary leads to less efficient
> code, which may or may not matter.

It may not be possible to completely detach (perceived) efficiency and
idiomatic usage, but I specifically tried to in my post.

> Apart from that, I tend to prefer LOOP:
> 
> (loop for i in list
>        collect (foo (bar i)))

Interesting. I tend to not use loop for lists, but I guess there's no
valid reason for that. Would you also use loop in preference to mapcar
if there was only one function to apply, as in (mapcar #'foo list)?

Ari.

-- 
Elections only count as free and trials as fair if you can lose money
betting on the outcome.
From: Pascal Costanza
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <3rr6meFl6kqmU1@individual.net>
K. Ari Krupnikov wrote:
> Pascal Costanza <··@p-cos.net> writes:
> 
>>Apart from that, I tend to prefer LOOP:
>>
>>(loop for i in list
>>       collect (foo (bar i)))
> 
> Interesting. I tend to not use loop for lists, but I guess there's no
> valid reason for that. Would you also use loop in preference to mapcar
> if there was only one function to apply, as in (mapcar #'foo list)?

I decide this on a case-by-case basis. Although I would probably go for 
the mapcar when it's really just one function.

When I have to create a lambda expression in order to express what I 
want I tend to go for the equivalent loop expression, essentially for 
the same reason why I use let instead of lambda. Consider:

(let ((x 42)
       (y 88))
   (* 2 (+ x y)))

vs.

((lambda (x y)
    (* 2 (+ x y)))
  42 88)

is, IMHO, similar to:

(loop for x in '(1 2 3)
       for y in '(4 5 6)
       collect (* 2 (+ x y)))

vs.

(mapcar (lambda (x y)
           (* 2 (+ x y)))
         '(1 2 3)
         '(4 5 6))

I think both the let and the loop versions are easier to read, and I try 
to focus on better readability of my code, instead of adhering to some 
arbitrary aesthetical consideration. (Basically, I don't understand what 
"more lispy", "more functional", "more object-oriented", "more 
whatever", buys me.)

I don't think there is a good generalizable rule to readability, but 
depends a lot on the context, for example the surrounding code, whether 
it's generated or manually written code, what the nature of the problem 
is that I try to solve, etc. That's similar to written natural language.


Pascal

-- 
OOPSLA'05 tutorial on generic functions & the CLOS Metaobject Protocol
++++ see http://p-cos.net/oopsla05-tutorial.html for more details ++++
From: Thomas F. Burdick
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <xcvr7afcrgm.fsf@conquest.OCF.Berkeley.EDU>
Pascal Costanza <··@p-cos.net> writes:

> (loop for x in '(1 2 3)
>        for y in '(4 5 6)
>        collect (* 2 (+ x y)))
> 
> vs.
> 
> (mapcar (lambda (x y)
>            (* 2 (+ x y)))
>          '(1 2 3)
>          '(4 5 6))

Oh, that one's easy:

  (mapcar (compose (curry #'* 2) #'+)
          '(1 2 3) '(4 5 6))

Not that I generally write code that way....

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Pascal Costanza
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <3rvl47FlsdjsU1@individual.net>
Thomas F. Burdick wrote:
> Pascal Costanza <··@p-cos.net> writes:
> 
> 
>>(loop for x in '(1 2 3)
>>       for y in '(4 5 6)
>>       collect (* 2 (+ x y)))
>>
>>vs.
>>
>>(mapcar (lambda (x y)
>>           (* 2 (+ x y)))
>>         '(1 2 3)
>>         '(4 5 6))
> 
> Oh, that one's easy:
> 
>   (mapcar (compose (curry #'* 2) #'+)
>           '(1 2 3) '(4 5 6))

Apparently, my message didn't get through, so I'll try again.

The good thing about LET vs. LAMBDA is that in LET, you see the flow of 
control. In (let ((x 42)) (print x)), first X is bound to some value, 
and then something is done with X. In ((lambda (x) (print x)) 42), X is 
also bound to some value and then exactly the same is done with X, but 
the first step is distributed across the (source!) code: The binding is 
established in the lambda expression, but the value can only be found at 
the end of the whole expression.

Same in LOOP vs. MAPCAR: In (loop for x in list collect (+ x x)), X is 
bound to a number of values in sequence, and something is done with 
those values in sequence. Some with (mapcar (lambda (x) (+ x x)) list), 
but again the first step distributed across the (source!) code: Again, 
the bindings are established in the lambda expression, but the values 
can only be found at the end of the whole expression.

To illustrate the steps:

(1) ((lambda (x)
(3)    (print x))
(2)  42)

(1) (let ((x
(2)           42))
(3)   (print x))

vs.

(1) (mapcar (lambda (x)
(3)           (+ x x))
(2)         list)

(1) (loop for x
(2)             in list
(3)       collect (+ x x))


To extend this further: This is probably why some people find recursion 
harder to understand than iteration. Consider:

(labels ((collect (list result)
            (if list
                (collect
                  (cdr list)
                  (cons (+ (car list)
                           (car list))
                        result))
                result)))
   (collect '(1 2 3) '()))

Scheme's named let is neater in that regard:

(let collect ((lst '(1 2 3)) (result '()))
                 (if (not (null? lst))
                    (collect
                      (cdr lst)
                      (cons (+ (car lst)
                               (car lst))
                            result))
                    result))

...because again the values that the variables are bound to are 
textually near the corresponding bindings.


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <871x2db5px.fsf@qrnik.zagroda>
Pascal Costanza <··@p-cos.net> writes:

> To illustrate the steps:
>
> (1) ((lambda (x)
> (3)    (print x))
> (2)  42)
>
> (1) (let ((x
> (2)           42))
> (3)   (print x))

I would say that the temporal order is 42, bind x, print x, so neither
variant agrees with it. 'case' in various languages do.

> Scheme's named let is neater in that regard:
>
> (let collect ((lst '(1 2 3)) (result '()))
>                  (if (not (null? lst))
>                     (collect
>                       (cdr lst)
>                       (cons (+ (car lst)
>                                (car lst))
>                             result))
>                     result))

And my Kogut's loop is "named case" (with multiple matched values):

loop [1 2 3] [] [
   []     result {result}
   (x\xs) result {again xs (x+x \ result)}
];

The name is "again" by default, can be different if written
explicitly. Perhaps a better name would be "next".

-- 
   __("<         Marcin Kowalczyk
   \__/       ······@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
From: Peter Seibel
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <m2ach1e3h6.fsf@beagle.local>
···@lib.aero (K. Ari Krupnikov) writes:

> Pascal Costanza <··@p-cos.net> writes:

>> Apart from that, I tend to prefer LOOP:
>> 
>> (loop for i in list
>>        collect (foo (bar i)))
>
> Interesting. I tend to not use loop for lists, but I guess there's no
> valid reason for that. Would you also use loop in preference to mapcar
> if there was only one function to apply, as in (mapcar #'foo list)?

When there's a simple function to be applied (such as #'foo) MAPCAR is
more concise. But it's interesting (to me anyway) to note that the
following to expressions (where you need to map a function with a
reference to some local variable) are exactly the same length in
characters.

  (mapcar #'(lambda (x) (foo x i)) list)
  (loop for x in list collect (foo x i))

Obviously, if you are the kind of person who eschews the #' before
(lambda ...) then the MAPCAR verion is two characters shorter. But I
always use #' as a matter of style so they're the same for me.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Alan Crowe
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <868xwidhzw.fsf@cawtech.freeserve.co.uk>
Peter Seibel <·····@gigamonkeys.com> writes:
> When there's a simple function to be applied (such as #'foo) MAPCAR is
> more concise. But it's interesting (to me anyway) to note that the
> following to expressions (where you need to map a function with a
> reference to some local variable) are exactly the same length in
> characters.
> 
>   (mapcar #'(lambda (x) (foo x i)) list)
>   (loop for x in list collect (foo x i))

I've taken to using a little macro

(defmacro defcurry (name arglist1 arglist2 &body code)
  `(defun ,name ,arglist1
    (lambda ,arglist2 ,@code)))

so that I can write little function builders easily

(defcurry increase-by(x)(y)
  (+ x y))

(mapcar (increase-by 10) '(1 2 3)) => (11 12 13)

Notice that 

    (mapcar (increase-by (f x)) list) 

is equivalent to

    (loop with temp = (f x)
          for item in list
          collect (+ item temp))

or

    (let ((temp (f x)))
      (mapcar (lambda(y)(+ y temp)) list))

If you actually want

    (loop for item in list
          collect (+ item (f x)))

or

    (mapcar (lambda(y)(+ (f x) y)) list)

in order to get fresh results from f for each item on the
list, then defcurry is not for you.

I think this buys me me something because both loop and 
mapcar-lambda require a variable name, to name the variable
that ferries the list items to the form that takes them as data.
Using defcurry gets that little piece of clutter out of the
mapcar form.

But the price is quite high. That variable name is not
eliminated but moved elsewhere, into the defcurry, and the
defcurry is a pretty fat form for the small tidying up of
the mapcar that it provides.

On the other hand, the defcurry also does your temporary
variable for you very smoothly.

Am I winning or losing with defcurry?

Alan Crowe
Edinburgh
Scotland
From: Lars Brinkhoff
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <85sluq6lbx.fsf@junk.nocrew.org>
Alan Crowe <····@cawtech.freeserve.co.uk> writes:
> I think this buys me me something because both loop and 
> mapcar-lambda require a variable name, to name the variable
> that ferries the list items to the form that takes them as data.
> Using defcurry gets that little piece of clutter out of the
> mapcar form.

In this case (and in some others, but not all), I think a simple

  (mapcar (curry #'+ 10) list)

would suffice.

> Am I winning or losing with defcurry?

It could be a win if you find yourself doing a lot of (curry foo) for
a particular value of foo.

On the other hand, something which bothers me slightly is that
defining a lot of higher-order function (such as your increase-by) can
introduce a set of operators that parallel the existing ones.  For
example, this:

  (lambda (x) (+ (f x) (* (g x) (- (h x)))))

could in the parallel universe be expressed as

  (sum #'f (product #'g (negation #'h)))

Of course, to get some sense of connection with the standard
operators, you could write something like

  (applicator #'+ #'f (applicator #'* #'g (compose #'- #'h)))

Where applicator is some kind of cousin to compose:

  (defun applicator (f &rest fns)
    (lambda (x)
      (let ((xs (list x)))
        (setf (rest xs) xs)
        (apply f (mapcar #'funcall fns xs)))))
From: Espen Vestre
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <kw7jc71f3b.fsf@merced.netfonds.no>
Pascal Costanza <··@p-cos.net> writes:

> Apart from that, I tend to prefer LOOP:
>
> (loop for i in list
>       collect (foo (bar i)))

Hmm, interesting. Easy to read, actually, though I tend to use mapcar for
anything that is actually a simple one-to-one mapping of a list, but 
resort to use/loop every time I have to e.g. iterate on a second variable
(e.g. a counter).

(btw. I'd never use I for the elements of a list, I should be reserved for
 integers ;))
-- 
  (espen)
From: Alain Picard
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <87irvstt7w.fsf@memetrics.com>
···@lib.aero (K. Ari Krupnikov) writes:

> Performance issues aside, which one of these expressions is more
> idiomatic in Common Lisp?
>
> (mapcar #'foo (mapcar #'bar list))
>
> (mapcar #'(lambda (i) (foo (bar i))) list)

I'd prefer (mapcar (compose #'foo #'bar) list)
From: K. Ari Krupnikov
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <867jc8dn2p.fsf@deb.lib.aero>
Alain Picard <············@memetrics.com> writes:

> ···@lib.aero (K. Ari Krupnikov) writes:
> 
> > Performance issues aside, which one of these expressions is more
> > idiomatic in Common Lisp?
> >
> > (mapcar #'foo (mapcar #'bar list))
> >
> > (mapcar #'(lambda (i) (foo (bar i))) list)
> 
> I'd prefer (mapcar (compose #'foo #'bar) list)

Any particular reason you think a user-defined function is more
idiomatic than standard machinery?

Ari.

-- 
Elections only count as free and trials as fair if you can lose money
betting on the outcome.
From: ··············@hotmail.com
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <1129841062.558758.230760@g43g2000cwa.googlegroups.com>
K. Ari Krupnikov wrote:
> Alain Picard <············@memetrics.com> writes:
>
> > ···@lib.aero (K. Ari Krupnikov) writes:
> >
> > > Performance issues aside, which one of these expressions is more
> > > idiomatic in Common Lisp?
> > >
> > > (mapcar #'foo (mapcar #'bar list))
> > >
> > > (mapcar #'(lambda (i) (foo (bar i))) list)
> >
> > I'd prefer (mapcar (compose #'foo #'bar) list)
>
> Any particular reason you think a user-defined function is more
> idiomatic than standard machinery?

>From my point of view, "idiomatic" boils down to "what an experienced
Lisper would do, and recognize immediately in others' code."

In this case, #'compose

1) is more readable than the #'(lambda (i) (foo (bar i)))
2) is more concise than the lambda form
3) is a common functional programming idiom
4) almost everyone has written #'compose, and they use almost
invariably the same name and behavior

3,4 mean it is idiomatic
1,2 make it superior to the (also idiomatic) lambda form
From: K. Ari Krupnikov
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <86r7af7gva.fsf@deb.lib.aero>
···············@hotmail.com" <············@gmail.com> writes:

> >From my point of view, "idiomatic" boils down to "what an experienced
> Lisper would do, and recognize immediately in others' code."

Yes, that is how I understand the word, too.

> In this case, #'compose
> 
> 1) is more readable than the #'(lambda (i) (foo (bar i)))
> 2) is more concise than the lambda form
> 3) is a common functional programming idiom
> 4) almost everyone has written #'compose, and they use almost
> invariably the same name and behavior
> 
> 3,4 mean it is idiomatic
> 1,2 make it superior to the (also idiomatic) lambda form

I hear you.

Ari.

-- 
Elections only count as free and trials as fair if you can lose money
betting on the outcome.
From: Björn Lindberg
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <9mp3bmvf1s7.fsf@muvclx01.cadence.com>
···@lib.aero (K. Ari Krupnikov) writes:

> Alain Picard <············@memetrics.com> writes:
> 
> > ···@lib.aero (K. Ari Krupnikov) writes:
> > 
> > > Performance issues aside, which one of these expressions is more
> > > idiomatic in Common Lisp?
> > >
> > > (mapcar #'foo (mapcar #'bar list))
> > >
> > > (mapcar #'(lambda (i) (foo (bar i))) list)
> > 
> > I'd prefer (mapcar (compose #'foo #'bar) list)
> 
> Any particular reason you think a user-defined function is more
> idiomatic than standard machinery?

The standard machinery could very well have contained compose. As it
happens it doesn't, but I would expect most Lispers to have a version
of it in their personal toolbox. If you regularly use the mapping
functions, remove-*, etc. you will want to have COMPOSE, CURRY and
friends available.


Bj�rn
From: Alain Picard
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <873bmv828o.fsf@memetrics.com>
···@lib.aero (K. Ari Krupnikov) writes:

> Alain Picard <············@memetrics.com> writes:
>> 
>> I'd prefer (mapcar (compose #'foo #'bar) list)
>
> Any particular reason you think a user-defined function is more
> idiomatic than standard machinery?

Well... yes.  If Lisp is "the programmable programming language",
it doesn't make much sense to use it without programming it.

I think staying away from abstractions not predefined for you
in the spec, on the basis that they make things hard to understand,
is fallacious.  This is a perfect example:  a reader who has not
heard of COMPOSE (but, say, who is reasonably mathematically sophisticated)
will jump to to source (always only 1 M-. away), study it, and achieve
enlightenment.  After that, the expression (compose #'foo #'bar) is
internalized, and starts to look natural.

Isn't that what programming is all about: writing things in a way
that most clearly expresses programmer intent?  Surely you don't 
think the Hyperspec is complete, and no new functions are left to
be invented?

                                        --ap
From: K. Ari Krupnikov
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <86vezqd1en.fsf@deb.lib.aero>
Alain Picard <············@memetrics.com> writes:

> ···@lib.aero (K. Ari Krupnikov) writes:
> 
> > Alain Picard <············@memetrics.com> writes:
> >> 
> >> I'd prefer (mapcar (compose #'foo #'bar) list)
> >
> > Any particular reason you think a user-defined function is more
> > idiomatic than standard machinery?
> 
> Well... yes.  If Lisp is "the programmable programming language",
> it doesn't make much sense to use it without programming it.
> 
> I think staying away from abstractions not predefined for you
> in the spec, on the basis that they make things hard to understand,
> is fallacious.

I think this is the logic that Scheme programmers espouse. Follow it
far enough, and you'll jettison the standard library altogether. I'm
not saying it's bad, btw.

Ari.

-- 
Elections only count as free and trials as fair if you can lose money
betting on the outcome.
From: Alain Picard
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <87y84m7882.fsf@memetrics.com>
···@lib.aero (K. Ari Krupnikov) writes:

> I think this is the logic that Scheme programmers espouse. Follow it
> far enough, and you'll jettison the standard library altogether. I'm
> not saying it's bad, btw.

Well, I haven't met many Scheme programmers, so I can't speak to
that.  But I think all good programmers, in all languages, follow
this direction, whether consciously or not, since they will be
solving problems for which a natural vocabulary does not exist
in their language of choice.  So I don't think this is Lisp specific.

CL has a large library, yes, so we don't have to reinvent it all
the time, like the Scheme folks, but that doesn't mean it contains
all useful abstractions which can be conceived of...

Think of the Screamer package, for an example of a "layered library"
with many powerful abstractions.

                              --ap
From: tichy
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <1129988675.175825.64800@o13g2000cwo.googlegroups.com>
(travl (a '(1 2 3) b '(4 5 6)) (* 2 (+ a b)))

==> (10 14 18)

;; I just wrote it -- not tested.

(defmacro travl
((&rest vl) &body body
&aux (v (loop for i in vl by #'cddr collect i))
(l (loop for i in (cdr vl) by #'cddr collect i))
(vlist (map-into (make-list (length l)) #'gensym))
(set-chunk (mapcan (lambda (v l) `(,v (car ,l))) v vlist))
(trav-chunk (mapcan (lambda (g) `(,g (cdr ,g))) vlist)))
(when (cdr body) (setq body (list (cons 'progn body))))
(let ((tag (gensym)) (result (gensym)) (p (gensym)))
`(let (,@(mapcar #'list vlist l) ,result ,@v)
(setq ,@set-chunk ,@trav-chunk ,result (cons ,@body nil))
(when (and ,@vlist)
(let ((,p ,result))
(tagbody ,tag
(setq ,@set-chunk ,@trav-chunk
,p (cdr (rplacd ,p (cons ,@body nil))))
(when (and ,@vlist) (go ,tag)))))
,result)))

:-)
From: Joe Marshall
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <8xwlie38.fsf@alum.mit.edu>
"tichy" <·····@o2.pl> writes:

> (travl (a '(1 2 3) b '(4 5 6)) (* 2 (+ a b)))
>
> ==> (10 14 18)
>
> ;; I just wrote it -- not tested.

I'm guessing that your news system has stripped the leading blanks.

 (defmacro travl ((&rest vl) &body body
                  &aux (v (loop for i in vl by #'cddr collect i))
                  (l (loop for i in (cdr vl) by #'cddr collect i))
                  (vlist (map-into (make-list (length l)) #'gensym))
                  (set-chunk (mapcan (lambda (v l) `(,v (car ,l))) v vlist))
                  (trav-chunk (mapcan (lambda (g) `(,g (cdr ,g))) vlist)))
   (when (cdr body) (setq body (list (cons 'progn body))))
   (let ((tag (gensym)) (result (gensym)) (p (gensym)))
     `(let (,@(mapcar #'list vlist l) ,result ,@v)
        (setq ,@set-chunk ,@trav-chunk ,result (cons ,@body nil))
        (when (and ,@vlist)
          (let ((,p ,result))
            (tagbody ,tag
                     (setq ,@set-chunk ,@trav-chunk
                           ,p (cdr (rplacd ,p (cons ,@body nil))))
                     (when (and ,@vlist) (go ,tag)))))
        ,result)))

-----

I wonder what Python aficionados do about this.
From: tichy
Subject: Re: What's more idiomatic?
Date: 
Message-ID: <1130237294.899393.257960@z14g2000cwz.googlegroups.com>
Joe Marshall writes:

> I'm guessing that your news system has stripped the leading blanks.

Sorry about that.

> I wonder what Python aficionados do about this.

Hm, I agree that travl's code looks obscure (MAPCAN,
TAGBODY, RPLACD) so pythonists (I guess that they
like 'clean' code) may reject it. I wrote that macro without
thinking... here is shorter, and 'cleaner' version:

(defmacro travl ((&rest vl) &body body &aux symlist (result (gensym)))
  `(let (,result)
     (do* ,(loop for (v l) on vl by #'cddr
                 for g = (car (push (gensym) symlist))
                 nconc `((,g ,l (cdr ,g)) (,v (car ,g) (car ,g))))
         ((not (and ,@symlist)))
       (push (progn ,@body) ,result))
     (nreverse ,result)))

:-)