You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@groovy.apache.org by "Milles, Eric (TR Technology & Ops)" <er...@thomsonreuters.com> on 2018/10/18 15:39:55 UTC

DGM for first or default

I see there are the following DGMs for getting first element of a "collection":

  static <T> T first(T[] self)

  static <T> T first(List<T> self)

  static <T> T first(Iterable<T> self)


Is there a simple sequence for getting the first element or a default value if the "collection" is empty?  If not, may I propose the addition of the following DGMs:

  static <T> T first(T[] self, T defaultValue)

  static <T> T first(List<T> self, T defaultValue)

  static <T> T first(Iterable<T> self, T defaultValue)

  static <T> T first(T[] self, Closure<T> defaultSupplier)
  static <T> T first(List<T> self, Closure<T> defaultSupplier)

  static <T> T first(Iterable<T> self, Closure<T> defaultSupplier)



Eric M.

Re: DGM for first or default

Posted by Paolo Di Tommaso <pa...@gmail.com>.
ouch.. true! if so:

list ? list.first() : defaultValue


p








On Thu, Oct 18, 2018 at 7:07 PM ocs@ocs <oc...@ocs.cz> wrote:

> 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 <pa...@gmail.com>
> wrote:
>
> -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,
> OC
>
>
>
> p
>
> On Thu, Oct 18, 2018 at 6:45 PM Daniel.Sun <su...@apache.org> wrote:
>
>> +0 from me.
>> P.S. we should add similar DGM for `last` too?
>>
>> Cheers,
>> Daniel.Sun
>>
>>
>>
>>
>> -----
>> Daniel Sun
>> Apache Groovy committer
>> Blog: http://blog.sunlan.me
>> Twitter: @daniel_sun
>>
>> --
>> Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html
>>
>
>

Re: DGM for first or default

Posted by "ocs@ocs" <oc...@ocs.cz>.
[0,'',[],[:]].find()?:'not quite what you wanted here'
[0,1,2].find()?:'nor in this case'

Actually, far as my experience can say, there's precisely one reason to have first/last, and that is that they won't throw, but return a null on an empty list. If they do not, there's no point in having those at all, for indices can be used instead just as well.

All the best,
OC

> On 18 Oct 2018, at 7:52 PM, Mario Garcia <ma...@gmail.com> wrote:
> 
> Eric you can use `find`:
> 
> list.find() ?: defaultValue
> 
> The method find with no arguments takes the first element, and if the collection is empty or null it will return null and you won't get an IndexOutOfBounds
> 
> Regards
> Mario
> 
> El jue., 18 oct. 2018 a las 19:32, Milles, Eric (TR Technology & Ops) (<eric.milles@thomsonreuters.com <ma...@thomsonreuters.com>>) escribió:
> Is it still valuable to have DGMs -- whether named "first()" or "firstOrDefault()" or whatever?  Content assist does not propose "list ? list.first() : defaultValue".  I suppose I'd need to create a code template to get that proposal in the IDE.
> 
> Are there any other small idioms like this that anyone has added as a template to improve the editing experience?
> From: Milles, Eric (TR Technology & Ops)
> Sent: Thursday, October 18, 2018 12:19:42 PM
> To: dev@groovy.apache.org <ma...@groovy.apache.org>
> Subject: Re: DGM for first or default
>  
> "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 <ocs@ocs.cz <ma...@ocs.cz>>
> Sent: Thursday, October 18, 2018 12:07 PM
> To: dev@groovy.apache.org <ma...@groovy.apache.org>
> 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 <paolo.ditommaso@gmail.com <ma...@gmail.com>> wrote:
>> 
>> -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,
> OC
> 
>> 
>> 
>> p
>> 
>> On Thu, Oct 18, 2018 at 6:45 PM Daniel.Sun <sunlan@apache.org <ma...@apache.org>> wrote:
>> +0 from me.
>> P.S. we should add similar DGM for `last` too?
>> 
>> Cheers,
>> Daniel.Sun
>> 
>> 
>> 
>> 
>> -----
>> Daniel Sun 
>> Apache Groovy committer 
>> Blog: http://blog.sunlan.me <https://urldefense.proofpoint.com/v2/url?u=http-3A__blog.sunlan.me_&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=Kuqjwc4Pu38Y9C4Zooo3uBjDkGvyna3lloonS2m7GTE&e=> 
>> Twitter: @daniel_sun 
>> 
>> --
>> Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html <https://urldefense.proofpoint.com/v2/url?u=http-3A__groovy.329449.n5.nabble.com_Groovy-2DDev-2Df372993.html&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=J5vmRmzvL66tJOtxSbSidNjQHcCHKNV3t2A0OHPCgDY&e=>
> 


Re: DGM for first or default

Posted by Mario Garcia <ma...@gmail.com>.
Eric you can use `find`:

list.find() ?: defaultValue

The method find with no arguments takes the first element, and if the
collection is empty or null it will return null and you won't get an
IndexOutOfBounds

Regards
Mario

El jue., 18 oct. 2018 a las 19:32, Milles, Eric (TR Technology & Ops) (<
eric.milles@thomsonreuters.com>) escribió:

