Primitives in Generics
Neal Gafter
neal at gafter.com
Thu Jul 8 14:49:29 PDT 2010
ParallelArray is really the *only* well-known example of the kind of
aggregate operations API that project lambda is intended to enable. If
project lambda can't do a good job there, it is hard to see how we can
consider it to have fulfilled its design criteria.
On Thu, Jul 8, 2010 at 2:42 PM, Brian Goetz <brian.goetz at oracle.com> wrote:
> Its worth noting that ParallelArray is really the *only* well-known bad
> case
> here. Given the invasiveness to the language that function types
> represent,
> it seems a bad trade to take on such a big solution for a single
> ill-behaved
> library that some mad professor cooked up :) :) :)
> ^ Lots of smileys here!
>
>
>
> On 7/8/2010 9:48 AM, Reinier Zwitserloot wrote:
> > It's quite relevant, because state-of-the-lambda suffers from a rather
> > serious problem, which is highlighted by a core use-case driving project
> > lambda: ParallelArray's Ops container with its 132 SAM types. This
> proposal
> > would solve the issue and reduce that set of 132 to 8.
> >
> > If a JVM optimization can be proven to be trivial to implement (JRockit),
> > and fail to apply only in those cases where specialization wouldn't work
> > either, then I don't see how relying on this optimization is not
> sufficient.
> >
> > Your idea is an intriguing one which would indeed drop the need for the
> > JRockit boxing elimination optimization, though I don't think it can
> work.
> > For example, the following 2 code samples would seem to be perfectly
> valid,
> > but as far as I can tell the end result will be a NoSuchMethodError
> because
> > the produced instance will not actually have the primitive version of the
> > method. How will the compiler stop you from doing this, and, even if it
> > does, how is a java programmer to know these snippets won't work?
> >
> > Snippet #1: new ArrayList<int>().add(10);
> >
> > and to show this problem cannot be remedied just by detecting such
> > situations and disallowing them:
> >
> > Snippet #2:
> >
> > public static List<T> createList(Class<T> type) { return new
> ArrayList<T>();
> > }
> >
> > public void test() {
> > List<int> list = createList(int.class);
> > list.add(10);
> > }
> >
> >
> > --Reinier Zwitserloot
> >
> >
> >
> > On Thu, Jul 8, 2010 at 9:42 AM, Gernot Neppert<mcnepp02 at googlemail.com
> >wrote:
> >
> >> Reinier, I think your proposal is propably off-topic with regards to
> >> this mailing list, nevertheless I could not resist to respond ;-)
> >>
> >> I like the idea of making efficient use of generic classes with
> >> primitive type parameters possible. However, I'm worried that solely
> >> relying on a JVM optimization will not be sufficient. Wouldn't it be
> >> possible to gain efficiency on every VM if something along the
> >> following could be adopted:
> >>
> >> 1. Let's assume the existence of a generic interface
> >>
> >> L<T> {
> >> void add(T element);
> >> T get(int index);
> >> }
> >>
> >> 2. The declaration of a variable of type L<p> where p is one of the 8
> >> primitive types is possible.
> >> If the compiler encounters such a variable, it assumes that L<p>
> >> actually is equivalent to following 'extended' interface
> >>
> >> L'<P>
> >> {
> >> void add(P element);
> >> void add(p element);
> >> P get(int index);
> >> p get(int index);
> >> }
> >>
> >> where 'P' is the wrapper type corresponding to 'p'.
> >>
> >> 3. It would still remain illegal to declare an interface such as the
> >> above 'by hand', since overriding by return type is illegal unless the
> >> return types are covariant. However, the VM can cope with such
> >> overrides; and the compiler will encounter no ambiguities, as
> >> paragraph 4. will show.
> >>
> >> 4. With the assumptions made above, the following code would compile
> >> to the most efficient bytecode, invoking the primitive versions of
> >> 'add' and 'get':
> >>
> >> L<int> list;
> >> list.add(42);
> >> int value = list.get(0);
> >>
> >>
> >> 5. There has to be a means of instantiating objects of type L<p>. With
> >> the assumption made in 2., the solution is the same as with other
> >> abstract classes:
> >>
> >> A non-abstract class that implements L<p> for a primitive type p must
> >> implement those methods from the synthetic L'<p> that use the
> >> primitive type p, while the compiler will generate the necessary
> >> bridge methods with the wrapper type P:
> >>
> >> public class IntList implements L<int>
> >> {
> >> public void add(int element)
> >> {
> >> // efficient int-based implementation
> >> }
> >>
> >>
> >> public int get(int index)
> >> {
> >> // efficient int-based implementation.
> >> }
> >>
> >> }
> >>
> >> 6. The types L<P> and L<p> will be assignment compatible in only one
> >> direction: It will be possible to assign an instance of type L<int> to
> >> L<Integer>, but not vice versa.
> >>
> >> L<Integer> list1 = new IntList(); // OK
> >> L<int> list2 = new ArrayList<Integer>(); // Will not compile
> >>
> >> 7. If the assignment from L<P> to L<p> is forced through an unsafe
> >> cast, the attempt to invoke a method of L<p> using the primitive type
> >> p will result in a java.lang.NoSuchMethodException at runtime. This is
> >> comparable to the ClassCastException that can be thrown arbitrarily
> >> when unsafe casts are involved.
> >>
> >> L<int> list = (List<int>)(List)new ArrayList<Integer>();
> >> list.add(42); // Will throw NoSuchMethodException.
> >>
> >
>
>
More information about the lambda-dev
mailing list