## Making Java 8 Groovier: A few annotated examples

September 6, 2016 1 Comment

In a couple of weeks, I’m giving two talks at talk at the 2016 JavaOne conference in San Francisco. One of them is called “**Groovy and Java 8: Making Java Better**“. I’m building examples in preparation for the conference, and as the Groovy community is good about correcting my errors in a friendly way, I thought I’d show some of them here ahead of time.

[Note: the session is labeled CON3277 and will take place Monday, Sept 19, from 12:30 – 1:30pm in the Hilton Plaza Room A, according to the session catalog.]

[One more aside: my co-host on the Groovy Podcast, Baruch Sadogursky, is participating in “**The Ultimate Build Tools Face-off**“, representing Gradle against Maven and Bazel. The winner of the face-off is determined by audience applause, so if you are within 500 miles of the event, be sure to make your voice heard. If I wasn’t giving my talk *at the exact same time*, I’d definitely be there.

Let me put that another way. As T’Pau said in the Star Trek original series episode Amok Time:

T’Pau: If both survive the lirpa, combat will continue with the ahn woon.

Kirk: Ah, what do you mean “if both survive?”

T’Pau: This combat isto the death.(emphasis unnecessarily added)

So Baruch, if you’re reading this: DON’T SCREW IT UP.

But no pressure.]

Anyway, my (first) talk is a demonstration of how Groovy goes beyond the functional capabilities added in Java 8, but can be used from Java to make life easier. Of course I’m going to talk about Java 8 lambdas vs Groovy closures, and how the method references syntax is different, but in this post I thought I’d highlight a couple of the cool AST transformations that are somewhat less common.

First, there’s memoize. Memoization is the process of building a cache of method calls, so if the same call occurs again, the system can return the cached value right away rather than re-computing it.

One way Groovy accomplishes this is by adding a `memoize`

method to the `Closure`

class. To build the cache, simply invoke the method. For example, consider a variable called `add`

assigned to a closure that takes two arguments and sleeps for one second before returning their sum.

def add = { x, y -> sleep 1000; x + y }.memoize() println add(3, 4) // takes 1 sec println add(3, 4) // immediate println add('a','b') // takes 1 sec println add('a','b') // immediate

Invoking the `memoize`

method replaces the closure with a new one that has keeps a cache of method calls. Therefore, the first call to `add`

with any arguments executes normally, but the second and all subsequent calls with the same arguments pulls the value out of the cache. Pretty sweet.

Recursive calls are naturals for this, and the classic example is computing Fibonacci numbers. Here are two separate ways to memoize a `fib`

function. In the first, a variable is assigned to a closure, so internally the closure uses the `call`

method for recursion.

def fib = { n -> if (n < 2) 1 else call(n - 1) + call(n - 2) }.memoize()

Alternatively, the `@Memoize`

Abstract Syntax Tree (AST) transformation can be applied to a method to accomplish the same thing.

@Memoized long fib(long n) { if (n < 2) 1 else fib(n - 1) + fib(n - 2) }

Either way, the result of each call with a particular value of `n`

is saved, so the recursive calls return almost immediately.

To demonstrate that I can use that from Java, I put the method in a Groovy class.

import groovy.transform.Memoized class AnnotatedFunctions { @Memoized BigInteger fib(BigInteger n) { if (n < 2) 1 else fib(n - 1) + fib(n - 2) } @Memoized BigInteger fact(BigInteger n) { if (n < 2) 1 else n * fact(n - 1) } }

In addition to the Fibonacci method `fib`

, I also have a recursive factorial computation, `fact`

. In Java, it’s easy enough to instantiate the Groovy class and invoke its methods directly. Here’s a snippet from the `main`

method of my Java class.

AnnotatedFunctions mf = new AnnotatedFunctions(); IntStream.range(1, 100) .forEach(i -> { long before = System.nanoTime(); BigInteger val = mf.fib(new BigInteger(i + "")); long after = System.nanoTime(); System.out.printf("%3d: %8s, fib(%2d) = %d%n", i, (after - before) / 1e9, i, val); }); IntStream.range(1, 100) .forEach(i -> { long before = System.nanoTime(); BigInteger val = mf.fact(new BigInteger(i + "")); long after = System.nanoTime(); System.out.printf("%3d: %8s, fact(%2d) = %d%n", i, (after - before) / 1e9, i, val); });

The output resembles:

1: 0.10599, fib( 1) = 1 2: 0.02197, fib( 2) = 2 3: 2.1E-4, fib( 3) = 3 4: 1.56E-4, fib( 4) = 5 5: 1.71E-4, fib( 5) = 8 6: 1.7E-4, fib( 6) = 13 // ... 98: 1.19E-4, fib(98) = 218922995834555169026 99: 1.16E-4, fib(99) = 354224848179261915075 1: 2.74E-4, fact( 1) = 1 2: 0.002715, fact( 2) = 2 3: 1.34E-4, fact( 3) = 6 4: 1.31E-4, fact( 4) = 24 5: 8.1E-5, fact( 5) = 120 6: 1.41E-4, fact( 6) = 720 // ... 98: 5.5E-5, fact(98) = 9426890448883247745626185743057242473809693764078951663494238777294707070023223798882976159207729119823605850588608460429412647567360000000000000000000000 99: 5.3E-5, fact(99) = 933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000