> Is it still valuable to have DGMs -- whether named "first()" or
> "firstOrDefault()" or whatever?  Content assist does not propose "list ?
> list.first() : defaultValue".  I suppose I'd need to create a code template
> to get that proposal in the IDE.
>
>
> Are there any other small idioms like this that anyone has added as a
> template to improve the editing experience?
> ------------------------------
> *From:* Milles, Eric (TR Technology & Ops)
> *Sent:* Thursday, October 18, 2018 12:19:42 PM
> *To:* dev@groovy.apache.org
> *Subject:* Re: DGM for first or default
>
>
> "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 <oc...@ocs.cz>
> *Sent:* Thursday, October 18, 2018 12:07 PM
> *To:* dev@groovy.apache.org
> *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 <pa...@gmail.com>
> wrote:
>
> -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,
> OC
>
>
>
> p
>
> On Thu, Oct 18, 2018 at 6:45 PM Daniel.Sun <su...@apache.org> wrote:
>
> +0 from me.
> P.S. we should add similar DGM for `last` too?
>
> Cheers,
> Daniel.Sun
>
>
>
>
> -----
> Daniel Sun
> Apache Groovy committer
> Blog: http://blog.sunlan.me
> <https://urldefense.proofpoint.com/v2/url?u=http-3A__blog.sunlan.me_&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=Kuqjwc4Pu38Y9C4Zooo3uBjDkGvyna3lloonS2m7GTE&e=>
> Twitter: @daniel_sun
>
> --
> Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html
> <https://urldefense.proofpoint.com/v2/url?u=http-3A__groovy.329449.n5.nabble.com_Groovy-2DDev-2Df372993.html&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=J5vmRmzvL66tJOtxSbSidNjQHcCHKNV3t2A0OHPCgDY&e=>
>
>
>

Re: DGM for first or default

Posted by "Milles, Eric (TR Technology & Ops)" <er...@thomsonreuters.com>.
Is it still valuable to have DGMs -- whether named "first()" or "firstOrDefault()" or whatever?  Content assist does not propose "list ? list.first() : defaultValue".  I suppose I'd need to create a code template to get that proposal in the IDE.


Are there any other small idioms like this that anyone has added as a template to improve the editing experience?

________________________________
From: Milles, Eric (TR Technology & Ops)
Sent: Thursday, October 18, 2018 12:19:42 PM
To: dev@groovy.apache.org
Subject: Re: DGM for first or default


"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 <oc...@ocs.cz>
Sent: Thursday, October 18, 2018 12:07 PM
To: dev@groovy.apache.org
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 <pa...@gmail.com>> wrote:

-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,
OC



p

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

Cheers,
Daniel.Sun




-----
Daniel Sun
Apache Groovy committer
Blog: http://blog.sunlan.me<https://urldefense.proofpoint.com/v2/url?u=http-3A__blog.sunlan.me_&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=Kuqjwc4Pu38Y9C4Zooo3uBjDkGvyna3lloonS2m7GTE&e=>
Twitter: @daniel_sun

--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html<https://urldefense.proofpoint.com/v2/url?u=http-3A__groovy.329449.n5.nabble.com_Groovy-2DDev-2Df372993.html&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=J5vmRmzvL66tJOtxSbSidNjQHcCHKNV3t2A0OHPCgDY&e=>


Re: DGM for first or default

Posted by "Milles, Eric (TR Tech, Content & Ops)" <er...@thomsonreuters.com>.
Thanks for the note on 2.5 and the v8 methods.


I considered withDefault, but yes the mutation was a deal breaker and it only works for List and Map.  If I use Optional, then the case of null as a member of the collection becomes an issue to deal with.  Adding a bevy of new DGMs is not ideal either.  This is a tough one; I might end up sticking with "iterable ? iterable.first() : defaultValue" for now.


I would like to submit for future consideration that it would be nice to be able to control getAt's choice to return null if the given index is out of range.  This to me is the more general solution.

________________________________
From: Paul King <pa...@asert.com.au>
Sent: Sunday, February 17, 2019 6:07 PM
To: Groovy_Developers
Subject: Re: DGM for first or default

Groovy 2.5 still has JDK 7 as minimum whereas Groovy 3.0 has 8 as minimum. You can still add DGM methods into org.codehaus.groovy.vmplugin.v8.PluginDefaultGroovyMethods and then they will only be available when running on a JDK8+ VM.

Wrt to the question of whether we should have firstOrElse, lastOrElse, getAtOrElse, etc., it is certainly a possibility to add such a whole myriad of duplicated methods but there might be better alternatives. Does the existing ListWtihDefault work for you? It does mutate which might not be what you are after but perhaps we could create an alternative variant of that.

Cheers, Paul.


On Mon, Feb 18, 2019 at 7:36 AM Milles, Eric (TR Tech, Content & Ops) <er...@thomsonreuters.com>> wrote:

When I first worked all this up my target was Groovy 2.4.  If that is raised to Groovy 2.5+ I just started to wonder if java.util.Optional could be leveraged for an improved solution.  I also remembered some feedback some time ago from MG where to no-arg call would be "getName()" so that it could be used in Groovy sources as "name".  Then if there were versions with more arguments, they would be "name(arg1, arg2, ...)".


So if I were to implement new DGMs in a vacuum, would something like this make sense?


public static <T> Optional<T> getFirst(Iterable<T> self)

public static <T> Optional<T> getFirst(List<T> self)

public static <T> Optional<T> getFirst(T[] self)
public static <T> Optional<T> getFirst(org.codehaus.groovy.runtime.NullObject self)

This could be used like "list.first.orElse(defaultValue)".  Now that I write that out, I can see the conflict with list spread shorthand.  Darn, I wish that didn't exist and you had to explicitly use "list*.prop".


General question: Are there limitations to using Java 8 stuff in Groovy core?  I'm not sure how Android support comes into play here.


________________________________
From: Milles, Eric (TR Tech, Content & Ops) <er...@thomsonreuters.com>>
Sent: Sunday, February 17, 2019 1:56 PM
To: dev@groovy.apache.org<ma...@groovy.apache.org>
Subject: Re: DGM for first or default


I'd like to restart this discussion.  I'm not sure if this should move to new JIRA ticket or Pull Request.  There are a few open questions I'd like to get some feedback on.  I have managed to solve the problem of getting from a null array/iterable.


