tags:

views:

130

answers:

2

Still working on lisp recipes and idioms.

I have a list like this:

((a b c) (d e f) nil (g h))

I'd like to consolidate that to one list,

(a b c d e f g h)

Seems like there oughta be a one-liner for that.

+2  A: 
(apply #'append '((a b c) (d e f) (g h i)))

or

(loop for outer in '((a b c) (d e f) (g h i))
      nconcing (loop for inner in outer collecting inner))
Dirk
Perfect! - just what I needed.
Cheeso
`nconc` (and `mapcan`) can be bad for your health.
Eli Barzilay
@eli: Certainly. But in the loop above it's fine, or is it? The inner loop returns fresh lists, so `nconc`ing is ok.
Dirk
Dirk: Yes, I should have read this more carefully, and then put my comment next to Rainer's answer instead...
Eli Barzilay
@Eli why nconc is bad?
Yongwei Xing
@Yongwei Xing: Because it destructively modifies its arguments. This is usually a bad idea, unless you know exactly that nobody else has access to the very same data structure. Here it should be fine, as the inner loop produces fresh lists, to which nobody but the outer loop can have reference to.
Dirk
+1  A: 

That's a typical homework question. Generally this operation is called FLATTEN (which flattens lists on all levels).

(mapcan #'copy-list '((a b c) (d e f) nil (g h)))

The APPLY variant has the problem that it may run into the CALL-ARGUMENTS-LIMIT when there are more sublists than CALL-ARGUMENTS-LIMIT.

See for example also http://rosettacode.org/wiki/Flatten_a_list#Common_Lisp

Rainer Joswig
Thanks for the helpful answer. It definitely was not homework for me. Maybe 20 years ago, I might have had that as a homework question, but I can't remember that far back, now!
Cheeso
@Cheeso: it was a hint that you can find solutions for it...
Rainer Joswig