'last' on empty collections

126 views
Skip to first unread message

Warren Lynn

unread,
Jul 1, 2012, 3:47:58 PM7/1/12
to Clojure
Right now

(last []) => nil
(last [nil]) => nil

So there is no way to differentiate these two (except with some
emptiness checking). In my opinion (last []) should throw an
exception, because that's when last does not apply. From another point
of view, there are two cases:

1. The local semantics requires the collection not to be empty.
Throwing an exception here will remove the burden of manual checking.

2. The local semantics allows the collection to be empty, in that case
the caller needs to do
(when-not (empty? c) (last c)).

case 1 is the "normal case" with higher probability, so the burden of
checking should be on the second case.

Your opinion?

Note this is rather academic because it probably is too late do
anything about it at this stage. But it may help future cases.

Jay Fields

unread,
Jul 1, 2012, 4:20:07 PM7/1/12
to clo...@googlegroups.com
It works as I expect, and I would be disappointed if it did throw.

Sent from my iPhone
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

Dennis Haupt

unread,
Jul 1, 2012, 4:21:02 PM7/1/12
to clo...@googlegroups.com
i'd do (actually, i did) it like this:
(my-special-last coll) -> returns the last element or throws an
exception if there is none
(my-special-last coll if-empty) -> in case of an empty collections,
ifEmpty is returned
--



Softaddicts

unread,
Jul 1, 2012, 4:35:48 PM7/1/12
to clo...@googlegroups.com
Clojure avoid as much as possible making nil or emptiness a special case
requiring the caller to test it before calling a function.

I would like this to remain like that after years of testing null in Java before
doing anything else on a object to prevent exceptions.

This is a design decision taken years ago. If you really need to test emptiness,
empty? exists exactly for this purpose.

Luc
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
>
--
Softaddicts<lprefo...@softaddicts.ca> sent by ibisMail from my ipad!

Tyler Perkins

unread,
Jul 1, 2012, 4:41:19 PM7/1/12
to Clojure
No, I think it's worthwhile to think about a more fundamental
semantic. What does nil mean? Although it's often misused, nil is
provided so that a function can simply respond, "I can't answer your
question". That's the perfect response from (last c) when c is empty,
whether c normally contains nil elements or not.

Now, if you insist on using the same tool when c is not empty but
contains nil elements, well, that's your problem! It's a higher-level
problem, one that may require rethinking your data representation. Or
you could use empty? as you showed. But let's not claim this is an
exceptional condition when the current semantic of nil is already a
perfect fit.

Sean Corfield

unread,
Jul 1, 2012, 6:12:05 PM7/1/12
to clo...@googlegroups.com
On Sun, Jul 1, 2012 at 12:47 PM, Warren Lynn <wrn....@gmail.com> wrote:
> Right now
>
> (last []) => nil
> (last [nil]) => nil
>
> So there is no way to differentiate these two (except with some
> emptiness checking). In my opinion (last []) should throw an
> exception, because that's when last does not apply.

That would be horribly inconsistent with the rest of Clojure, IMO:

user> (first [])
nil
user> (first [nil])
nil
user> (second [])
nil
user> (second [nil])
nil
user> (second [nil nil])
nil
user> (next [])
nil
user> ({:a 1 :b 2} :c)
nil
user> (map inc nil)
()
user> (map inc [])
nil
user> (seq nil)
nil
user> (seq [])
nil
;; etc etc etc

Warren, this and some of your other issues with how Clojure works
makes me curious about your language background. May I ask what
languages you're most used to? That may help us frame future
discussions about differences in opinion about features in Clojure.
--
Sean A Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/
World Singles, LLC. -- http://worldsingles.com/

"Perfection is the enemy of the good."
-- Gustave Flaubert, French realist novelist (1821-1880)

László Török

unread,
Jul 1, 2012, 6:16:12 PM7/1/12
to clo...@googlegroups.com

Returning nil is consistent across seq functions and play well with when, if-let, when-let, just to name a few...

Michał Marczyk

unread,
Jul 1, 2012, 7:18:20 PM7/1/12
to clo...@googlegroups.com
On 2 July 2012 00:12, Sean Corfield <seanco...@gmail.com> wrote:
> user> (map inc nil)
> ()
> user> (map inc [])
> nil

Actually that's also (). Agreed on the point of the message.

Cheers,
M.

Sean Corfield

unread,
Jul 1, 2012, 7:20:13 PM7/1/12
to clo...@googlegroups.com
Sorry, copy'n'paste error :) Glad the point was obvious...

Warren Lynn

unread,
Jul 1, 2012, 7:45:08 PM7/1/12
to clo...@googlegroups.com

On Sunday, July 1, 2012 4:21:02 PM UTC-4, Dennis Haupt wrote:
i'd do (actually, i did) it like this:
(my-special-last coll) -> returns the last element or throws an
exception if there is none
(my-special-last coll if-empty) -> in case of an empty collections,
ifEmpty is returned



I like this one.

Warren Lynn

unread,
Jul 1, 2012, 7:58:58 PM7/1/12
to clo...@googlegroups.com
That would be horribly inconsistent with the rest of Clojure, IMO:

Sure it will be. That is why I said this is an academic one, and I don't expect any change to current one.



Warren, this and some of your other issues with how Clojure works
makes me curious about your language background. May I ask what
languages you're most used to? That may help us frame future
discussions about differences in opinion about features in Clojure.

Gee, seems like an interview question. :-) Sure, if it helps us understand each other better, why not (am I so different from others?)

My daily language at work is C++/C.
My language for non mission critical tasks (testing, utilities and etc) is Python.
My hobby language is Elisp (and also a necessity for my Emacs configs)
I played with Common Lisp for a while and gave it up (too much historical baggage, and also terrible eco-system)
I read books on Ruby but never used it.
10 years ago I was designing Java interfaces (via JCP process) for an industry consortium, but since then I have never used it.

I am very interested in Clojure and am thinking about using it in a kind-of mission critical project (except my mission is not well defined yet).

So that is it.

Vinzent

unread,
Jul 2, 2012, 5:28:22 AM7/2/12
to clo...@googlegroups.com
This decision definitely is a part of clojure design; as far as I can tell, clojure tends to not throw an exception unless the input is terribly wrong (e.g. can't be converted to a seq in your case). Of course, it has some drawbacks, but is pretty convenient for the programmer and doesn't cause any problems in practice.

Sean Corfield

unread,
Jul 2, 2012, 1:45:31 PM7/2/12
to clo...@googlegroups.com
On Sun, Jul 1, 2012 at 4:58 PM, Warren Lynn <wrn....@gmail.com> wrote:
> Sure it will be. That is why I said this is an academic one, and I don't
> expect any change to current one.

:)

> I am very interested in Clojure and am thinking about using it in a kind-of
> mission critical project (except my mission is not well defined yet).

Cool. We both have background in C++ and Java (for me C++ was the
90's, Java the following decade), and I did a fair bit of FP in the
80's so, as you suspected, not that different. Thank you for humoring
me.
Reply all
Reply to author
Forward
0 new messages