Pretty impressive, and trivial to do in Groovy even if you just want to call it from Java.

Another AST transform that comes up if the algorithm is right is `@TailRecursive`

. If you can express your algorithm in a way that the recursive call comes last, you can use that transform, which will also check that you did it properly.

I added the following method to my `AnnotatedFunctions`

class.

import groovy.transform.TailRecursive class AnnotatedFunctions { // ... other methods ... @TailRecursive BigInteger factorial(BigInteger n, BigInteger acc = 1G) { n < 2 ? acc : factorial(n - 1G, n * acc) } }

I don’t normally write `BigInteger`

, since Groovy automatically uses it if the system requires that many digits, but when integrating with Java it helps to be explicit. I’m also taking advantage of Groovy’s ability to optionally initialize a method variable by assigning the `acc`

accumulator the value of 1.

Now I can call this from Java, too.

AnnotatedFunctions mf = new AnnotatedFunctions(); // ... other calls from before ... System.out.println("70000! has " + mf.factorial(new BigInteger(70_000 + "")).toString().length() + " digits");

[This also takes advantage of the fact that starting in Java 7, you can embed underscores in numeric literals, like 70_000, for readability.]

The output is: `70000! has 308760 digits`

.

Another cool AST transform is `@Immutable`

. Functional programming favors immutability, but it’s enormously difficult to make a Java class produce immutable objects. You have to remove all the setters, provide private final backing fields for properties, wrap collections in their unmodifiable equivalents, make the class final, and so on.

Or, you can just use the `@Immutable`

annotation, which does all that and more for you. Here’s an immutable point class.

import groovy.transform.Immutable @Immutable class Point { double x double y }

Here is a Spock test (aside — my other JavaOne talk is on Spock testing) that demonstrates its capabilities.

import spock.lang.Specification class PointSpec extends Specification { def 'tuple constructor works'() { expect: new Point(3, 4) } def "can't change x"() { given: Point p = new Point(1, 2) when: p.x = 5 then: thrown(ReadOnlyPropertyException) } def "can't change y"() { given: Point p = new Point(1, 2) when: p.y = 5 then: thrown(ReadOnlyPropertyException) } }

I couldn’t really leave that alone, so I added a few more methods.

import groovy.transform.Immutable @Immutable class Point { double x double y static Point createPoint(double x, double y) { new Point(x, y) } Point translate(double dx = 0, double dy = 0) { new Point(x + dx, y + dy) } Point rotate(double radians) { double r = Math.sqrt(x * x + y + y) new Point(r * Math.cos(radians), r * Math.sin(radians)) } Point plus(Point p) { new Point(x + p.x, y + p.y) } Point minus(Point p) { new Point(x - p.x, y - p.y) } }

The `translate`

and `rotate`

methods produce new points that are the result of moving or rotating the original point. I also added a `plus`

and a `minus`

method to take advantage of operator overloading. The corresponding tests are:

import spock.lang.Specification class PointSpec extends Specification { // ... other tests ... def "can translate"() { given: Point start = new Point(1, 0) Point end = new Point(3, 3) when: Point p = start.translate(2, 3) then: assert (p.x - end.x).abs() < 1e-10 assert (p.y - end.y).abs() < 1e-10 } def "can rotate 90 deg"() { given: Point p = new Point(1, 0) when: p = p.rotate(Math.PI / 2) then: p.x.abs() < 1e-10 p.y == 1 } def "can rotate 180 deg"() { given: Point p = new Point(1, 0) when: p = p.rotate(Math.PI) then: p.x == -1 p.y.abs() < 1e-10 } def "overloaded plus"() { given: Point p1 = new Point(1, 2) Point p2 = new Point(3, 4) when: Point p = p1 + p2 then: p.x == 4 p.y == 6 } def "overloaded minus"() { given: Point p1 = new Point(1, 2) Point p2 = new Point(3, 4) when: Point p = p1 - p2 then: p.x == -2 p.y == -2 } }

The only nuisance is that because I’m planning to integrate with Java, I’m using doubles rather than `BigDecimal`

s, and that means the precision of zero isn’t quite what I need. Everything works, though, *including the tuple constructor*.

That’s significant, because I ran into a problem when trying to call this from Java.

public class UsePoint { public static void main(String[] args) { // Point p = new Point(1, 0) // doesn't work (aww) Point p = Point.createPoint(1, 0); System.out.println(p); System.out.printf("(%s,%s)%n", p.getX(), p.getY()); Point p1 = p.translate(2, 3); System.out.println(p1); // should be (3,3) Point p2 = p.rotate(Math.PI / 2); System.out.println(p2); // should be (0,1) } }

Even though the AST transform generates a tuple constructor for `Point`

, the Java code apparently is compiled too soon to see it. I was forced to add a `createPoint`

method to `Point`

in order to instantiate the class.

The rest works, though. I can invoke `translate`

or `rotate`

without a problem. The `plus`

and `minus`

methods don’t help Java much, since they’re there just for the Groovy operator overloading. Of course, there are no setters (no `setX`

or `setY`

methods) available, so I don’t have an issue with Java trying to call them.

I’m going to talk about streams, lambdas, and method references, too, but this post has enough in it for now. I’ll show that stuff in my next post. Besides, that’ll give me another chance to “encourage” Baruch in the Thunderdome.

## Recent Comments