Re: JEP 186: Collection Literals
Timo Kinnunen
timo.kinnunen at gmail.com
Wed Jan 15 11:50:50 PST 2014
Hi,
Re: “Array literals (and, array types) are more of an oddity from today's
point of view; we should get rid of them if that were possible,
because their functions can be perfectly achieved with other general
purpose language devices.”
If it is at all possible, it’s possible through providing something that’s simpler and in all respects better than old arrays.
With one magical annotation, you could do:
@Retention(RetentionPolicy.SOURCE)
@interface SyntaxProvider {
@Retention(RetentionPolicy.SOURCE) @Target(ElementType.METHOD) @interface ArrayInitializer {}
@Retention(RetentionPolicy.SOURCE) @Target(ElementType.METHOD) @interface ArrayGetter {}
@Retention(RetentionPolicy.SOURCE) @Target(ElementType.METHOD) @interface ArraySetter {}
@Retention(RetentionPolicy.SOURCE) @Target(ElementType.METHOD) @interface ArrayLength {} }
Which allows:
interface ArraySyntaxProviderForMyClass {
// Allows: MyClass it = { myItem1, myItem2 };
@SyntaxProvider.ArrayInitializer
static MyClass containing(MyItem... items){
return new MyClass(Arrays.asList(items)); }
// Allows: MyItem there = it[100_000_000_000_000L];
@SyntaxProvider.ArrayGetter
static MyItem getAt(MyClass that, long index){
//TODO: Implement actual long indexing
return that.items.get((int) index); }
// Allows: MyItem another = it[1] = there;
@SyntaxProvider.ArraySetter
static MyItem setAt(MyClass that, long index, MyItem item){
that.items.set((int) index, item); return item; }
// Allows: long items = it.length;
@SyntaxProvider.ArrayLength
static long getLengthOfMyClass(MyClass it){
return it.items.size(); }
This covers most of the usual array stuffs already. Lists, ArrayLists are doable. Add interleaved varargs at compile-time and that covers Maps and JSON:
// Allows: MyClass it = { "one", new MyItem(1), "two", new MyItem(2) };
@SyntaxProvider.ArrayInitializer
static MyClass createdFrom(String[] keys, MyItem... items){
MyClass myClass = new MyClass(Arrays.asList(items));
for(int i = 0, n = keys.length; i < n; i++) {
myClass.index.put(keys[i], items[i]);
}
return myClass; }
Faking array[. . .] syntax by making it mean the same as calling somestaticmethod(array, . . .) covers indexing with multiple axis in one call, allowing sparse tables and continuous multi-dimensional arrays:
// Allows: MyItem item = myClass["clubs", 10];
@SyntaxProvider.ArrayGetter
static MyItem getAt(MyClass that, String id, int subId){
return that.items.get(subId).index.get(id); }
// Allows: MyItem old = myClass["clubs", 10] = new MyItem(5);
@SyntaxProvider.ArraySetter
static MyItem setAt(MyClass that, String id, int subId, MyItem item) {
return that.items.get(subId).index.put(id, item); // returns old item, if any, unlike arrays
} }
class MyItem extends MyClass { int value;
public MyItem(int i) {
super(new ArrayList<>());
this.value=i; } }
class MyClass implements ArraySyntaxProviderForMyClass {
List<MyItem> items;
Map<String, MyItem> index = new HashMap<>();
public MyClass(List<MyItem> asList) { this.items=asList; } }
If some of the array syntax is to be reused, better reuse all of it to leave no doubt.
Is this the least expansive way of covering all of these cases or is there some other way that has an even smaller impact or footprint?
--
Have a nice day,
Timo.
Sent from Windows Mail
From: Zhong Yu
Sent: Wednesday, January 15, 2014 21:19
To: Per Bothner
Cc: lambda-dev at openjdk.java.net
On Wed, Jan 15, 2014 at 11:04 AM, Per Bothner <per at bothner.com> 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.
There is no need for array literals; method+vararg is just fine
String[] strings = array("a", "b", "c");
(of course this requires generics/vararg which java1.0 didn't have.)
Array literals (and, array types) are more of an oddity from today's
point of view; we should get rid of them if that were possible,
because their functions can be perfectly achieved with other general
purpose language devices.
List literals, or T literals in your example, have equally little
value. It creates a new burden for programmers - they now have two
very similar ways to do the same thing, and they have to waste their
brain power to make a choice. Two camps will emerge fighting each
other over whose syntax is better.
Zhong Yu
>
> --
> --Per Bothner
> per at bothner.com http://per.bothner.com/
More information about the lambda-dev
mailing list