Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

flatten that does not drop nil

77 views
Skip to first unread message

Antony

unread,
Sep 21, 2011, 9:39:57 AM9/21/11
to
Hi

I needed a flatten that keeps the nils
All the ones I found seem to drop or ignore nils
So, I slightly modified one that I found (on c.l.l)

Here it is
(defun flatten (tree)
(labels ((flatten-with-nil (tree)
(typecase tree
(null (list nil))
(list (mapcan #'flatten-with-nil tree))
(atom (list tree)))))
(when tree
(flatten-with-nil tree))))

CL-USER> (flatten '(1 2 (5 3 6) nil 9))
(1 2 5 3 6 NIL 9)
CL-USER> (flatten nil)
NIL

This was mostly a cut-past-change exercise, so any feedback would be useful.

-Antony

Chris Riesbeck

unread,
Sep 21, 2011, 5:29:14 PM9/21/11
to
Although I'm betting you don't really need or want a flatten at all, I
don't see why you need a typecase, or why you need the first branch
given the third. So

(defun flatten (tree)
(labels ((flatten-with-nil (tree)
(if (atom tree) (list tree)
(mapcan #'flatten-with-nil tree))))
(when tree
(flatten-with-nil tree))))

Antony

unread,
Sep 22, 2011, 2:31:31 AM9/22/11
to
On 9/21/2011 2:29 PM, Chris Riesbeck wrote:
> On 9/21/2011 8:39 AM, Antony wrote:
>> I needed a flatten that keeps the nils
>> All the ones I found seem to drop or ignore nils
>> So, I slightly modified one that I found (on c.l.l)
>>...
>> Here it is
>> (defun flatten (tree)
>> (labels ((flatten-with-nil (tree)
>> (typecase tree
>> (null (list nil))
>> (list (mapcan #'flatten-with-nil tree))
>> (atom (list tree)))))
>> (when tree
>> (flatten-with-nil tree))))
>>
>> CL-USER> (flatten '(1 2 (5 3 6) nil 9))
>> (1 2 5 3 6 NIL 9)
>> CL-USER> (flatten nil)
>> NIL
>>...
>
> Although I'm betting you don't really need or want a flatten at all, I
> don't see why you need a typecase, or why you need the first branch
> given the third. So
>
> (defun flatten (tree)
> (labels ((flatten-with-nil (tree)
> (if (atom tree) (list tree)
> (mapcan #'flatten-with-nil tree))))
> (when tree
> (flatten-with-nil tree))))

Thanks for the feedback.
Changed to
(defun flatten (tree &optional keep-nil)
(labels ((flatten-with-nil (tree)
(typecase tree
(null (when keep-nil
(list nil)))
(list (mapcan #'flatten-with-nil tree))
(atom (list tree)))))
(when tree
(flatten-with-nil tree))))

This should be pluggable in place of what people are already using
-Antony

Antony

unread,
Sep 22, 2011, 2:33:38 AM9/22/11
to
On 9/21/2011 2:29 PM, Chris Riesbeck wrote:
> On 9/21/2011 8:39 AM, Antony wrote:
>> I needed a flatten that keeps the nils
>> All the ones I found seem to drop or ignore nils
>> So, I slightly modified one that I found (on c.l.l)
>>...
>> Here it is
>> (defun flatten (tree)
>> (labels ((flatten-with-nil (tree)
>> (typecase tree
>> (null (list nil))
>> (list (mapcan #'flatten-with-nil tree))
>> (atom (list tree)))))
>> (when tree
>> (flatten-with-nil tree))))
>>
>> CL-USER> (flatten '(1 2 (5 3 6) nil 9))
>> (1 2 5 3 6 NIL 9)
>> CL-USER> (flatten nil)
>> NIL
>>...
>
> Although I'm betting you don't really need or want a flatten at all, I
> don't see why you need a typecase, or why you need the first branch
> given the third. So
>
> (defun flatten (tree)
> (labels ((flatten-with-nil (tree)
> (if (atom tree) (list tree)
> (mapcan #'flatten-with-nil tree))))
> (when tree
> (flatten-with-nil tree))))

Thanks for the feedback.
Changed to
(defun flatten (tree &optional keep-nil)
(labels ((flatten-with-nil (tree)
(typecase tree
(null (when keep-nil
(list nil)))
(list (mapcan #'flatten-with-nil tree))
(atom (list tree)))))
(when tree
(flatten-with-nil tree))))

Tim Bradshaw

unread,
Sep 22, 2011, 5:22:45 AM9/22/11
to
On 2011-09-22 07:33:38 +0100, Antony said:

> This should be pluggable in place of what people are already using

What I want to know is: has anyone, ever, used a flatten function in
anger? I always assume they are only set as exercises (I've set them
as such).

Zach Beane

unread,
Sep 22, 2011, 6:19:08 AM9/22/11
to
Tim Bradshaw <t...@tfeb.org> writes:

I used one once when I wanted to construct a list to pass as arguments
to a shell command, and I wanted to do something like this:

(list "--foo" 42
(when bar
"--bar" 91)
"--output" "baz.txt")

Of course, in this case, I wanted the semantics of NIL "disappearing".

Zach

Antony

unread,
Sep 22, 2011, 6:40:24 AM9/22/11
to
My use case is for building cons pairs for http parameters to drakma
I have stuff like
(list
"foo" (do-somehting-to-get-value)
(when (some-condition)
(list x y))
...)
where foo and x are http query parameters.
Then do a flatten and then construct the pairs.

So I needed to keep the nils.
Mostly likely in-efficient, but works.

I guess using backquote and ,@ might be another way, even though this is
runtime need.


-Antony

Pascal J. Bourguignon

unread,
Sep 22, 2011, 6:56:04 AM9/22/11
to
Right, but you could instead write:

(append '("--foo" 42)
(when bar
'("--bar" 91))
'("--output" "baz.txt"))

or even:

`("--foo" 42 ,@(when bar '("--bar" 91)) "--output" "baz.txt")


--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.

Zach Beane

unread,
Sep 22, 2011, 8:09:09 AM9/22/11
to
"Pascal J. Bourguignon" <p...@informatimago.com> writes:

> Zach Beane <xa...@xach.com> writes:
>
>> Tim Bradshaw <t...@tfeb.org> writes:
>>
>>> On 2011-09-22 07:33:38 +0100, Antony said:
>>>
>>>> This should be pluggable in place of what people are already using
>>>
>>> What I want to know is: has anyone, ever, used a flatten function in
>>> anger? I always assume they are only set as exercises (I've set them
>>> as such).
>>
>> I used one once when I wanted to construct a list to pass as arguments
>> to a shell command, and I wanted to do something like this:
>>
>> (list "--foo" 42
>> (when bar
>> "--bar" 91)
>> "--output" "baz.txt")
>>
>> Of course, in this case, I wanted the semantics of NIL "disappearing".
>
> Right, but you could instead write:
>
> (append '("--foo" 42)
> (when bar
> '("--bar" 91))
> '("--output" "baz.txt"))
>
> or even:
>
> `("--foo" 42 ,@(when bar '("--bar" 91)) "--output" "baz.txt")

I consider both of those uglier.

Zach

Tim Bradshaw

unread,
Sep 22, 2011, 10:33:03 AM9/22/11
to
On 2011-09-22 13:09:09 +0100, Zach Beane said:

> I consider both of those uglier.

Me to, that's a good use for flatten.

Peter Keller

unread,
Oct 12, 2011, 12:17:11 PM10/12/11
to

If I recall, the book Let Over Lambda uses them to collect specific
symbol names out of bodies of code during macro expansion. I believe
this is to implement the defmacro/g! form specified in the book. I
don't have a copy handy at the moment though to cross reference.

-pete

WJ

unread,
Mar 6, 2012, 4:36:38 AM3/6/12
to
NewLisp:

> (flat '(2 nil (3 (4))))
(2 nil 3 4)
0 new messages