My use case is getting the first item from an iterable or else a supplied default.  Alternate proposals like "list?.first() ?: defaultValue" or "list?.find() ?: defaultValue" do not properly handle all use cases.  It took quite a number of tries to figure it out.


"list ? list.first() : defaultValue" appears to be roughly equivalent.  However, having the additional DGMs would mean a one-time check for non-null, non-empty and elimination of repeated "list", which may be a more complicated expression.  And in rare cases, a type could extend Iterable and provide a non-standard implementation of asBoolean().



Proposed additions to DefaultGroovyMethods:


public static <T> T firstOrElse(Iterable<T> self, T defaultValue)

public static <T> T firstOrElse(List<T> self, T defaultValue) // allows use of isEmpty() and get(i) instead of creating an Iterator instance

public static <T> T firstOrElse(T[] self, T defaultValue)

public static <T> T firstOrElse(org.codehaus.groovy.runtime.NullObject self, T defaultValue) // exists solely for the (null).firstOrDefault(value) case


public static <T> T firstOrElse(Iterable<T> self, Supplier<T> defaultValue)

public static <T> T firstOrElse(List<T> self, Supplier<T> defaultValue)

public static <T> T firstOrElse(T[] self, Supplier<T> defaultValue)

public static <T> T firstOrElse(org.codehaus.groovy.runtime.NullObject self, Supplier<T> defaultValue)

Since this is targeted at Groovy 2.5+ I have selected java.util.function.Supplier instead of groovy.lang.Closure.  Although that could be changed if a new Groovy 2.4 minor release was planned.


Usage:
  Iterable<Object> iterable = null
  println iterable.firstOrElse('default') // prints 'default'

  iterable = []
  println iterable.firstOrElse('default') // prints 'default'

  iterable = [0]
  println iterable.firstOrElse('default') // prints 0

  iterable = [null]
  println iterable.firstOrElse('default') // prints null

  iterable = [false]
  println iterable.firstOrElse('default') // prints false

  iterable = null
  iterable.firstOrElse { -> throw new ExceptionOfMyChoosing() } // throws



Open items:


  1.  Should a set of methods "lastOrElse" also be created?  It would not take much effort to add them at the same time.
  2.  Should the "getAt" methods be similarly extended, like "public static <T> T getAt(List<T> self, int idx, T defaultValue)", etc.
  3.  If "getAt" is extended in this way, would it be useful to also consider extending the "[idx]" syntax form of "getAt" to include the default?
  4.  There was a question raised: if "iterable" contains Closures or Suppliers, how should that case be handled?  I'm curious how often this might come up.



________________________________
From: Milles, Eric (TR Technology & Ops) <er...@thomsonreuters.com>>
Sent: Friday, October 19, 2018 10:54 AM
To: dev@groovy.apache.org<ma...@groovy.apache.org>
Subject: Re: DGM for first or default


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 iter.next();
        }
        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 <ma...@gmail.com>>
Sent: Thursday, October 18, 2018 6:19 PM
To: dev@groovy.apache.org<ma...@groovy.apache.org>
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

