On 1/17/2025 5:49 PM, David Alayachew wrote:

It definitely helps.

I guess my next question is, there is no bridge method, which is why this fails. Why not add a bridge method? What is stopping Java from doing this?


The default response to the question "Should we fundamentally change how Java source files are compiled into class files?" is "No." ;-)

Covariant returns "work" for instance methods for several reasons. Such behavior is expected from object-oriented type theory where it is sound for an overridden method to return a more specialized type in a subtype. Also, when presented with a single snapshot of the type hierarchy, as during compilation, it is relatively straightforward for the compiler to compute which bridge methods are needed, roughly look over the superclass and implemented interfaces for methods with the same name and set of arguments, but a different return type.

Muddier on both accounts for how static methods would be handled by such a bridge method feature.

-Joe


And to be clear, it is obvious to me that SewuencedSet.of is the right answer. I am just trying to understand the point you raised.


On Fri, Jan 17, 2025, 8:14 PM Joseph D. Darcy <joe.da...@oracle.com> wrote:


    On 1/17/2025 5:00 PM, David Alayachew wrote:

    Thanks for the corrections folks. I was thinking from the
    perspective of LSP. I now see that there is the performance
    perspective to consider too.

    Now that said, I don't understand your comment Joe Darcy. Could
    you explain it in more detail?

    Say you compile your code against JDK 24 and use the 1-argument
    Set.Of() method. For that call site, your class file will refer to
    a method using information akin to

        "In the class java.util.Set, a method named "of" that *returns
    a java.util.Set* and take a java.lang.Object as an argument"

    (The generic information is basically erased in the class file,
    hence Set rather than Set<E> and Object rather than E.)

    If we were then in JDK 25 to replace in java.util.Set

        static <E> Set<E> of(E e1){...}

    with

        static <E> SequencedSet<E> of(E e1){...}

    when your class file ran against JDK 25, there would be no method

        "In the class java.util.Set, a method named "of" that *returns
    a java.util.Set* and take a java.lang.Object as an argument"

    for your class to call and the linkage would fail.

    For static methods, the change is equivalent to removing a method
    and adding back a different, same-named method.

    HTH,

    -Joe


    My initial pick up of your comment is that, the parameter types
    and the return types of a method must match the types exactly
    between releases, otherwise there are no bridge methods FOR
    STATIC TYPES. But as for why, I don't understand.

    I know that static methods are not so much inherited as they are
    just given as is (hence why there is not really a static abstract
    method). But I don't quite see the line connecting that with no
    bridge methods for static. Maybe I don't understand bridge
    methods well enough.


    On Fri, Jan 17, 2025, 12:32 PM Joseph D. Darcy
    <joe.da...@oracle.com> wrote:

        On 1/16/2025 11:26 PM, Rafael Winterhalter wrote:
        Would it even be possible to change the return types of
        Set.of(...) and Map.of(...) without breaking binary
        compatibility?


        In short, no.

        The methods in question are *static* methods. Switching to
        covariant overrides with more precise return types works for
        subclasses because of bridge methods.

        In a bit more detail, in a covariant override a single method
        in the source code gets translated into multiply methods in
        the class file. References to methods in the class file use
        the argument types and return type so if an old class file
        refers to the previously declared source-level return type,
        there is the bridge method present to be linked to (for
        binary compatibility) and then executed.

        -Joe



        I also think that the randomization of Set.of(...) and
        Map.of(...) is a good property as it uncovers bugs early if
        one relies on iteration order. This especially since those
        methods are often used in tests where production code would
        use a proper HashSet which cannot guarantee iteration order
        for good reasons. Exactly here I think the new interfaces
        are a good addition as it uncovers such misconceptions. If
        code relies on insertion order, providing a Set.of(...) does
        no longer compile, what is a good thing.

        To me, adding SequencedSet.of(...) and SequencedMap.of(...)
        sounds like the right approach, with implementations similar
        to that of Set.of(...) and Map.of(...). As for megamorphism,
        I think the chance of encounter at a call site is similar,
        as Set12 and SetN from the Set interface are typically
        combined with HashMap. As for a possible SequencedSet12 and
        SequencedSetN, I think they would normally be seen with
        LinkedHashSet.

        Best regards, Rafael

        Am Fr., 17. Jan. 2025 um 00:36 Uhr schrieb David Alayachew
        <davidalayac...@gmail.com>:

            I should also add, the documentation went out of their
            way to specify that iteration order is unspecified.

            Also, I see Rémi's comment, but that's even more
            unconvincing to me.

            Map.of has an upper limit of 10 entries, and
            Map.ofEntries has an upper limit of that Java max file
            size limit thing. You all know what I am talking about.

            Point is, both of these static factories were meant to
            be used on a small number of entries. If it truly has
            just been not done until now, then the bug database will
            confirm that easily.

            When I get back, I can check myself.


            On Thu, Jan 16, 2025, 6:25 PM David Alayachew
            <davidalayac...@gmail.com> wrote:

                I guess let me ask the obvious question.

                Chesterton's fence -- why wasn't this done before? I
                refuse to believe that this idea wasn't thought up
                years ago, which leads me to believe there was a
                reason that it hasn't been done.

                Is there any way we can look this up in the bug
                database or something?


                On Thu, Jan 16, 2025, 2:28 PM Jens Lideström
                <j...@lidestrom.se> wrote:

                    Having the result Map.of and Set.of preserve the
                    insertion order would
                    often be convenient.

                    More often than not programs iterate over the
                    contents of a maps and
                    sets at some point. For example to present the
                    values in a GUI, for
                    serialisation, or even for error printouts. In
                    all those cases having a
                    fixed iteration order is much better than having
                    a random iteration
                    order.

                    Often it is even a subtle bug to have a random
                    iteration order. For
                    example, I ran in to a situation where jdeps
                    printed a error message
                    containing a list of modules. But the list was
                    in a different order on
                    each run of the program! It took me a while to
                    figure out that it was
                    actually the same list. A possible explanation
                    is that jdeps is
                    implemented using Map.of or Set.of.

                    Because of this I think I would be better if the
                    most commonly used
                    standard collection factories produced
                    collections with a fixed
                    iteration order.

                    Guavas ImmutableMap and ImmutableSet also
                    preserve insertion order.

                    Regards,
                    Jens Lideström


                    On 2025-01-16 08:44, Remi Forax wrote:

                    > -------------------------
                    >
                    >> From: "Rafael Winterhalter"
                    <rafael....@gmail.com>
                    >> To: "core-libs-dev"
                    <core-libs-...@openjdk.java.net>
                    >> Sent: Thursday, January 16, 2025 8:13:17 AM
                    >> Subject: Factory methods for SequencedSet and
                    SequencedMap
                    >
                    >> Hello,
                    >
                    > Hello,
                    >
                    >> I am happily taking SequencedSet and
                    SequencedMap into use, but one
                    >> inconvenience I encounter is the lack of
                    factory methods for the two.
                    >> In code where many (initial) collections have
                    zero or one element (for
                    >> later aggregation), I now write
                    Set.of()/Set.of(one) and
                    >> Map.of()/Map.of(key, value), as it makes the
                    code shorter and more
                    >> readable. Those collections are of course
                    implicitly sequenced, but
                    >> now I must make the variable type of the
                    surrounding monad Set and
                    >> Map, and simply assume that a LinkedHashSet
                    or LinkedHashMap is used
                    >> when a collection of more than one element is
                    set, without requiring
                    >> the interface type. This does not require any
                    type casting, as I rely
                    >> on the iteration order only, but the code
                    loses some of its
                    >> expressiveness.
                    >> I did not find any discussion around
                    introducing factories for
                    >> SequencedSet.of(...) and
                    SequencedMap.of(...), similar to those that
                    >> exist in the Set and Map interfaces. Was this
                    ever considered, and if
                    >> not, could it be?
                    >
                    > Thanks for re-starting that discussion, it was
                    talked a bit, but not as
                    > it should be.
                    >
                    > So the issue is that currently we do not have
                    any compact, unmodifiable
                    > and ordered Set/Map implementation,
                    > one use case is when you have data that comes
                    from a JSON object as a
                    > Map and you want to keep the inserted order,
                    if by example the JSON is
                    > a config file editable by a human, an other
                    example is in unit tests
                    > where you want to help the dev to read the
                    output of the test so the
                    > code that creates a Set/Map and what is
                    outputed by the test should be
                    > in the same order.
                    > Currently there is no good solution for those
                    use cases because
                    > Set|Map.copyOf() does not keep the ordering.
                    >
                    > I see two solutions, either we add a new
                    > SequenceSet|SequenceMap.of/copyOf, or we
                    change the impleemntation of
                    > Set|Map.of()/copyOf().
                    > Python had gone for the latter solution, which
                    has the advantage a
                    > being simple from the user POV, but from an
                    algorithm expert POV, a Set
                    > and a SequencedSet are different concepts we
                    may want to emphasis ?
                    >
                    >> Best regards, Rafael
                    >
                    > regards,
                    > Rémi

Reply via email to