Indexing access for Lists and Maps considered harmful?

Lawrence Kesteloot lk at teamten.com
Tue Jun 23 22:26:54 PDT 2009


Reinier,

I don't buy the argument that the compile error makes returning void
acceptable. Programmers won't realize that the construct "a[b] = c"
isn't a real assignment and won't understand why they get a cryptic
error when they write:

    do {
        x = read();
    } while ((list[i++] = x) != terminatingValue);

They'll fight with it for a while before deciding that Java is just
mysteriously inconsistent. This consideration, in my opinion, trumps
arguments about library implementation elegance or efficiency.

Besides, if the code is indeed a hot spot, the process of inlining
will recognize the needless handling of the old value and remove it.
(If it's not a hot spot then it's doesn't matter.)

Neal's argument about the ability to return an "equivalent" object is
valid. Something has to give, that I would pick that. It's reasonable
in nearly all cases to just return the RHS object.

Lawrence


On Tue, Jun 23, 2009 at 9:38 PM, Reinier
Zwitserloot<reinier at zwitserloot.com> wrote:
> It's not just a matter of figuring out "what interfaces we need to
> make this work" - at least, with Neal's semantics. I'm making the
> assumption that "a[x] = b" should be legal where x is an integer, a is
> a java.util.List<T>, and b is a T. That's obvious - that's the goal of
> this proposal in the first place. Neal's semantics and the way
> java.util.List is designed makes it impossible to address this issue
> by way of an interface. You'd need to hardcode the meaning of a[b] = c
> for at least java.util.List, if you want Neal's semantics.
>
> At the same time, Neal's semantics, while almost impossible to
> implement, are essentially correct, in that they are the most
> compatible of all the various proposals with how pass-through
> assignment works today in java6.
>
> Conclusion: I think we need to move away from being 100% consistent in
> an area (pass-through assignment) that almost nobody uses. It's not
> worth either complicating the proposal or delaying it, just to get to
> this mythical 100% consistency, especially considering that we can
> always add it later if we roll with 'a[b] = c is not an expression but
> a statement, when it involves SetIndex desugaring' now.
>
>
>  --Reinier Zwitserloot
>
>
>
> On 2009/24/06, at 05:40, Joshua Bloch wrote:
>
>> Reinier,
>>
>> I don't really understand your post.  What's wrong with just
>> agreeing at the outset that a[i] = b[i] = x; works, and then
>> figuring out what (if any) interfaces we need to make it work?
>>
>>          Josh
>>
>> On Tue, Jun 23, 2009 at 6:39 PM, Reinier Zwitserloot <reinier at zwitserloot.com
>> > wrote:
>> I agree to the theory of your post, but, so what?
>>
>> Java is not going to be perfect unless java is willing to sacrifice
>> backwards compatibility, which it isn't. So, perfection can't be the
>> goal - because if it is, then no language change is ever going to make
>> it in, and paradoxically, that really brings java no closer to
>> perfection.
>>
>> So - so what that it isn't perfect? Let's roll with where I think you
>> are trying to go, and create 2 interfaces, where the SetIndex
>> semantics are defined as requiring the implementing class to return
>> the logical value - e.g. boxing a primitive when assigning it into a
>> list, for example.
>>
>> But now we can't retrofit java.util.List without breaking thousands of
>> List implementations out there, so the conclusion would have to be
>> that you can not use a List itself; you must use either a specific
>> type (such as ArrayList, retrofitted to implement SetIndex), or a
>> newly created List2 interface that also implements SetIndex. In this
>> scenario, I'm assuming the name of the method isn't set(), as that
>> would conflict with java.util.List's set which has different
>> semantics.
>>
>> So, riddle me this then. There are 3 java7 scenarios:
>>
>> In the first scenario, m[a] = m[b] = c; does what you want, but only
>> if m is an ArrayList, SetIndex, or HashMap. It just doesn't work if m
>> is a List or Map type. Even for just "m[b] = c", which I'll bet is
>> more prevalent than m[a] = m[b] = c by a factor of 100 or more!
>>
>> In the second scenario, m[a] = m[b] = c does not do what you want (and
>> in my opinion, should express this by failing fast - generating a
>> compiler error on the spot stating that m[b] = c is not an expression,
>> but that's not relevant to the point I'm trying to make here) - but it
>> works with every type you'd expect it to work with: List, Map, arrays,
>> and many other types of objects.
>>
>> In the third scenario, m[a] = c isn't allowed at all.
>>
>> In the fourth scenario, java complicates the process quite a bit e.g.
>> by having a scala-esque conversion semantic where some class in the
>> classpath has registered itself as capable of turning any
>> java.util.List into a java.lang.SetIndex object. m[a] = m[b] =c does
>> what you want, and it works with List, but now the proposal is rather
>> complicated.
>>
>> I'm quite certain the (vast?) majority will go with the second java7.
>> If pass-through assignment was more common than it is, it might be
>> worth investigating the fourth scenario more thoroughly,
>>
>> NB: I'd hereby like to repeat my suggestion to choose pragmatism over
>> perfection here: Returning void is pragmatic, in that we can always
>> change it later without breaking any code. In this case, the pragmatic
>> choice may have to be to define explicitly SetIndex behaviour as
>> existing for java.util.List and java.util.Map and no other types of
>> objects (hard code the types, at least for now - no need to do this to
>> GetIndex, as there are no issues there). If these things are sorted
>> out in the future, then the restriction can be waived, and any code
>> can use it. It may not be /pretty/, but it has the crucial advantage
>> of being future-compatible!
>>
>>  --Reinier Zwitserloot
>>
>>
>>
>> On 2009/24/06, at 02:47, Neal Gafter wrote:
>>
>> > These methods are language-support methods.  If I create a new
>> array-
>> > like
>> > API, what should its "put" method return?  Four choices are void,
>> > null, the
>> > input value, or the logical value placed into the data structure.
>> >
>> > void doesn't work because that's not the return type of the method
>> > in these
>> > interfaces.
>> >
>> > null is silly (an API method that should always return nothing
>> > should be
>> > declared void), and conflicts with the JLS's meaning of an
>> assignment
>> > expression (see below).
>> >
>> > The input value isn't correct; the value resulting from the
>> > assignment is
>> > supposed to be the NEW value in that variable (JLS3 15.26 paragraph
>> > 3).  For
>> > built-in arrays, that is the value converted to the array element
>> > type.
>> >
>> > For general collection-like APIs, the result of an assignment using
>> > the
>> > array syntax may be some other "equivalent" value (for example,
>> > strings
>> > might be interned).  To support the JLS semantics, the API needs to
>> > have an
>> > opportunity to yield this value.  So IndexedAccess<V>.put() should
>> be
>> > declared to return a value of type V, which should be specified to
>> > be *the
>> > value of the logical variable after the assignment has occurred*.
>> > java.util.List, on the other hand, has a put method that is declared
>> > with
>> > the right signature (it returns a V), but it returns the wrong value
>> > to
>> > support the JLS semantics for assignment.
>> >
>> > Retrofitting interfaces onto existing classes is a poor solution to
>> > this
>> > language-design problem.
>> >
>> > Regards,
>> > Neal
>> >
>> > On Tue, Jun 23, 2009 at 4:35 PM, Shams Mahmood <shams.mahmood at gmail.com
>> > >wrote:
>> >
>> >> I don't follow why it won't handle anything other than the
>> >> collections api.
>> >> The compiler should be able to support any implementations of
>> >> IndexedAccess<V> and DictionaryAccess<K, V> just like the for each
>> >> loop
>> >> handles any implementations of the Iterable interface.
>> >>
>> >>
>> >>
>> >> ------------------------------
>> >> *From:* Neal Gafter <neal at gafter.com>
>> >> *To:* Shams Mahmood <shams.mahmood at gmail.com>
>> >> *Cc:* coin-dev at openjdk.java.net
>> >> *Sent:* Tuesday, June 23, 2009 4:42:40 PM
>> >> *Subject:* Re: Indexing access for Lists and Maps considered
>> harmful?
>> >>
>> >> On Tue, Jun 23, 2009 at 1:55 PM, Shams Mahmood <shams.mahmood at gmail.com
>> >> >wrote:
>> >>
>> >>> So,
>> >>> List<String> list = new ArrayList();
>> >>> list[1] = list[0] = "value";
>> >>> would get translated to:
>> >>> Collections.set(list, 1, Collections.set(list, 0, "value"))
>> >>
>> >>
>> >> The link to methods in Collections is a bit too magical (e.g. it
>> >> won't
>> >> gracefully handle anything other than the collections API nor
>> will it
>> >> gracefully support evolution of the platform).
>> >>
>> >>
>> >>
>> >
>>
>>
>>
>
>
>



More information about the coin-dev mailing list