JEP 186: Collection Literals
Zhong Yu
zhong.j.yu at gmail.com
Wed Jan 15 15:05:48 PST 2014
On Wed, Jan 15, 2014 at 4:56 PM, Samir Talwar <samir at noodlesandwich.com> wrote:
> On Wed, Jan 15, 2014 at 8:24 PM, Remi Forax <forax at univ-mlv.fr> wrote:
>
>> On 01/15/2014 06:44 PM, Samir Talwar wrote:
>> > I've wanted to chip in to this thread all day. Now I finally have time.
>> :-D
>> >
>> > Remi: Overloads for `MyCollectionType.of(…)` are just pushing the work
>> onto
>> > the API designer. We should be able to do better than that. This sort of
>> > thing is duplicated all over Guava too (I think in that case it was to
>> > avoid unchecked warnings), and it's silly to expect everyone designing a
>> > collection to do the same.
>>
>> It depends how you define silly.
>> What I wanted to say is just that collection literal should not be more
>> complex than adding several overloads. And I fear that this is not
>> possible.
>> And the warning is not an unchecked warning but a varargs warning, and
>> for of() it can be disable by using @SafeVarargs.
>>
>
> You're right. Sorry for the mix-up. I'm not sure what you mean by "more
> complex" though. Do you mean the code required in APIs to support
> collection literals? (If not, ignore the next bit.) I don't think there's
> really a comparison to be made here; one exists purely to fill a language
> hole, and one to hook into a language feature that would be otherwise
> unavailable.
>
> >
>> > Klaus: Agreed. Strings are fine in dynamically typed languages, but when
>> we
>> > have static typing, I'd much rather use something the compiler can
>> check. I
>> > imagine that, just like in most JavaScript applications, most cases will
>> > expect a relatively small number of keys that are known ahead of time.
>>
>> The question was more, not to restrict keys to be String only but
>> to acknowledge that most of the keys will be String.
>>
>
> And I don't think this is true. When using string keys in JavaScript,
> Groovy, etc. this is done because strings are no less safe than, for
> example, enum values in a dynamically-typed language. In Java, etc. the
> rules are different. Enum values offer no real penalty and a whole load of
> compile-time benefits in most cases (i.e. where the keys are known ahead of
> time in options maps and the like). While I'm not sure that strings won't
> be more popular, I'd argue that's probably down to sloppiness and shouldn't
> be encouraged. Obviously, any type is a candidate for a map key, but I'd be
> upset if it was assumed to be a string and only processed as something else
> if there was some extra magic syntax (for example, `[(key): value]` in
> Groovy).
>
>>
>> >
>> > I am very much of the opinion that the concrete type of the object
>> > shouldn't be dictated. I think it should maintain a similar style to
>> > lambdas; that is that the type is determined by the context (left-hand
>> > side, parameter type, etc.). I would like to see something better than a
>> > cast (which is generally very long when generics get involved) for
>> > occasions where the concrete type is ambiguous, as this is going to
>> happen
>> > much more often than with lambdas.
>>
>> you want to be able to do a diamond in a cast ?
>>
>
> Not exactly. Often that's too late. For example, if I'm assigning to a
> variable of the type `List<Runnable<Integer>>`, then I can't just assign
> `[new DoThatThing(), new DoThatThing()]`. Nor can I cast it to
> `ArrayList<Runnable>` later, as it's already of the type
> `List<DoThatThing>`, and we can't vary the generic type. It needs to be
> done at construction time. Something like `new ArrayList<> [1, 2, 3]` would
> be more preferable, because then I can type `new ArrayList<Runnable> [x, y,
> z]`.
Why is this any better than
List.of(x, y, z);
ArrayList.of(x, y, z);
LinkedList.of(x, y, z);
>
>>
>> >
>> > I'd also like to avoid binding certain styles to specific interfaces; not
>> > all of us use List, Set and Map every day. One notable exception is the
>> > pcollections library, which defines persistent equivalents with
>> interfaces
>> > such as PVector, PSet, PMap, etc. and is a pretty good example of
>> something
>> > that others have hinted they'd like to see in the core Java library. To
>> > that end, I'd like for every type to have the option of providing a
>> builder
>> > (could we re-use Collector, as Remi hints at?). I know there's the
>> > possibility people will abuse this to make Java work like C++ but
>> honestly,
>> > I don't think there's much danger. Most people are pretty good at
>> following
>> > conventions, even if they're terrible (Java beans spring to mind).
>>
>> I just say that we give up to try to find a common interface for
>> injecting values for something more specific to stream.
>>
>
> I don't know much about this. What would be the problems with using
> collectors?
>
>
>>
>> >
>> > Finally, I think it's pretty clear that we need two distinct styles: one
>> > for list-like collections and one for map-like ones. I'm a pretty big fan
>> > of Groovy's `[a, b, c]` and `[a: 1, b: 2, c: 3]`. I don't think there's
>> an
>> > advantage to a specific syntax for sets because of the above.
>> >
>> > Cheers,
>> >
>> > — Samir.
>>
>> regards,
>> Rémi
>>
>
> And thanks again for humouring me. :-)
>
> — Samir.
>
>>
>> >
>> >
>> >
>> > On Wed, Jan 15, 2014 at 5:14 PM, Remi Forax <forax at univ-mlv.fr> wrote:
>> >
>> >> On 01/15/2014 06:04 PM, Per Bothner wrote:
>> >>> On 01/15/2014 03:44 AM, Zhong Yu wrote:
>> >>>> On Tue, Jan 14, 2014 at 7:17 PM, Per Bothner <per at bothner.com> wrote:
>> >>>>> For example, one could define:
>> >>>>>
>> >>>>> T v = { e1, ..., en}
>> >>>>>
>> >>>>> as syntactic sugar for:
>> >>>>>
>> >>>>> TB tmp = T.make_builder();
>> >>>>> tmp.add(e1); ..; tmp.add(en);
>> >>>>> T v = tmp.build();
>> >>>> How is this any better than
>> >>>>
>> >>>> T.of(e1, ..., en);
>> >>>>
>> >>>> ? I don't see how the literal syntax helps code writers or code
>> >>>> readers in this case.
>> >>> I can think of two reasons:
>> >>>
>> >>> (1) Target-typing means you don't have to redundantly specify T:
>> >>>
>> >>> T v = { e1, ..., en};
>> >>>
>> >>> vs
>> >>>
>> >>> T v = T.of(e1, ..., en);
>> >>>
>> >>> (2) Using the T.of form requires allocating an array,
>> >>> which is then thrown away.
>> >>>
>> >>> I don't think (2) is a major justification. (1) may not
>> >>> be enough to justify a new language feature by itself,
>> >>> though one could argue it's a natural extension of the
>> >>> existing syntax for arrays.
>> >> I disagree for (1), if you take a look to java.util.EnumSet by example,
>> >> you will see that there are multiple overloads of 'of' to avoid to
>> allocate
>> >> an array in the common cases.
>> >>
>> >> Rémi
>> >>
>> >>
>> >>
>> >>
>>
>>
>>
>
More information about the lambda-dev
mailing list