Skip to content
Skip to breadcrumbs
Skip to header menu
Skip to action menu
Skip to quick search
Quick Search
Browse
Pages
Blog
Labels
Attachments
Mail
Advanced
What’s New
Space Directory
Feed Builder
Keyboard Shortcuts
Confluence Gadgets
Log In
Dashboard
Groovy
Copy Page
You are not logged in. Any changes you make will be marked as
anonymous
. You may want to
Log In
if you already have an account. You can also
Sign Up
for a new account.
This page is being edited by
.
Paragraph
Paragraph
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Preformatted
Quote
Bold
Italic
Underline
More colours
Strikethrough
Subscript
Superscript
Monospace
Clear Formatting
Bullet list
Numbered list
Outdent
Indent
Align left
Align center
Align right
Link
Table
Insert
Insert Content
Image
Link
Attachment
Symbol
Emoticon
Wiki Markup
Horizontal rule
tinymce.confluence.insert_menu.macro_desc
Info
JIRA Issue
Status
Gallery
Tasklist
Table of Contents
Other Macros
Page Layout
No Layout
Two column (simple)
Two column (simple, left sidebar)
Two column (simple, right sidebar)
Three column (simple)
Two column
Two column (left sidebar)
Two column (right sidebar)
Three column
Three column (left and right sidebars)
Undo
Redo
Find/Replace
Keyboard Shortcuts Help
<table class="wysiwyg-macro" data-macro-name="note" data-macro-parameters="title=Superceded" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e25vdGU6dGl0bGU9U3VwZXJjZWRlZH0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="RICH_TEXT"><tr><td class="wysiwyg-macro-body"> <p>Note that an initial implementation of multiple assignment is already built in to Groovy 1.6 and above. This document is kept for historical purposes and because it contains suggestions for advanced features not yet implemented. See <a class="confluence-link" href="/display/GROOVY/Multiple+Assignment" data-linked-resource-id="122749175" data-linked-resource-type="page" data-linked-resource-default-alias="Multiple Assignment" data-base-url="http://docs.codehaus.org">Multiple Assignment</a> for more details of the current implementation.</p></td></tr></table> <h3>Introduction</h3> <p>This page looks at proposed changes to the Groovy language to support multiple assignment. Such support would allow for code such as:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> a, b = b, a // will transparently handle any temporary storage list = [1, 2, 3] def (c, d, e) = list assert c == 1 && d == 2 && e == 3 </pre></td></tr></table> <p>It is meant to be a discussion document, not a formal definition, we will work out the impact on the grammar etc. once we clarify our intention.</p> <h3>Single Assignment</h3> <p>Some existing declarations involving single assigment:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def a = 'a' // for examples below def b = 'b' // for examples below def c = 'c' // for examples below //------ Existing: Java style, simple case (Proposal leaves unchanged) def x1,y1,z1 = a // only z1 is equal to a, the others are undefined assert x1 == null assert y1 == null assert z1 == a //------ Existing: Java style, list case (Proposal leaves unchanged) def x2, y2, z2 = [a,b,c] // only z2 is equal to [a,b,c], the others are undefined assert x2 == null assert y2 == null assert z2 == [a,b,c] //------- Existing: Java style, multiple equals case (Proposal leaves unchanged) def x3 = a, y3 = b, z3 = c // obvious assert x6 == a assert y3 == b assert z3 == c //------- Existing: Java Java style, multiple lists case (Proposal leaves unchanged) def x4 = [a,b], y4 = [b,c], z4 = [a,c] // obvious assert x4 == [a,b] assert y4 == [b,c] assert z4 == [a,c] </pre></td></tr></table> <h3>Variable declarations</h3> <p>In order to not conflict with existing definitions, any variable declaration which wishes to make use of multiple assignments must surround the '<em>tuple</em>' of variable declarations in round brackets. Whenever such a round bracket is found, the compiler will match the tuple with a list. The list will be expected to be where it would be in the case of single assignment. The compiler will '<em>unpack</em>' the list into the tuple of variables.</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def (x5,y5,z5) = [a,b,c] // common type goes before round brackets def (x6,y6) = [a,b], z6 = c // x,y,z/5,6,7 must all be undefined def list = [b, c] def x7 = a, (y7, z7) = list // list can be explicit or implicit assert x5 == a && x6 == a && x7 == a assert y5 == b && y6 == b && y7 == b assert z5 == c && z6 == c && z7 == c </pre></td></tr></table> <p>Nested variations are also supported (this may be deferred initially):</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def ((x8,y8),z8) = [[a,b],c] assert x8 == a && y8 == b && z8 == c </pre></td></tr></table> <p>Differing sized tuples and lists are catered for by ignoring extra list members and leaving any untargeted variables in the tuple set to null:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def (x9,y9,z9) = [a,b] assert x9 == a && y9 == b && z9 == null def (x10,y10,z10) = [a,b,c,d] // d unused assert x10 == a && y10 == b && z10 == c </pre></td></tr></table> <p>There can be at most one [at the end like varargs?] 'tuple spread' operator which takes the rest of the list:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def (first11,*rest11) = [a,b,c,d] assert first11 == a assert rest11 == [b, c, d] </pre></td></tr></table> <p>Setting a bunch of variables to the same (or related) values is accomplished using normal list conventions:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def (x12,y12,z12) = [a] * 3 assert [x12, y12, z12] == [a, a, a] def (x13,y13,z13) = 0..2 assert [x13, y13, z13] == [0, 1, 2] def string = 'abcdefghi' def (x14,y14,z14) = (1..3).collect{ string[0..it*2]} assert [x14, y14, z14] = ["abc", "abcde", "abcdefg"] </pre></td></tr></table> <p>The tuple list is strictly a list (apart from the nesting seen earlier) and may not contain assignments itself:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> // INVALID def (x15 = c, y15, z15) = [a,b,c] </pre></td></tr></table> <p>Example involving nulls:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def (x16,y16,z16) assert x16 == null assert y16 == null assert z16 == null </pre></td></tr></table> <p>Examples involving real world use:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def (name, address1, address2, postcode) = myData.tokenize("\n").toList() // acts like first/head/top def (name) = myData.tokenize("\n").toList() // equivalent to above but 'self documenting' def (name, *ignored) = myData.tokenize("\n").toList() </pre></td></tr></table> <h3>Use in Expressions</h3> <p>The left hand side (LHS) of an expression involving the simple assignment operator, <code>=</code>, can be replaced with a tuple. In this case, the variables will be predefined or binding variables and the result of the RHS of the expression will be a (possibly coerced) list which will be unpacked into the tuple.</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def list = [a, b] def x17, y17 (x17, y17) = list assert [x17, y17] == [a, b] </pre></td></tr></table> <p>Where it is not ambiguous, the round brackets can be removed from the tuple list when used in such expressions, so the above could be written as:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> x17, y17 = list // LHS turned into (x17, y17) </pre></td></tr></table> <p>If the right hand side after any assignment operator contains a comma separated list of subexpressions, they will be assumed to make up a list (i.e. automatically turned into a list), so the above could be written as:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> x17, y17 = a, b // RHS turned into [a, b] </pre></td></tr></table> <p>[Note: the above probably requires lots of pouring over the grammar!]</p> <p>If you find you need a tuple with different typed items inside, use an expression form rather than the variable declaration form which requires the types to be the same, e.g.:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def myMonth(){ [2000, "Jan", 1] } String month int day, year (year, month, day) = myMonth() </pre></td></tr></table> <p>Unlike with declarations, the LHS doesn't need to simply be a variable:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def map = [a:1, b:2] (map.a, map.b) = [3, 4] assert map == [a:3, b:4] a = 10..15 i = 3 i, a[i] = i+1, 20 assert i == 4 && a[3] == 20 && a[4] == 14 </pre></td></tr></table> <p>Other examples which need to work:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> x = 0 a, b, c = x, (x += 1), (x += 1) assert [a, b, c] == [0, 1, 2] year, month, day = "2007-03-20".split('-') </pre></td></tr></table> <h3>Other assignment operators</h3> <p>These may not be implemented initially, but we attempt to define them here. It includes these:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> *= /= %= += -= <<= >>= >>>= &= ^= |= </pre></td></tr></table> <p>First, a tuple on the LHS of a special assignment operator:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> a, b *= 3 // form list [a, b] (tuple spread operator ignored here if present) // call multiply() operator with arg 3 // unpack result into (a, b) tuple (spread operator applies to unpacking) // example def x18 = a, y18 = b x18, *y18 *= 3 assert x18 = a assert y18 = [b, a, b, a, b] </pre></td></tr></table> <p>Now, an example with special treatment on the RHS:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> yourObject *= 1, 2 // calls the multiply() method on yourObject with the list [1, 2] </pre></td></tr></table> <p>As an alternative to the semantics described here, we could define '<code>a, b *= 3</code>' to be the same as '<code>a *= 3; b *= 3</code>'. This seems more useful but then if the semantics were to be consistent, then '<code>a, b = 3</code>' should mean '<code>a = 3; b = 3</code>'.</p> <h3>Use in Method declarations</h3> <p>No change, no grouping of method parameters is supported, i.e. the following is invalid:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> // INVALID def myMethod((a, b), c) { ... } </pre></td></tr></table> <h3>See Also</h3> <p><a href="http://jira.codehaus.org/browse/GROOVY-158">http://jira.codehaus.org/browse/GROOVY-158</a></p>
Please type the word appearing in the picture.
Attachments
Labels
Location
Watch this page
< Edit
Preview >
Loading…
Save
Cancel
Next hint
search
attachments
weblink
advanced