scala>
---------------------

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=> a
nil
user=> (first a)
nil
user=> (def a '(nil))
#'user/a
user=> a
(nil)
user=> (first a)
nil
user=> (def a '())
#'user/a
user=> a
()
user=> (first a)
nil
user=>
-------------------

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

  *   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 ambiguous.

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.
Mario

El jue., 18 oct. 2018 a las 20:27, Milles, Eric (TR Technology & Ops) (<er...@thomsonreuters.com>>) escribió:

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

________________________________
From: ocs@ocs <oc...@ocs.cz>>
Sent: Thursday, October 18, 2018 1:20 PM
To: dev@groovy.apache.org<ma...@groovy.apache.org>
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,
OC

On 18 Oct 2018, at 7:19 PM, Milles, Eric (TR Technology & Ops) <er...@thomsonreuters.com>> wrote:

"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 <oc...@ocs.cz>>
Sent: Thursday, October 18, 2018 12:07 PM
To: dev@groovy.apache.org<ma...@groovy.apache.org>
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 <pa...@gmail.com>> wrote:

-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).


Re: DGM for first or default

Posted by Paul King <pa...@asert.com.au>.
Groovy 2.5 still has JDK 7 as minimum whereas Groovy 3.0 has 8 as minimum.
You can still add DGM methods
into org.codehaus.groovy.vmplugin.v8.PluginDefaultGroovyMethods and then
they will only be available when running on a JDK8+ VM.

Wrt to the question of whether we should have firstOrElse, lastOrElse,
getAtOrElse, etc., it is certainly a possibility to add such a whole myriad
of duplicated methods but there might be better alternatives. Does the
existing ListWtihDefault work for you? It does mutate which might not be
what you are after but perhaps we could create an alternative variant of
that.

Cheers, Paul.


On Mon, Feb 18, 2019 at 7:36 AM Milles, Eric (TR Tech, Content & Ops) <
eric.milles@thomsonreuters.com> wrote:

> When I first worked all this up my target was Groovy 2.4.  If that is
> raised to Groovy 2.5+ I just started to wonder if java.util.Optional
> could be leveraged for an improved solution.  I also remembered some
> feedback some time ago from MG where to no-arg call would be "getName()" so
> that it could be used in Groovy sources as "name".  Then if there were
> versions with more arguments, they would be "name(arg1, arg2, ...)".
>
>
> So if I were to implement new DGMs in a vacuum, would something like this
> make sense?
>
>
> public static <T> Optional<T> getFirst(Iterable<T> self)
>
> public static <T> Optional<T> getFirst(List<T> self)
> public static <T> Optional<T> getFirst(T[] self)
> public static <T> Optional<T> getFirst(
> org.codehaus.groovy.runtime.NullObject self)
>
>
> This could be used like "list.first.orElse(defaultValue)".  Now that I
> write that out, I can see the conflict with list spread shorthand.  Darn, I
> wish that didn't exist and you had to explicitly use "list*.prop".
>
>
> *General question: *Are there limitations to using Java 8 stuff in Groovy
> core?  I'm not sure how Android support comes into play here.
>
>
> ------------------------------
> *From:* Milles, Eric (TR Tech, Content & Ops) <
> eric.milles@thomsonreuters.com>
> *Sent:* Sunday, February 17, 2019 1:56 PM
> *To:* dev@groovy.apache.org
> *Subject:* Re: DGM for first or default
>
>
> I'd like to restart this discussion.  I'm not sure if this should move to
> new JIRA ticket or Pull Request.  There are a few open questions I'd like
> to get some feedback on.  I have managed to solve the problem of getting
> from a null array/iterable.
>
>
> My use case is getting the first item from an iterable or else a supplied
> default.  Alternate proposals like "list?.first() ?: defaultValue" or
> "list?.find() ?: defaultValue" do not properly handle all use cases.  It
> took quite a number of tries to figure it out.
>
>
> "list ? list.first() : defaultValue" appears to be roughly equivalent.
> However, having the additional DGMs would mean a one-time check for
> non-null, non-empty and elimination of repeated "list", which may be a more
> complicated expression.  And in rare cases, a type could extend Iterable and
> provide a non-standard implementation of asBoolean().
>
>
>
> *Proposed additions to DefaultGroovyMethods:*
>
>
> public static <T> T firstOrElse(Iterable<T> self, T defaultValue)
>
> public static <T> T firstOrElse(List<T> self, T defaultValue) // allows
> use of isEmpty() and get(i) instead of creating an Iterator instance
>
> public static <T> T firstOrElse(T[] self, T defaultValue)
>
> public static <T> T firstOrElse(org.codehaus.groovy.runtime.NullObject
> self, T defaultValue) // exists solely for the (null).firstOrDefault(value)
> case
>
> public static <T> T firstOrElse(Iterable<T> self, Supplier<T> defaultValue
> )
>
> public static <T> T firstOrElse(List<T> self, Supplier<T> defaultValue)
>
> public static <T> T firstOrElse(T[] self, Supplier<T> defaultValue)
>
> public static <T> T
> firstOrElse(org.codehaus.groovy.runtime.NullObject self, Supplier<T>
> defaultValue)
>
> Since this is targeted at Groovy 2.5+ I have selected
> java.util.function.Supplier instead of groovy.lang.Closure.  Although that
> could be changed if a new Groovy 2.4 minor release was planned.
>
>
> *Usage:*
>   Iterable<Object> iterable = null
>   println iterable.firstOrElse('default') // prints 'default'
>
>   iterable = []
>   println iterable.firstOrElse('default') // prints 'default'
>
>   iterable = [0]
>   println iterable.firstOrElse('default') // prints 0
>
>   iterable = [null]
>   println iterable.firstOrElse('default') // prints null
>
>   iterable = [false]
>   println iterable.firstOrElse('default') // prints false
>
>   iterable = null
>   iterable.firstOrElse { -> throw new ExceptionOfMyChoosing() } // throws
>
>
>
> *Open items:*
>
>
>    1. Should a set of methods "lastOrElse" also be created?  It would not
>    take much effort to add them at the same time.
>    2. Should the "getAt" methods be similarly extended, like "public
>    static <T> T getAt(List<T> self, int idx, T defaultValue)", etc.
>    3. If "getAt" is extended in this way, would it be useful to also
>    consider extending the "[idx]" syntax form of "getAt" to include the
>    default?
>    4. There was a question raised: if "iterable" contains Closures or
>    Suppliers, how should that case be handled?  I'm curious how often this
>    might come up.
>
>
>
>
> ------------------------------
> *From:* Milles, Eric (TR Technology & Ops) <eric.milles@thomsonreuters.com
> >
> *Sent:* Friday, October 19, 2018 10:54 AM
> *To:* dev@groovy.apache.org
> *Subject:* Re: DGM for first or default
>
>
> 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 iter.next();
>         }
>         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 <ma...@gmail.com>
> *Sent:* Thursday, October 18, 2018 6:19 PM
> *To:* dev@groovy.apache.org
> *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
>
> scala>
> ---------------------
>
> 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=> a
> nil
> user=> (first a)
> nil
> user=> (def a '(nil))
> #'user/a
> user=> a
> (nil)
> user=> (first a)
> nil
> user=> (def a '())
> #'user/a
> user=> a
> ()
> user=> (first a)
> nil
> user=>
> -------------------
>
> BTW I forgot to mention that Groovy 3 will have safe indexing meaning an
> expression like the following:
>
>    - 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 ambiguous.
>
> 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.
> Mario
>
> El jue., 18 oct. 2018 a las 20:27, Milles, Eric (TR Technology & Ops) (<
> eric.milles@thomsonreuters.com>) escribió:
>
> I think first() exists so there is a semantic pair for functional
> programming: first()/head() and tail()  or init() and last()
>
> ------------------------------
> *From:* ocs@ocs <oc...@ocs.cz>
> *Sent:* Thursday, October 18, 2018 1:20 PM
> *To:* dev@groovy.apache.org
> *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,
> OC
>
> On 18 Oct 2018, at 7:19 PM, Milles, Eric (TR Technology & Ops) <
> eric.milles@thomsonreuters.com> wrote:
>
> "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 <oc...@ocs.cz>
> *Sent:* Thursday, October 18, 2018 12:07 PM
> *To:* dev@groovy.apache.org
> *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 <pa...@gmail.com>
> wrote:
>
> -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).
>
>
>

Re: DGM for first or default

Posted by "Milles, Eric (TR Tech, Content & Ops)" <er...@thomsonreuters.com>.
When I first worked all this up my target was Groovy 2.4.  If that is raised to Groovy 2.5+ I just started to wonder if java.util.Optional could be leveraged for an improved solution.  I also remembered some feedback some time ago from MG where to no-arg call would be "getName()" so that it could be used in Groovy sources as "name".  Then if there were versions with more arguments, they would be "name(arg1, arg2, ...)".


So if I were to implement new DGMs in a vacuum, would something like this make sense?


public static <T> Optional<T> getFirst(Iterable<T> self)

public static <T> Optional<T> getFirst(List<T> self)

public static <T> Optional<T> getFirst(T[] self)
public static <T> Optional<T> getFirst(org.codehaus.groovy.runtime.NullObject self)

This could be used like "list.first.orElse(defaultValue)".  Now that I write that out, I can see the conflict with list spread shorthand.  Darn, I wish that didn't exist and you had to explicitly use "list*.prop".


General question: Are there limitations to using Java 8 stuff in Groovy core?  I'm not sure how Android support comes into play here.


________________________________
From: Milles, Eric (TR Tech, Content & Ops) <er...@thomsonreuters.com>
Sent: Sunday, February 17, 2019 1:56 PM
To: dev@groovy.apache.org
Subject: Re: DGM for first or default


I'd like to restart this discussion.  I'm not sure if this should move to new JIRA ticket or Pull Request.  There are a few open questions I'd like to get some feedback on.  I have managed to solve the problem of getting from a null array/iterable.


My use case is getting the first item from an iterable or else a supplied default.  Alternate proposals like "list?.first() ?: defaultValue" or "list?.find() ?: defaultValue" do not properly handle all use cases.  It took quite a number of tries to figure it out.


"list ? list.first() : defaultValue" appears to be roughly equivalent.  However, having the additional DGMs would mean a one-time check for non-null, non-empty and elimination of repeated "list", which may be a more complicated expression.  And in rare cases, a type could extend Iterable and provide a non-standard implementation of asBoolean().



Proposed additions to DefaultGroovyMethods:


public static <T> T firstOrElse(Iterable<T> self, T defaultValue)

public static <T> T firstOrElse(List<T> self, T defaultValue) // allows use of isEmpty() and get(i) instead of creating an Iterator instance

public static <T> T firstOrElse(T[] self, T defaultValue)

public static <T> T firstOrElse(org.codehaus.groovy.runtime.NullObject self, T defaultValue) // exists solely for the (null).firstOrDefault(value) case


public static <T> T firstOrElse(Iterable<T> self, Supplier<T> defaultValue)

public static <T> T firstOrElse(List<T> self, Supplier<T> defaultValue)

public static <T> T firstOrElse(T[] self, Supplier<T> defaultValue)

public static <T> T firstOrElse(org.codehaus.groovy.runtime.NullObject self, Supplier<T> defaultValue)

Since this is targeted at Groovy 2.5+ I have selected java.util.function.Supplier instead of groovy.lang.Closure.  Although that could be changed if a new Groovy 2.4 minor release was planned.


Usage:
  Iterable<Object> iterable = null
  println iterable.firstOrElse('default') // prints 'default'

  iterable = []
  println iterable.firstOrElse('default') // prints 'default'

  iterable = [0]
  println iterable.firstOrElse('default') // prints 0

  iterable = [null]
  println iterable.firstOrElse('default') // prints null

  iterable = [false]
  println iterable.firstOrElse('default') // prints false

  iterable = null
  iterable.firstOrElse { -> throw new ExceptionOfMyChoosing() } // throws



Open items:


  1.  Should a set of methods "lastOrElse" also be created?  It would not take much effort to add them at the same time.
  2.  Should the "getAt" methods be similarly extended, like "public static <T> T getAt(List<T> self, int idx, T defaultValue)", etc.
  3.  If "getAt" is extended in this way, would it be useful to also consider extending the "[idx]" syntax form of "getAt" to include the default?
  4.  There was a question raised: if "iterable" contains Closures or Suppliers, how should that case be handled?  I'm curious how often this might come up.



________________________________
From: Milles, Eric (TR Technology & Ops) <er...@thomsonreuters.com>
Sent: Friday, October 19, 2018 10:54 AM
To: dev@groovy.apache.org
Subject: Re: DGM for first or default


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 iter.next();
        }
        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 <ma...@gmail.com>
