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
<p><a href="http://en.wikipedia.org/wiki/Functional_programming">Functional programming</a> is a style of programming that emphasizes the application of functions to solve computing problems. This is in contrast with imperative programming, which emphasizes changes in state and the execution of sequential commands. If you want use a functional-only programming language, you should consider something like <a href="http://www.haskell.org">Haskell</a>. If however you like Groovy but want to apply some functional style magic, read on.</p> <h2>Functional Basics</h2> <p>Groovy's functions (like Java's) can be used to define functions which contain no imperative steps, e.g. a factorial function may look like:</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 fac(n) { n == 0 ? 1 : n * fac(n - 1) } assert 24 == fac(4) </pre></td></tr></table> <p>In Groovy, we gain some slight syntactic sugar over Java in that we can leave out the <em><code>return</code></em> statements (the last evaluated expression is the default return value).</p> <p>You can also define the above factorial function using 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 fac2 = { n -> n == 0 ? 1 : n * call(n - 1) } assert 24 == fac2(4) </pre></td></tr></table> <p>As you can see from the last line, this Closure version gets called in the same way as the function version (although a long hand <code>fac2.call(4)</code> is also supported). The closure version has the advantage that we can pass the <code>fac2</code> Closure around (e.g. as a parameter) or place it within a data structure.</p> <p>We can also convert between functions and Closures, 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 fac3 = this.&fac assert 24 == fac3(4) </pre></td></tr></table> <p>The <code>fac3</code> variable will also be a closure.</p> <p>We can of course start to mix and match functional and imperative coding styles as in this quicksort-like example:</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 sort(list) { if (list.isEmpty()) return list anItem = list[0] def smallerItems = list.findAll{it < anItem} def equalItems = list.findAll{it == anItem} def largerItems = list.findAll{it > anItem} sort(smallerItems) + equalItems + sort(largerItems) } assert [1, 3, 4, 5] == sort([1, 4, 5, 3]) assert [1, 1, 3, 4, 4, 5, 8] == sort([4, 1, 4, 1, 8, 5, 3]) assert ['a', 'b', 'c'] == sort(['c', 'b', 'a']) </pre></td></tr></table> <h2>Curry functions</h2> <p>You can fix the values for one or more arguments to a closure instance using the curry() method as follows:</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 joinTwoWordsWithSymbol = { symbol, first, second -> first + symbol + second } assert joinTwoWordsWithSymbol('#', 'Hello', 'World') == 'Hello#World' def concatWords = joinTwoWordsWithSymbol.curry(' ') assert concatWords('Hello', 'World') == 'Hello World' def prependHello = concatWords.curry('Hello') // def prependHello = joinTwoWordsWithSymbol.curry(' ', 'Hello') assert prependHello('World') == 'Hello World' </pre></td></tr></table> <p>If you supply one argument to the <em>curry()</em> method you will fix the first argument. If you supply <em>N</em> arguments you will fix arguments <em>1..N</em>. See reference 1 or Chapter 5 of <a href="http://groovy.canoo.com/gina">GINA</a> for further details.</p> <h2>Lazy evaluation</h2> <p>One particular style of functional programming of particular merit is to make use of lazy evaluation. This allows you to define infinite structures (see the next section), devise particularly efficient solutions to certain kinds of problems, and come up with very elegant solutions to otherwise hard problems. The good news is that several parts of Groovy already make use of this style and they typically hide away the hard bits so you don't need to know what magic is happening on your behalf. Here's some examples:</p> <ul> <li><code>XmlSlurper</code> allows arbitrary GPath expressions to be crafted. As you create the expressions, you might think that XML parsing is going on behind the covers pulling XML nodes into and out of lists to match what your expressions are asking for. This is not the case. Instead a lazy representation of your GPath is stored away. When you need to evaluate the final result of a GPath expression, it calculates just what it needs to determine the expressions resulting value. [See chapter 12 of <a href="http://groovy.canoo.com/gina">GINA</a> for more information about XmlSlurper.]</li> <li>Groovy's <code>DataSet</code> feature does the some thing for data stored in relational databases. As you build up your dataset queries, no connections or operations to the database are happening under the covers. At the time when you need the result, an optimised query minimising SQL traffic is invoked to return the required result. [See section 10.2 of <a href="http://groovy.canoo.com/gina">GINA</a> for more information about DataSets.]</li> </ul> <h2>Infinite structures</h2> <p>See reference 2 below for all the details, but to give you a flavour, first you must define some lazy list handling functions, then you can define and use infinite streams. Here is an example:</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> // general purpose lazy list class class LazyList { def car private Closure cdr LazyList(def car, Closure cdr) { this.car=car; this.cdr=cdr } def LazyList getCdr() { cdr ? cdr.call() : null } def List take(n) { def r = []; def l = this n.times { r.add(l.car); l = l.cdr } r } def LazyList filter(Closure pred) { if (pred(car)) return pred.owner.cons(car, { getCdr().filter(pred) }) else return getCdr().filter(pred) } } // general purpose lazy list function def cons(val, Closure c) { new LazyList(val, c) } // now define and use infinite streams def integers(n) { cons(n, { integers(n+1) }) } def naturalnumbers = integers(1) assert '1 2 3 4 5 6 7 8 9 10' == naturalnumbers.take(10).join(' ') def evennumbers = naturalnumbers.filter{ it % 2 == 0 } assert '2 4 6 8 10 12 14 16 18 20' == evennumbers.take(10).join(' ') </pre></td></tr></table> <p>If you are not familiar with traditional functional programming terms like <code>cons</code>, <code>car</code> and <code>cdr</code>, you may find the refactored version below (creds to Alexander Kriegisch) somewhat more readable:</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> class LazyList { def head private Closure tail LazyList(def head, Closure tail) { this.head=head; this.tail=tail } def LazyList getTail() { tail ? tail.call() : null } def List getFirst(n) { def result = []; def current = this n.times { result.add(current.head); current = current.tail } result } def LazyList filter(Closure matchExpr) { if (matchExpr(head)) return matchExpr.owner.prepend(head, { getTail().filter(matchExpr) }) else return getTail().filter(matchExpr) } } // general purpose lazy list function def prepend(val, Closure c) { new LazyList(val, c) } // now define and use infinite streams def integers(n) { prepend(n, { integers(n+1) }) } def naturalnumbers = integers(1) assert '1 2 3 4 5 6 7 8 9 10' == naturalnumbers.getFirst(10).join(' ') def evennumbers = naturalnumbers.filter{ it % 2 == 0 } assert '2 4 6 8 10 12 14 16 18 20' == evennumbers.getFirst(10).join(' ') </pre></td></tr></table> <h2>Using Functional Java</h2> <p>You can also consider using Java libraries which support functional programming, e.g. using <a href="http://functionaljava.org/">Functional Java</a> for an example similar to the evens example above:</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> import fj.data.Stream // some metaprogramming to make fj mesh well with Groovy Stream.metaClass.filter = { Closure c -> delegate.filter(c as fj.F) } Stream.metaClass.getAt = { n -> delegate.index(n) } Stream.metaClass.getAt = { Range r -> r.collect{ delegate.index(it) } } Stream.metaClass.asList = { delegate.toCollection().asList() } def evens = Stream.range(0).filter{ it % 2 == 0 } assert evens.take(5).asList() == [0, 2, 4, 6, 8] assert (8..12).collect{ evens[it] } == [16, 18, 20, 22, 24] assert evens[3..6] == [6, 8, 10, 12] </pre></td></tr></table> <p>Or for something a little more adventurous, we can consider calculating primes:</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> import fj.data.Stream import static fj.data.Stream.cons // some metaprogramming to make Closures mesh well with fj functions and products Stream.metaClass.filterTail = { Closure c -> delegate.tail()._1().filter(c as fj.F) } Stream.metaClass.static.cons = { h, Closure c -> delegate.cons(h, ['_1':c] as fj.P1) } def sieve(nums) { cons nums.head(), { sieve nums.filterTail{ n -> n % nums.head() != 0 } } } println sieve(Stream.range(2)).index(100) // => 547 </pre></td></tr></table> <p>Remember to add <code>functionaljava.jar</code> to your classpath. You will need a version greater than version 2.8 of Functional Java.</p> <p>Another example:</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> @Grab('org.functionaljava:functionaljava:3.0') import static fj.data.Array.array import static fj.data.List.list import static fj.Show.* import fj.F arrayShow(intShow).println(array(1, 2, 3).map({ it + 42 } as F)) // => {43,44,45} assert array(1, 2, 3).map({ it + 42 } as F).toCollection().toList() == [43, 44, 45] assert [1, 2, 3].collect{ it + 42 } == [43, 44, 45] // native Groovy for comparison listShow(intShow).println(list(1, 2, 3).bind({ it % 2 ? list(it * 2) : list() } as F)) // => <2,6> assert list(1, 2, 3).bind({ it % 2 ? list(it * 2) : list() } as F).toCollection().toList() == [2, 6] assert [1, 2, 3].collect{ it % 2 ? [it * 2] : [] }.sum() == [2, 6] // native Groovy for comparison </pre></td></tr></table> <p>Or with a little bit of metaprogramming like so:</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> import static fj.data.Java.ArrayList_List as asList fj.data.List.metaClass.toList = { delegate.toCollection().toList() } List.metaClass.bind = { c -> asList().f(delegate).bind({ asList().f(c(it)) } as F) } List.metaClass.map = { c -> asList().f(delegate).map(c as F) } </pre></td></tr></table> <p>The above examples can be re-written like this:</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> assert [1, 2, 3].bind{ it % 2 ? [it * 2] : [] }.toList() == [2, 6] assert [1, 2, 3].map{ it + 42 }.toList() == [43, 44, 45] </pre></td></tr></table> <h2>More Information</h2> <p>See also:</p> <ol> <li><a href="http://www-128.ibm.com/developerworks/java/library/j-pg08235/index.html">Practically Groovy: Functional programming with curried closures</a></li> <li><a href="http://cromwellian.blogspot.com/2006/07/infinite-streams-in-groovy-in-my-last.html">Infinite Streams in Groovy</a></li> <li><a href="http://www.cs.nyu.edu/goldberg/pubs/gold96.pdf">Functional Programming Languages</a></li> <li><a href="http://www.md.chalmers.se/~rjmh/Papers/whyfp.pdf">Why Functional Programming Matters</a></li> <li><a href="http://www-128.ibm.com/developerworks/library/j-fp.html?ca=drs-tp2904">Functional programming in the Java language</a></li> <li><a href="http://docs.codehaus.org/pages/viewpage.action?pageId=7193">Post on functional programming in Java - maybe a tad verbose</a></li> <li><a href="http://functionalj.sourceforge.net/">FunctionalJ - A library for Functional Programming in Java</a></li> <li><a href="http://blog.reposita.org/?p=4">Weak versus strong languages, who wins the fight?</a></li> <li><a href="http://www.cs.brown.edu/~sk/Publications/Books/ProgLangs/">Programming Languages:Application and Interpretation</a></li> <li><a href="http://blackdragsview.blogspot.com/2006/08/beyond-groovy-10-groovy-goes-lisp.html">Beyond Groovy 1.0: Groovy goes Lisp</a></li> <li><a class="confluence-link" href="/display/GROOVY/Concurrency+with+Groovy" data-linked-resource-id="95092980" data-linked-resource-type="page" data-linked-resource-default-alias="Concurrency with Groovy" data-base-url="http://docs.codehaus.org">Concurrency with Groovy</a></li> </ol>
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