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
Sign Up
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
<h1>Blocks</h1> <p>We can embed a sequence of statements inside "try", called a "block". Defined variables are only visible within that block, not outside:</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 = 'good morning' try{ def b = 'greetings', c = 'nice day' //'def' keyword applies to both 'b' and 'c' assert a == 'good morning' assert b == 'greetings' } assert a == 'good morning' //println b //a compile error if uncommented: b not visible here </pre></td></tr></table> <p>Using the "def" keyword is optional because we are inside a script:</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 c = 5 assert c == 5 d = 6 assert d == 6 //def keyword optional because we're within a script context assert binding.variables.c == null assert binding.variables.d == 6 //when def not used, variable becomes part of binding.variables </pre></td></tr></table> <p>But variables without "def" are visible outside the block:</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> try{ h = 9 assert binding.variables.h == 9 } assert h == 9 assert binding.variables.h == 9 </pre></td></tr></table> <p>We can't define a variable (using "def") with the same name as another already visible (ie, another "in scope"):</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 = 'island' //def a = 'snake' //a compile error if uncommented: a already defined try{ //def a = 'jewel' //a compile error if uncommented: a already defined } </pre></td></tr></table> <p>We can nest blocks:</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 = 123 try{ try{ try{ assert a == 123 } } } </pre></td></tr></table> <h1>Closures</h1> <p>We can take a sequence of statements that refers to its external context and assign it to a variable, then execute it later. It's technically called a "closable block", commonly called a "closure":</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 = 'coffee' def c = { def b = 'tea' a + ' and ' + b //a refers to the variable a outside the closure, //and is remembered by the closure } assert c() == 'coffee and tea' //short for c.call() </pre></td></tr></table> <p>The closure assigned to the variable (here, c) will remember its context (here, including a) even if that context is not in scope when the closure is called:</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 c try{ def a = 'sugar' c = { a } //a closure always returns its only value } assert c() == 'sugar' def d = c //we can also assign the closure to another variable assert d() == 'sugar' </pre></td></tr></table> <p>A closure always returns a value, the result of its last statement:</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> giveSeven = { 7 } assert giveSeven() == 7 //value of last statement is returned giveNull = { def a } assert giveNull() == null //null returned if last statement has no value </pre></td></tr></table> <p>By putting a closure within another, we can create two instances of it:</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> c = { def e = { 'milk' }; e } d = c assert c == d v1 = c() v2 = c() assert v1 != v2 </pre></td></tr></table> <h3>Closure Parameters</h3> <p>We can put parameters at the beginning of a closure definition, and pass values in when we call the closure:</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 toTriple = {n -> n * 3} assert toTriple.call( 5 ) == 15 </pre></td></tr></table> <p>We can also pass information out using the parameters:</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 f = { list, value -> list << value } x = [] f(x, 1) f(x, 2,) //trailing comma in argument list OK f(x, 3) assert x == [1, 2, 3] </pre></td></tr></table> <p>One parameter is always available, called "it", if no explicit parameters are named:</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> c = { it*3 } assert c( 'run' ) == 'runrunrun' </pre></td></tr></table> <p>If parameters aren't specified, "it" will still be implicitly defined, but be 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> //c = { def it = 789 } //a compile error when uncommented: 'it' already implicitly defined c = { value1 -> def it = 789; [value1, it] } //works OK because no 'it' among parameters assert c( 456 ) == [456, 789] c = {-> def it = 789; it } //zero parameters, not even 'it', so works OK assert c() == 789 </pre></td></tr></table> <p>Parameters can't have the same name as another variable in scope, except for the implicit parameter 'it':</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= 'cup' //def c={ name-> println (name) } //a compile error when uncommented: //current scope already contains name 'name' c= { def d= { 2 * it }; 3 * d(it) } //'it' refers to immediately-surrounding closure's parameter in each case assert c(5) == 30 </pre></td></tr></table> <p>If there's already a variable called 'it' in scope, we can access it using owner.it:</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> it= 2 c= { assert it == 3; assert owner.it == 2 } c(3) </pre></td></tr></table> <p>We can pass one closure into another as a parameter:</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> toTriple = {n -> n * 3} runTwice = { a, c -> c( c(a) )} assert runTwice( 5, toTriple ) == 45 </pre></td></tr></table> <p>We can return a closure from another:</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 times= { x -> { y -> x * y }} assert times(3)(4) == 12 </pre></td></tr></table> <p>There's a shortcut syntax when explicitly defining a closure within another closure call, where that closure is the last or only parameter:</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 runTwice = { a, c -> c(c(a)) } assert runTwice( 5, {it * 3} ) == 45 //usual syntax assert runTwice( 5 ){it * 3} == 45 //when closure is last param, can put it after the param list def runTwiceAndConcat = { c -> c() + c() } assert runTwiceAndConcat( { 'plate' } ) == 'plateplate' //usual syntax assert runTwiceAndConcat(){ 'bowl' } == 'bowlbowl' //shortcut form assert runTwiceAndConcat{ 'mug' } == 'mugmug' //can skip parens altogether if closure is only param def runTwoClosures = { a, c1, c2 -> c1(c2(a)) } //when more than one closure as last params assert runTwoClosures( 5, {it*3}, {it*4} ) == 60 //usual syntax assert runTwoClosures( 5 ){it*3}{it*4} == 60 //shortcut form </pre></td></tr></table> <p>Arguments in a closure call can be named. They are interpreted as the keys in a map passed in as the first parameter:</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 f= {m, i, j-> i + j + m.x + m.y } assert f(6, x:4, y:3, 7) == 20 def g= {m, i, j, k, c-> c(i + j + k, m.x + m.y) } assert g(y:5, 1, 2, x:6, 3){a,b-> a * b } == 66 </pre></td></tr></table> <p>We can enquire the number of parameters for a closure, both from inside and outside the closure:</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> c= {x,y,z-> getMaximumNumberOfParameters() } assert c.getMaximumNumberOfParameters() == 3 assert c(4,5,6) == 3 </pre></td></tr></table> <p>A closure may have its last parameter/s assigned default value/s:</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 e = { a, b, c=3, d='a' -> "${a+b+c}$d" } assert e( 7, 4 ) == '14a' assert e( 9, 8, 7 ) == '24a' //override default value of 'c' </pre></td></tr></table> <p>A closure can take a varying number of arguments by prefixing its last parameter with Object[], and accessing them using 'each':</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 c = { arg, Object[] extras -> def list= [] list<< arg extras.each{ list<< it } list } assert c( 1 ) == [ 1 ] assert c( 1, 2 ) == [ 1, 2 ] assert c( 1, 2, 3 ) == [ 1, 2, 3 ] assert c( 1, 2, 3, 4 ) == [ 1, 2, 3, 4 ] </pre></td></tr></table> <p>We can also prefix the last parameter of a closure with Closure[] to pass in a varying number of other closures, even using the shortcut syntax:</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 apply = { a, Closure[] cc -> (cc as List).inject(a){ flo, it-> it(flo) } //apply the closures nestedly to the initial value } assert apply(7){it*3}{it+1}{it*2}.toString() == '44' </pre></td></tr></table> <p>When we call a closure with a list argument, if there's no closure defined with a list parameter, the arguments are passed in as separate parameters:</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 c= {a, b, c-> a + b + c} def list=[1,2,3] assert c(list) == 6 </pre></td></tr></table> <p>A closure may be copied with its first parameter/s fixed to a constant value/s, using curry:</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 concat = { p1, p2, p3 -> "$p1 $p2 $p3" } def concatAfterFly = concat.curry( 'fly' ) assert concatAfterFly( 'drive', 'cycle' ) == 'fly drive cycle' def concatAfterFlySwim = concatAfterFly.curry( 'swim' ) assert concatAfterFlySwim( 'walk' ) == 'fly swim walk' </pre></td></tr></table> <p>In closures, we can use currying and parameter-count-varying together:</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 c = { arg, Object[] extras -> arg + ', ' + extras.join(', ') } def d = c.curry( 1 ) //curry first param only assert d( 2, 3, 4 ) == '1, 2, 3, 4' def e = c.curry( 1, 3 ) //curry part of Object[] also assert e( 5 ) == '1, 3, 5' def f = e.curry( 5, 7, 9, 11 ) //currying continues on Object assert f( 13, 15 ) == '1, 3, 5, 7, 9, 11, 13, 15' </pre></td></tr></table> <p>We can make closures recursive:</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 gcd //predefine closure name gcd={ m,n-> m%n==0? n: gcd(n,m%n) } assert gcd( 28, 35 ) == 7 </pre></td></tr></table> <p>We can even make a recursion of anonymous closures (thanks to 'call' method available for each closure)</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 results = []; { a, b -> results << a a<10 && call(b, a+b) }(1,1) assert results == [1, 1, 2, 3, 5, 8, 13] // Fibonacci numbers </pre></td></tr></table> <h1>Functions</h1> <p>A function is similar to a closure, though a function can't access defined variables in its surrounding context:</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 = 32 //def keyword not used for this one def c = 'there', d = 'yonder' def f(){ assert a == 32 //outer 'a' visible because 'def' keyword wasn't used with it def c = 'here' //compiles OK because other defined c invisible inside function definition //println d //a compile error when uncommented: d not accessable c } assert f() == 'here' //syntax to invoke a function </pre></td></tr></table> <p>The def keyword is compulsory when defining functions:</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 f(){ a = 1 c = { 'here, again' } c() } assert f() == 'here, again' //g(){ println 'there, again' } //a compile error when uncommented: def keyword required </pre></td></tr></table> <p>We use a special syntax to assign a function to another variable when using the original definition name:</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 f(){ 77 } //define function using name 'f' assert f() == 77 def g = this.&f //special syntax to assign function to another variable assert g() == 77 def h = g //don't use special syntax here assert h() == 77 f = 'something else' //this 'f' is a VARIABLE, not the function NAME assert f() == 77 //the function name can't be reassigned </pre></td></tr></table> <p>Unlike blocks and closures, we can't nest functions:</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 f(){ //def g1(){ println 'there' } //a compile error when uncommented: can't nest functions 'here' } assert f() == 'here' try{ //def g2(){ println 'yonder' } //a compile error when uncommented: can't nest functions } c = { //def g3(){ println 'outer space' } //a compile error when uncommented: can't nest functions } def h(){ try{ def c = { 'here, again' } } //we can have blocks and closures within functions } </pre></td></tr></table> <h3>Function Parameters</h3> <p>A function can have parameters, with which we can pass information both in and out:</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 foo( list, value ){ list << value } x = [] foo(x, 1) foo(x, 2) assert x == [1, 2] </pre></td></tr></table> <p>We can have more than one function of the same name if they each have different numbers of (untyped) parameters.</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 foo(value){ 'v1' } def foo(list, value){ 'v2' } assert foo(9) == 'v1' assert foo([], 1) == 'v2' </pre></td></tr></table> <p>A function returns a value, unless prefixed by void instead of def, when it always returns 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 f1(){ 7 } assert f1() == 7 //value of last statement is returned def f2(){ return 8; 3 } assert f2() == 8 //return explicitly using return void f3(){ 10 } assert f3() == null //null always returned //void f4(){ return 9 } //a compile error when uncommented: can't use 'return' in a void function </pre></td></tr></table> <p>When there's a method and closure with the same name and parameters, the method is chosen instead of the closure:</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 c(){'method c'} def c= {-> 'closure c'} assert c() == 'method c' def d(i){'method d'} def d= {'closure d'} assert d(9) == 'method d' </pre></td></tr></table> <h3>Some Similarities with Closures</h3> <p>We can use the shortcut invocation syntax for closure parameters:</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 f(Closure c){ c() } assert f{ 'heehee' } == 'heehee' </pre></td></tr></table> <p>A function may have its last parameter/s assigned default value/s:</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 dd( a, b=2 ){ "$a, $b" } assert dd( 7, 4 ) == '7, 4' assert dd( 9 ) == '9, 2' </pre></td></tr></table> <p>Arguments in a function call can be named, interpreted as keys in a map passed in as first parameter:</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 f(m, i, j){ i + j + m.x + m.y } assert f(6, x:4, y:3, 7) == 20 def g(m, i, j, k, c){ c(i + j + k, m.x + m.y) } assert g(y:5, 1, 2, x:6, 3){a,b-> a * b } == 66 </pre></td></tr></table> <p>A function can take a varying number of arguments by prefixing its last argument by Object[], and accessing them using each:</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 c( arg, Object[] extras ){ def list= [] list<< arg extras.each{ list<< it } list } assert c( 1 ) == [ 1 ] assert c( 1, 2, 3, 4 ) == [ 1, 2, 3, 4 ] </pre></td></tr></table> <p>When we call a function with a list argument, if there's none defined with a list parameter, the arguments are passed in separately:</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 x(a, b, c){a + b + c} def list=[1,2,3] assert x(list) == 6 </pre></td></tr></table> <p>We can call a function recursively by referencing its own name:</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 gcd( m, n ){ if( m%n == 0 )return n; gcd(n,m%n) } assert gcd( 28, 35 ) == 7 </pre></td></tr></table>
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