Sent: Thursday, October 18, 2018 6:19 PM
To: dev@groovy.apache.org
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

scala>
---------------------

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=> a
nil
user=> (first a)
nil
user=> (def a '(nil))
#'user/a
user=> a
(nil)
user=> (first a)
nil
user=> (def a '())
#'user/a
user=> a
()
user=> (first a)
nil
user=>
-------------------

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

  *   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 ambiguous.

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.
Mario

El jue., 18 oct. 2018 a las 20:27, Milles, Eric (TR Technology & Ops) (<er...@thomsonreuters.com>>) escribió:

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

________________________________
From: ocs@ocs <oc...@ocs.cz>>
Sent: Thursday, October 18, 2018 1:20 PM
To: dev@groovy.apache.org<ma...@groovy.apache.org>
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,
OC

On 18 Oct 2018, at 7:19 PM, Milles, Eric (TR Technology & Ops) <er...@thomsonreuters.com>> wrote:

"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 <oc...@ocs.cz>>
Sent: Thursday, October 18, 2018 12:07 PM
To: dev@groovy.apache.org<ma...@groovy.apache.org>
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 <pa...@gmail.com>> wrote:

-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).


Re: DGM for first or default

Posted by "Milles, Eric (TR Tech, Content & Ops)" <er...@thomsonreuters.com>.
I'd like to restart this discussion.  I'm not sure if this should move to new JIRA ticket or Pull Request.  There are a few open questions I'd like to get some feedback on.  I have managed to solve the problem of getting from a null array/iterable.


My use case is getting the first item from an iterable or else a supplied default.  Alternate proposals like "list?.first() ?: defaultValue" or "list?.find() ?: defaultValue" do not properly handle all use cases.  It took quite a number of tries to figure it out.


"list ? list.first() : defaultValue" appears to be roughly equivalent.  However, having the additional DGMs would mean a one-time check for non-null, non-empty and elimination of repeated "list", which may be a more complicated expression.  And in rare cases, a type could extend Iterable and provide a non-standard implementation of asBoolean().



Proposed additions to DefaultGroovyMethods:


public static <T> T firstOrElse(Iterable<T> self, T defaultValue)

public static <T> T firstOrElse(List<T> self, T defaultValue) // allows use of isEmpty() and get(i) instead of creating an Iterator instance

public static <T> T firstOrElse(T[] self, T defaultValue)

public static <T> T firstOrElse(org.codehaus.groovy.runtime.NullObject self, T defaultValue) // exists solely for the (null).firstOrDefault(value) case


public static <T> T firstOrElse(Iterable<T> self, Supplier<T> defaultValue)

public static <T> T firstOrElse(List<T> self, Supplier<T> defaultValue)

public static <T> T firstOrElse(T[] self, Supplier<T> defaultValue)

public static <T> T firstOrElse(org.codehaus.groovy.runtime.NullObject self, Supplier<T> defaultValue)

Since this is targeted at Groovy 2.5+ I have selected java.util.function.Supplier instead of groovy.lang.Closure.  Although that could be changed if a new Groovy 2.4 minor release was planned.


Usage:
  Iterable<Object> iterable = null
  println iterable.firstOrElse('default') // prints 'default'

  iterable = []
  println iterable.firstOrElse('default') // prints 'default'

  iterable = [0]
  println iterable.firstOrElse('default') // prints 0

  iterable = [null]
  println iterable.firstOrElse('default') // prints null

  iterable = [false]
  println iterable.firstOrElse('default') // prints false

  iterable = null
  iterable.firstOrElse { -> throw new ExceptionOfMyChoosing() } // throws



Open items:


  1.  Should a set of methods "lastOrElse" also be created?  It would not take much effort to add them at the same time.
  2.  Should the "getAt" methods be similarly extended, like "public static <T> T getAt(List<T> self, int idx, T defaultValue)", etc.
  3.  If "getAt" is extended in this way, would it be useful to also consider extending the "[idx]" syntax form of "getAt" to include the default?
  4.  There was a question raised: if "iterable" contains Closures or Suppliers, how should that case be handled?  I'm curious how often this might come up.



________________________________
From: Milles, Eric (TR Technology & Ops) <er...@thomsonreuters.com>
Sent: Friday, October 19, 2018 10:54 AM
To: dev@groovy.apache.org
Subject: Re: DGM for first or default


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 iter.next();
        }
        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 <ma...@gmail.com>
