[
https://issues.apache.org/jira/browse/GROOVY-10666?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17573023#comment-17573023
]
Eric Milles edited comment on GROOVY-10666 at 7/29/22 3:10 PM:
---------------------------------------------------------------
Here is an idea that leverages dynamic "iterator()" and still supports
"getAt(int)" for the few types that still require it (Calendar, others?).
Translate "def (a,b,c) = rhs" into (pseudo-code):
{code:java}
Iterator it = rhs.iterator();
Object first = it.next();
def a, b, c;
if (first != rhs) { // does "rhs" present itself as the element?
a = first;
b = it.next();
c = it.next();
} else { // old path
a = rhs.getAt(0);
b = rhs.getAt(1);
c = rhs.getAt(2);
}
{code}
The downside is that the iterator and getAt paths must both be written into the
bytecode. The upside is that many, many iterable types and iterator itself
will be used efficiently. This would only be a breaking change for a type that
implements both {{iterator()}} and {{getAt(int)}} in an incongruent manner. My
gut says this is few if any types.
was (Author: emilles):
Here is an idea that leverages dynamic "iterator()" and still supports
"getAt(int)" for the few types that still require it (Calendar, others?):
Translate "def (a,b,c) = rhs" into (pseudo-code):
{code:java}
Iterator it = rhs.iterator();
Object first = it.next();
def a, b, c;
if (first != rhs) { // does "rhs" present itself as the element?
a = first;
b = it.next();
c = it.next();
} else { // old path
a = rhs.getAt(0);
b = rhs.getAt(1);
c = rhs.getAt(2);
}
{code}
The downside is that the iterator and getAt paths must both be written into the
bytecode. The upside is that many, many iterable types and iterator itself
will be used efficiently. This would only be a breaking change for a type that
implements both {{iterator()}} and {{getAt(int)}} in an incongruent manner. My
gut says this is few if any types.
> Implement multiple-assignment (aka destructuring) via getAt(IntRange) or
> iterator()
> -----------------------------------------------------------------------------------
>
> Key: GROOVY-10666
> URL: https://issues.apache.org/jira/browse/GROOVY-10666
> Project: Groovy
> Issue Type: Improvement
> Components: bytecode, groovy-jdk
> Reporter: Eric Milles
> Assignee: Eric Milles
> Priority: Minor
>
> Currently multiple-assignment is implemented using {{getAt(int)}}. For types
> that support {{getAt(IntRange)}} it may be more efficient to use that
> operation. For cases where {{getAt(int)}} is a terminal operation (aka
> streams) it may be the only way to go. Or maybe using one {{iterator()}}
> would be better overall.
> Consider the following:
> {code:groovy}
> Set<String> set = ['foo','bar','baz']
> def (foo, bar, baz) = set // inefficient; requires 3 iterators and 6 calls to
> next
> Stream<String> stream = ['foo','bar','baz'].stream()
> def (foo, bar, baz) = stream // not possible because `getAt(int)` is terminal
> {code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)