On 10/8/15 2:10 PM, Roger Riggs wrote:
I am curious as to Stuart's question about whether it is supposed to figure out
the overloads
and is a bug, or if it just too difficult to make the inference work.

I talked this over (internal discussion) with Vicente Romero-Zaldivar, one of the compiler guys. He walked me through what the compiler is doing. He says this isn't a bug in the compiler. Here's what's going on.

We have

    // (1)
    <T> T nonNullOf(T obj, T defaultObj)

    // (2)
    <T> T nonNullOf(T obj, Supplier<? extends T> defaultSupplier)

and the code in question:

    void setSupplier(Supplier<String> arg) {
        Supplier<String> supplier = Objects.nonNullOf(arg, () -> ""); // ERROR
    }

The compiler first does overload resolution, and chooses (2) because it's more specific. The lambda matches Supplier, a functional interface, more specifically than it matches T, which is unconstrained (essentially Object) at this point.

Unfortunately we really wanted this code to call (1).

But now that the compiler has chosen (2), it tries to infer T. There's no value of T that allows both the first and the second arg to match, resulting in the error.

The usual problem with overloads is that resolution is ambiguous. This case is different. The compiler goes through the overload resolution process and comes up with an unambiguous answer. Unfortunately it's the "wrong" one, or at least, the one we as programmers didn't expect for this case. Once the compiler has chosen the "wrong" method, it proceeds down that path to an error.

The conclusion here is that we need to adjust the API so that it avoids overloading. This can be done by changing the name or arity. I can't really think of another parameter for this method, so that leaves us with the name.

We now return to our usual naming bikeshed.... :-)

s'marks





Thanks, Roger

The variations:
     nonNullOf(T, T) is ok but
     nonNullOfOrGet(T, Supplier<T>) is poor

Splitting between Of and Or
     nonNullOf(T, T)
     nonNullOrGet(T, Supplier<T>)   -   nope

Sigh...



On 10/8/2015 3:34 PM, fo...@univ-mlv.fr wrote:


------------------------------------------------------------------------

    *De: *"Roger Riggs" <roger.ri...@oracle.com>
    *À: *fo...@univ-mlv.fr
    *Cc: *"core-libs-dev" <core-libs-dev@openjdk.java.net>
    *Envoyé: *Jeudi 8 Octobre 2015 21:09:26
    *Objet: *Re: RFR 9: 8138963 : java.lang.Objects new method to
    default to non-null

    So for you, method overloading is a mis-feature of the language
    because it inhibits readability.
    Though I might argue, that the magic type inference is the real
    culprit.
    In most coding cases, the types of the arguments are visible
    and/or via syntax and naming.

    Thanks, Roger


I don't really like overloading mostly because the rules that govern
overloading are too complex. When you introduce a new feature like auto-boxing
or lambda auto-conversion in the language, you can not say that a call is
ambiguous with the new rules because it will break backward compatibility, so
you end up with weird overloading rules that you can only understand in the
light of the Java history.

Anyway, in this case the problem is not just overloading, it is the mix of
overloading and type inference as you said.
I vaguely remember that we, the lambda EG, discuss about javac emitting a
warning for cases like this one.

regards,
Rémi




    On 10/8/2015 2:37 PM, fo...@univ-mlv.fr wrote:

        Hi Roger,
        my point was that for me, all theses forms are ambiguous thus
        not readable.

            *De: *"Roger Riggs" <roger.ri...@oracle.com>
            *À: *"Remi Forax" <fo...@univ-mlv.fr>
            *Cc: *"core-libs-dev" <core-libs-dev@openjdk.java.net>
            *Envoyé: *Jeudi 8 Octobre 2015 16:44:54
            *Objet: *Re: RFR 9: 8138963 : java.lang.Objects new method
            to default to non-null

            Hi Remi,

            On 10/8/2015 4:49 AM, Remi Forax wrote:

                Hi Roger,
                using overloads here seems to be a bad idea,
                as a nice puzzler, what does the compiler do for these two
lines of code
                   Supplier<String> supplier = Objects.nonNullOf(null, () ->
null);
                   Supplier<String> supplier2 = Objects.nonNullOf(null, () ->
"");

            The first form compiled and threw the expected NPE at runtime.


        I'm not sure you can say this is the expected result. Why the
        compiler doesn't call <T> T nonNullOf(T, T) and return () ->
        null as Supplier ?



            In the second case, the () -> "" is a supplier<String> not
            a Supplier<Supplier<String>>.
            The compiler correctly produced a error.

        Why the compiler doesn't select the method <T> T nonNullOf(T,
        T) instead, this version compiles !

        and if you want more weirdness, what about ?
          Object o = Objects.nonNullOf"foo", null);



            I don't think the method name will help the developer much
            and just makes the name longer
            for everyone else who is not producing a
            Supplier<Supplier<T>>.


        maybe "nonNullOfGet" is a bad name, my point is that when you
        have several overloads like this, the result is not easy to
        predict (I suppose that people don't know by heart the chapter
        15.12.2 of the JLS).

        [...]


            Thanks, Roger


        regards,
        Rémi



                otherwise apart form the remark of Stephen, the code is Ok.

                cheers,
                Rémi

                ----- Mail original -----

                    De: "Roger Riggs"<roger.ri...@oracle.com>
                    À: "core-libs-dev"<core-libs-dev@openjdk.java.net>
                    Envoyé: Jeudi 8 Octobre 2015 00:24:26
                    Objet: Re: RFR 9: 8138963 : java.lang.Objects new method
to default to    non-null

                    Hi,

                    The original intent was to simplify the filling in of
default values
                    (even if null).
                    I took Remi's point about  the canonical coalescing
operator not always
                    returning non-null
                    but the push seems to be in the direction of making sure
the result is
                    always non-null.
                    I'd rather add a few very useful methods and avoid those 
with
                    diminishing returns.

                    I note that nulls are discovered eventually, but doing
more aggressive
                    checking is preferred.
                    I expect the compiler is able to squeeze out all the extra
checks.

                    In the current context of Objects that the jdk, I read the
naming
                    pattern of firstNonNull to imply
                    access to some sequential data structure like an array or
list; but it
                    doesn't gel with me to apply it to the arg list
                    (unless it was varargs).  The pattern of naming us "of"
as being
                    factory producing an object
                    from the arguments seems apropos and is concise.

                    Please consider and comment:

                          <T> T nonNullOf(T obj, T defaultObj);
                          <T> T nonNullOf(T, obj, Supplier<T> defaultSupplier);

                    Details are in the updated webrev:

http://cr.openjdk.java.net/~rriggs/webrev-object-non-null/

                    Regards, Roger


                    On 10/6/2015 6:42 PM, Remi Forax wrote:

                        Null coalescing is a popular operator in several
languages [1] and the
                        usual semantics is nullOrElse and not firstNonNull.
                        In languages like Kotlin or Swift, because there is a
distinction between
                        Object and Object?, it's not a big deal, you can not
de-reference null by
                        error, anyway.

                        Also note that nullOrElseGet, the one that takes a
supplier also exists in
                        Groovy and Kotlin under the name null safe navigation.

                        So even if i prefer the semantics of firstNonNull, i
think we should also
                        include both nullOrElse and nullOrElseGet.

                        regards,
                        Rémi

                        
[1]https://en.wikipedia.org/wiki/Null_coalescing_operator

                        -






Reply via email to