Sent: Thursday, October 18, 2018 6:19 PM
To: dev@groovy.apache.org
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

scala>
---------------------

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=> a
nil
user=> (first a)
nil
user=> (def a '(nil))
#'user/a
user=> a
(nil)
user=> (first a)
nil
user=> (def a '())
#'user/a
user=> a
()
user=> (first a)
nil
user=>
-------------------

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

  *   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 ambiguous.

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.
Mario

El jue., 18 oct. 2018 a las 20:27, Milles, Eric (TR Technology & Ops) (<er...@thomsonreuters.com>>) escribió:

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

________________________________
From: ocs@ocs <oc...@ocs.cz>>
Sent: Thursday, October 18, 2018 1:20 PM
To: dev@groovy.apache.org<ma...@groovy.apache.org>
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,
OC

On 18 Oct 2018, at 7:19 PM, Milles, Eric (TR Technology & Ops) <er...@thomsonreuters.com>> wrote:

"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 <oc...@ocs.cz>>
Sent: Thursday, October 18, 2018 12:07 PM
To: dev@groovy.apache.org<ma...@groovy.apache.org>
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 <pa...@gmail.com>> wrote:

-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).


Re: DGM for first or default

Posted by "Milles, Eric (TR Technology & Ops)" <er...@thomsonreuters.com>.
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 iter.next();
        }
        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 <ma...@gmail.com>
Sent: Thursday, October 18, 2018 6:19 PM
To: dev@groovy.apache.org
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

