Functional programming 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 Haskell. If however you like Groovy but want to apply some functional style magic, read on.
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:
In Groovy, we gain some slight syntactic sugar over Java in that we can leave out the
return statements (the last evaluated expression is the default return value).
You can also define the above factorial function using a Closure:
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
fac2.call(4) is also supported). The closure version has the advantage that we can pass the
fac2 Closure around (e.g. as a parameter) or place it within a data structure.
We can also convert between functions and Closures, e.g.
fac3 variable will also be a closure.
We can of course start to mix and match functional and imperative coding styles as in this quicksort example:
You can fix the values for one or more arguments to a closure instance using the curry() method as follows:
If you supply one argument to the curry() method you will fix the first argument. If you supply N arguments you will fix arguments 1..N. See reference 1 or Chapter 5 of GINA for further details.
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:
XmlSlurperallows 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 GINA for more information about XmlSlurper.]
DataSetfeature 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 GINA for more information about DataSets.]
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:
If you are not familiar with traditional functional programming terms like
cdr, you may find the refactored version below (creds to Alexander Kriegisch) somewhat more readable:
Using Functional Java
You can also consider using Java libraries which support functional programming, e.g. using Functional Java for an example similar to the evens example above:
Or for something a little more adventurous, we can consider calculating primes:
Remember to add
functionaljava.jar to your classpath. You will need a version greater than version 2.8 of Functional Java.
- Practically Groovy: Functional programming with curried closures
- Infinite Streams in Groovy
- Functional Programming Languages
- Why Functional Programming Matters
- Functional programming in the Java language
- Post on functional programming in Java - maybe a tad verbose
- FunctionalJ - A library for Functional Programming in Java
- Weak versus strong languages, who wins the fight?
- Programming Languages:Application and Interpretation
- Beyond Groovy 1.0: Groovy goes Lisp
- Concurrency with Groovy