groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Milles, Eric (TR Technology & Ops)" <>
Subject Re: DGM for first or default
Date Fri, 19 Oct 2018 15:54:07 GMT
These may seem a bit simple for DGMs, but they do solve a couple problems as compared to "list
? list.first() ?: defaultValue".  First, no repetition of the "list" expression, which may
be complex.  Second, content assist will show proposals for these methods.  Third, the Groovy
truth problems with "list?[0] ?: defaultValue", "list?.getAt(0) ?: defaultValue", "list.find()
?: defaultValue" and others do not exist for these.  If the first element is null or otherwise
falsy, it will be returned as desired.  The only case for me that is unresolved is a null
array or iterable.  In this case, Groovy throws "Cannot invoke method firstOrElse() on null
obect" instead of running the method allowing null tolerance and return of default value.

    public static <T> T firstOrElse(Iterable<T> self, T defaultValue) {
        Iterator<T> iter = self.iterator();
        if (iter.hasNext()) {
        return defaultValue;
    public static <T> T firstOrElse(T[] self, T defaultValue) {
        if (self.length > 0) {
            return self[0];
        return defaultValue;
    // and similarly for the Closure (or java.util.function.Supplier if Java 8+ only) variants

Since safe navigation is being explored for by-index access, is there a possibility for including
some for of "or supplied default" in any of the safe-navigation cases?  I personally find
the new safe-indexing syntax to be unnecessary when "list?.getAt(i)" appears to be the equivalent
to "list?[i]".

Alternate proposal, what if the DGM.getAt(self, int idx) had variants that included a default
value return instead of hard-coded null?  Like this:

    public static <T> T getAt(List<T> self, int idx, T def) {
        int size = self.size();
        int i = normaliseIndex(idx, size);
        if (i < size) {
            return self.get(i);
        } else {
            //return null;
            return def;

From: Mario Garcia <>
Sent: Thursday, October 18, 2018 6:19 PM
Subject: Re: DGM for first or default

Good point OC:

[0,'',[],[:]].find()?:'not quite what you wanted here'
[0,1,2].find()?:'nor in this case'

The more I think on this the more I think is an interesting topic. I fully understand your
frustration with first(), but apart from the example with Cocoa you mentioned, looking in
the JVM it turns out there're plenty of examples of language collections behaving that way:

In scala the head of an empty list does throw an exception
scala> var empty = List[Int]()
empty: List[Int] = List()

scala> empty.head
java.util.NoSuchElementException: head of empty list
  at scala.collection.immutable.Nil$.head(List.scala:426)
  at scala.collection.immutable.Nil$.head(List.scala:423)
  ... 28 elided


and so does kotlin when calling to first()
Welcome to Kotlin version 1.2.71 (JRE 1.8.0_171-b11)
Type :help for help, :quit for quit
>>> val num: List<Int> = listOf()
>>> num.first()
java.util.NoSuchElementException: List is empty.
at kotlin.collections.CollectionsKt___CollectionsKt.first(_Collections.kt:184)
in Kotlin they have firstOrNull(), but I haven't found any overloaded function with a default
value. They also have "find", but it's not possible to call it without parameter

However Clojure returns null whether:

  *   The first element was nil
  *   The list was empty
  *   Or the list was nil

user=> (def a nil)
user=> a
user=> (first a)
user=> (def a '(nil))
user=> a
user=> (first a)
user=> (def a '())
user=> a
user=> (first a)

BTW I forgot to mention that Groovy 3 will have safe indexing meaning an expression like the

  *   will return the first element of a non empty list which I guess it will be the Kotlin
firstOrNull() equivalent
  *   or null if the list was null or empty

// trying to get first element from null list
nullList?[0] ==> null

// trying to get an inexistent element from a non empty list (but this is not new, this is
how a non empty list indexing works in Groovy)
nonNullList?[9999] => null

Outside the JVM, Haskell, when asking for the head of an empty list, throws an exception (There
is an explanation in stackoverflow which I'm afraid I don't understand). So in the end Groovy's
first() seems not to be the exception among other modern languages out there.

Another point of view, could be thinking about returning null consistently. Lets say a list
returns null using first():

  *   Does it mean the first element is a null value or is an empty list and that's why is
giving me a null value ?
  *   What if null is a valid value, with some meaning in my process ? With that context a
method like firstOrNull() (even first(defaultValue) with a null list) could be considered

My guess is that in the case of languages throwing an exception using first() on an empty
list, when they designed the language collections they didn't have any other way to express
that kind of semantics. But this is just a lucky guess. I'm probably wrong. I only can think
of pattern matching as a complete solution, where the terminal result in the case of an empty
or null list, is a default value different than any of the elements of the expected result
set ?

I apologize in advance for the lengthy e-mail, but it seemed interesting to think why first()
was designed like that, not only in Groovy, but in some other languages as well.

El jue., 18 oct. 2018 a las 20:27, Milles, Eric (TR Technology & Ops) (<<>>)

I think first() exists so there is a semantic pair for functional programming: first()/head()
and tail()  or init() and last()

From: ocs@ocs <<>>
Sent: Thursday, October 18, 2018 1:20 PM
Subject: Re: DGM for first or default

Well I thought first is smart enough to return null for an empty list, same as my firstObject
in Cocoa does. If it throws, what's on earth point of having the thing at all? In that case
it can be replaced by list[0] without any drawback at all.

All the best,

On 18 Oct 2018, at 7:19 PM, Milles, Eric (TR Technology & Ops) <<>>

"list?.first() ?: defaultValue" is not the equivalent.  If the collection is empty, first()
throws an IndexOutOfBoundsException is thrown.  That's why I'm asking if there is a simple
equivalent.  I suppose this is the equivalent now that I think about it:

list ? list.first() : defaultValue

From: ocs@ocs <<>>
Sent: Thursday, October 18, 2018 12:07 PM
Subject: Re: DGM for first or default

Myself, I am not a huge fan of adding not-often-needed functionalities (and actually would
add almost none of those discussed lately); nevertheless...

On 18 Oct 2018, at 6:48 PM, Paolo Di Tommaso <<>>

-1, it can be easily done as:
list.first() ?: defaultValue

... this won't work in case the first object is a Groovy False (e.g., an empty string, or
a plethora of others).

All the best,


On Thu, Oct 18, 2018 at 6:45 PM Daniel.Sun <<>>
+0 from me.
P.S. we should add similar DGM for `last` too?


Daniel Sun
Apache Groovy committer
Twitter: @daniel_sun

Sent from:<>

View raw message