[
https://issues.apache.org/jira/browse/GROOVY-11964?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18076319#comment-18076319
]
ASF GitHub Bot commented on GROOVY-11964:
-----------------------------------------
blackdrag commented on code in PR #2489:
URL: https://github.com/apache/groovy/pull/2489#discussion_r3143307569
##########
src/test/groovy/gls/statements/MultipleAssignmentDeclarationTest.groovy:
##########
@@ -226,4 +226,1326 @@ final class MultipleAssignmentDeclarationTest {
assert baz == 'baz'
'''
}
+
+ // GEP-20 tail-rest tests
+
+ @Test
+ void testTailRestFromList() {
+ assertScript '''
+ def (h, *t) = [1, 2, 3, 4]
+ assert h == 1
+ assert t == [2, 3, 4]
+ '''
+ }
+
+ @Test
+ void testTailRestWithMultipleHeads() {
+ assertScript '''
+ def (a, b, *rest) = [10, 20, 30, 40, 50]
+ assert a == 10
+ assert b == 20
+ assert rest == [30, 40, 50]
+ '''
+ }
+
+ @Test
+ void testTailRestWithTypedHead() {
+ assertScript '''
+ def (int h, *t) = [1, 2, 3]
+ assert h == 1
+ assert h instanceof Integer
+ assert t == [2, 3]
+ '''
+ }
+
+ @Test
+ void testTailRestFromEmptyList() {
+ assertScript '''
+ def (h, *t) = []
+ assert h == null
+ assert t == []
+ '''
+ }
+
+ @Test
+ void testTailRestFromString() {
+ assertScript '''
+ def (c, *cs) = "hello"
+ assert c == 'h'
+ assert cs == "ello"
+ '''
+ }
+
+ @Test
+ void testTailRestFromIterator() {
+ assertScript '''
+ def (h, t) = [1, 2, 3].iterator() // baseline: same iterator
semantics as existing
+ assert h == 1
+ assert t == 2
+
+ // tail-rest binds the advanced iterator (Path B)
+ def it = [10, 20, 30].iterator()
+ def (head, *tail) = it
+ assert head == 10
+ assert tail instanceof Iterator
+ assert tail.next() == 20
+ assert tail.next() == 30
+ assert !tail.hasNext()
+ '''
+ }
+
+ @Test
+ void testTailRestFromSet() {
+ assertScript '''
+ def s = new LinkedHashSet<>([7, 8, 9])
+ def (sh, *st) = s
+ assert sh == 7
+ def remaining = []
+ while (st.hasNext()) remaining << st.next()
+ assert remaining == [8, 9]
+ '''
+ }
+
+ @Test
+ void testTailRestFromStream() {
+ assertScript '''import java.util.stream.Stream
+ def (first, *rest) = Stream.of('a', 'b', 'c')
+ assert first == 'a'
+ assert rest instanceof Iterator
Review Comment:
To explain a bit more my way of thinking... What if the stream is
"endless" or just "big" (data does not fit in memory)? For example a
generator of some kind, or a stream representing a giant file, or... We could
do an iterator that wraps the stream and then works one take(1) base I
guess, but in a,*b we never return the iterator, but but a list or something
alike for b. Of course I am aware that everything falls apart for a,*b,c Here
b cannot be the original stream, for this to work it cannot be an endless
stream either. Or even a stream that produces more data, that fits in memory.
> Additional multi-assignment forms
> ---------------------------------
>
> Key: GROOVY-11964
> URL: https://issues.apache.org/jira/browse/GROOVY-11964
> Project: Groovy
> Issue Type: Improvement
> Reporter: Paul King
> Priority: Major
>
> Three idioms are common in modern languages but unavailable in Groovy:
> * Tail rest binding: {{def (h, *t) = list}} - separate the head from the
> remainder. Common in functional code (recursive list traversal,
> pipeline-style processing of streams and iterators).
> * Map-style destructuring: {{def (name: n, age: a) = person}} - extract named
> properties or map keys directly, without intermediate variables.
> * Rest in non-tail positions: {{def (*f, last) = list, def (l, *m, r) =
> list}} - useful when the boundaries are at the ends rather than the middle.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)