scala>
---------------------

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=> a
nil
user=> (first a)
nil
user=> (def a '(nil))
#'user/a
user=> a
(nil)
user=> (first a)
nil
user=> (def a '())
#'user/a
user=> a
()
user=> (first a)
nil
user=>
-------------------

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

  *   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 ambiguous.

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.
Mario

El jue., 18 oct. 2018 a las 20:27, Milles, Eric (TR Technology & Ops) (<er...@thomsonreuters.com>>) escribió:

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

________________________________
From: ocs@ocs <oc...@ocs.cz>>
Sent: Thursday, October 18, 2018 1:20 PM
To: dev@groovy.apache.org<ma...@groovy.apache.org>
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,
OC

On 18 Oct 2018, at 7:19 PM, Milles, Eric (TR Technology & Ops) <er...@thomsonreuters.com>> wrote:

"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 <oc...@ocs.cz>>
Sent: Thursday, October 18, 2018 12:07 PM
To: dev@groovy.apache.org<ma...@groovy.apache.org>
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 <pa...@gmail.com>> wrote:

-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,
OC



p

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

Cheers,
Daniel.Sun




-----
Daniel Sun
Apache Groovy committer
Blog: http://blog.sunlan.me<https://urldefense.proofpoint.com/v2/url?u=http-3A__blog.sunlan.me_&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=Kuqjwc4Pu38Y9C4Zooo3uBjDkGvyna3lloonS2m7GTE&e=>
Twitter: @daniel_sun

--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html<https://urldefense.proofpoint.com/v2/url?u=http-3A__groovy.329449.n5.nabble.com_Groovy-2DDev-2Df372993.html&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=J5vmRmzvL66tJOtxSbSidNjQHcCHKNV3t2A0OHPCgDY&e=>


Re: DGM for first or default

Posted by Mario Garcia <ma...@gmail.com>.
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

scala>
---------------------

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=> a
nil
user=> (first a)
nil
user=> (def a '(nil))
#'user/a
user=> a
(nil)
user=> (first a)
nil
user=> (def a '())
#'user/a
user=> a
()
user=> (first a)
nil
user=>
-------------------

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

   - 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 ambiguous.

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.
Mario

El jue., 18 oct. 2018 a las 20:27, Milles, Eric (TR Technology & Ops) (<
eric.milles@thomsonreuters.com>) escribió:

> I think first() exists so there is a semantic pair for functional
> programming: first()/head() and tail()  or init() and last()
>
> ------------------------------
> *From:* ocs@ocs <oc...@ocs.cz>
> *Sent:* Thursday, October 18, 2018 1:20 PM
> *To:* dev@groovy.apache.org
> *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,
> OC
>
> On 18 Oct 2018, at 7:19 PM, Milles, Eric (TR Technology & Ops) <
> eric.milles@thomsonreuters.com> wrote:
>
> "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 <oc...@ocs.cz>
> *Sent:* Thursday, October 18, 2018 12:07 PM
> *To:* dev@groovy.apache.org
> *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 <pa...@gmail.com>
> wrote:
>
> -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,
> OC
>
>
>
> p
>
> On Thu, Oct 18, 2018 at 6:45 PM Daniel.Sun <su...@apache.org> wrote:
>
> +0 from me.
> P.S. we should add similar DGM for `last` too?
>
> Cheers,
> Daniel.Sun
>
>
>
>
> -----
> Daniel Sun
> Apache Groovy committer
> Blog: http://blog.sunlan.me
> <https://urldefense.proofpoint.com/v2/url?u=http-3A__blog.sunlan.me_&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=Kuqjwc4Pu38Y9C4Zooo3uBjDkGvyna3lloonS2m7GTE&e=>
>
> Twitter: @daniel_sun
>
> --
> Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html
> <https://urldefense.proofpoint.com/v2/url?u=http-3A__groovy.329449.n5.nabble.com_Groovy-2DDev-2Df372993.html&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=J5vmRmzvL66tJOtxSbSidNjQHcCHKNV3t2A0OHPCgDY&e=>
>
>
>

Re: DGM for first or default

Posted by "Milles, Eric (TR Technology & Ops)" <er...@thomsonreuters.com>.
I think first() exists so there is a semantic pair for functional programming: first()/head() and tail()  or init() and last()

________________________________
From: ocs@ocs <oc...@ocs.cz>
Sent: Thursday, October 18, 2018 1:20 PM
To: dev@groovy.apache.org
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,
OC

On 18 Oct 2018, at 7:19 PM, Milles, Eric (TR Technology & Ops) <er...@thomsonreuters.com>> wrote:

"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 <oc...@ocs.cz>>
Sent: Thursday, October 18, 2018 12:07 PM
To: dev@groovy.apache.org<ma...@groovy.apache.org>
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 <pa...@gmail.com>> wrote:

-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,
OC



p

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

Cheers,
Daniel.Sun




-----
Daniel Sun
Apache Groovy committer
Blog: http://blog.sunlan.me<https://urldefense.proofpoint.com/v2/url?u=http-3A__blog.sunlan.me_&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=Kuqjwc4Pu38Y9C4Zooo3uBjDkGvyna3lloonS2m7GTE&e=>
Twitter: @daniel_sun

--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html<https://urldefense.proofpoint.com/v2/url?u=http-3A__groovy.329449.n5.nabble.com_Groovy-2DDev-2Df372993.html&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=J5vmRmzvL66tJOtxSbSidNjQHcCHKNV3t2A0OHPCgDY&e=>


Re: DGM for first or default

Posted by "ocs@ocs" <oc...@ocs.cz>.
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,
OC

> On 18 Oct 2018, at 7:19 PM, Milles, Eric (TR Technology & Ops) <er...@thomsonreuters.com> wrote:
> 
> "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 <ocs@ocs.cz <ma...@ocs.cz>>
> Sent: Thursday, October 18, 2018 12:07 PM
> To: dev@groovy.apache.org <ma...@groovy.apache.org>
> 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 <paolo.ditommaso@gmail.com <ma...@gmail.com>> wrote:
>> 
>> -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,
> OC
> 
>> 
>> 
>> p
>> 
>> On Thu, Oct 18, 2018 at 6:45 PM Daniel.Sun <sunlan@apache.org <ma...@apache.org>> wrote:
>> +0 from me.
>> P.S. we should add similar DGM for `last` too?
>> 
>> Cheers,
>> Daniel.Sun
>> 
>> 
>> 
>> 
>> -----
>> Daniel Sun 
>> Apache Groovy committer 
>> Blog: http://blog.sunlan.me <https://urldefense.proofpoint.com/v2/url?u=http-3A__blog.sunlan.me_&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=Kuqjwc4Pu38Y9C4Zooo3uBjDkGvyna3lloonS2m7GTE&e=> 
>> Twitter: @daniel_sun 
>> 
>> --
>> Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html <https://urldefense.proofpoint.com/v2/url?u=http-3A__groovy.329449.n5.nabble.com_Groovy-2DDev-2Df372993.html&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=J5vmRmzvL66tJOtxSbSidNjQHcCHKNV3t2A0OHPCgDY&e=>

Re: DGM for first or default

Posted by "Milles, Eric (TR Technology & Ops)" <er...@thomsonreuters.com>.
"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 <oc...@ocs.cz>
Sent: Thursday, October 18, 2018 12:07 PM
To: dev@groovy.apache.org
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 <pa...@gmail.com>> wrote:

-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,
OC



p

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

Cheers,
Daniel.Sun




-----
Daniel Sun
Apache Groovy committer
Blog: http://blog.sunlan.me<https://urldefense.proofpoint.com/v2/url?u=http-3A__blog.sunlan.me_&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=Kuqjwc4Pu38Y9C4Zooo3uBjDkGvyna3lloonS2m7GTE&e=>
Twitter: @daniel_sun

--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html<https://urldefense.proofpoint.com/v2/url?u=http-3A__groovy.329449.n5.nabble.com_Groovy-2DDev-2Df372993.html&d=DwMFAg&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=eCM29fHJoKqW_CdKJO2GxdVR6VMqldnDZ9NQgYxSo08&s=J5vmRmzvL66tJOtxSbSidNjQHcCHKNV3t2A0OHPCgDY&e=>


Re: DGM for first or default

Posted by "ocs@ocs" <oc...@ocs.cz>.
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 <pa...@gmail.com> wrote:
> 
> -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,
OC

> 
> 
> p
> 
> On Thu, Oct 18, 2018 at 6:45 PM Daniel.Sun <sunlan@apache.org <ma...@apache.org>> wrote:
> +0 from me.
> P.S. we should add similar DGM for `last` too?
> 
> Cheers,
> Daniel.Sun
> 
> 
> 
> 
> -----
> Daniel Sun 
> Apache Groovy committer 
> Blog: http://blog.sunlan.me <http://blog.sunlan.me/> 
> Twitter: @daniel_sun 
> 
> --
> Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html <http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html>


Re: DGM for first or default

Posted by Paolo Di Tommaso <pa...@gmail.com>.
-1, it can be easily done as:

list.first() ?: defaultValue


p

On Thu, Oct 18, 2018 at 6:45 PM Daniel.Sun <su...@apache.org> wrote:

> +0 from me.
> P.S. we should add similar DGM for `last` too?
>
> Cheers,
> Daniel.Sun
>
>
>
>
> -----
> Daniel Sun
> Apache Groovy committer
> Blog: http://blog.sunlan.me
> Twitter: @daniel_sun
>
> --
> Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html
>

Re: DGM for first or default

Posted by "Daniel.Sun" <su...@apache.org>.
+0 from me.
P.S. we should add similar DGM for `last` too?

Cheers,
Daniel.Sun




-----
Daniel Sun 
Apache Groovy committer 
Blog: http://blog.sunlan.me 
Twitter: @daniel_sun 

--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Dev-f372993.html

Re: DGM for first or default

Posted by Mauro Molinari <ma...@tiscali.it>.
Isn't it equivalent to something like this?

|def elem = collection?.first()?: defaultValue||
||def elem = collection?.first()?: defaultSupplier()||
|
Mauro

Il 18/10/2018 17:39, Milles, Eric (TR Technology & Ops) ha scritto:
>
> I see there are the following DGMs for getting first element of 
> a "collection":
>
>   static<T>Tfirst(T[] self)
>
>   static<T>Tfirst(List<T>self)
>
> static<T>Tfirst(Iterable<T>self)
>
>
> *Is there a simple sequence for getting the first element or a default 
> value if the "collection" is empty?*  If not, may I propose the 
> addition of the following DGMs:
>
>   static<T>Tfirst(T[] self, TdefaultValue)
>
>   static<T>Tfirst(List<T>self, TdefaultValue)
>
>   static<T>Tfirst(Iterable<T>self, TdefaultValue)
>
>   static<T>Tfirst(T[] self, Closure<T> defaultSupplier)
> static<T>Tfirst(List<T>self, Closure<T> defaultSupplier)
>
>   static<T>Tfirst(Iterable<T>self, Closure<T> defaultSupplier)
>
>
>
> Eric M.
>


Re: DGM for first or default

Posted by "ocs@ocs" <oc...@ocs.cz>.
P.S. Oh, and when I am writing anyway — please, do not abuse the “overloaded” methods which differ just by their argument lists (myself, I consider them always at best suspicious; mostly plain wrong). Instead of the suggestion below, if something like that is accepted, it would be much better to change the method name appropriately (say, e.g., firstWithDefault, firstWithSupplier). Or perhaps named arguments might be (consistently!) used for these things (e.g., “first(default:value)” or “first(supplier:value)”).

Consider e.g., an array of closures, of which one would want to get the first one with a default closure... with the definitions suggested below that's going to be fun!

All the best,
OC

> On 18 Oct 2018, at 5:39 PM, Milles, Eric (TR Technology & Ops) <er...@thomsonreuters.com> wrote:
> 
> I see there are the following DGMs for getting first element of a "collection":
>   static <T> T first(T[] self)
>   static <T> T first(List<T> self)
>   static <T> T first(Iterable<T> self)
> 
> Is there a simple sequence for getting the first element or a default value if the "collection" is empty?  If not, may I propose the addition of the following DGMs:
>   static <T> T first(T[] self, T defaultValue)
>   static <T> T first(List<T> self, T defaultValue)
>   static <T> T first(Iterable<T> self, T defaultValue)
>   static <T> T first(T[] self, Closure<T> defaultSupplier)
>   static <T> T first(List<T> self, Closure<T> defaultSupplier)
>   static <T> T first(Iterable<T> self, Closure<T> defaultSupplier)
> 
> 
> Eric M.