Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typed tuples and closures in Groovy

I've done a bit of programming and Haskell, and wanted to implement some Haskell list processing functions in Groovy. Below is an implementation of unfoldr. Basically A is the type of the resulting iterator (i.e. list) and B is the state.

There are two things I'd like to give stronger types to:

  1. I'd like to be able to say Tuple<A,B> instead of just Tuple
  2. I'd like to be able to define the arguments of the closure, not just the result type.

Example code which generates an iterator which enumerates from 1 to 100 is below and linked on ideone here.

class Unfoldr<A,B> implements java.util.Iterator<A>
{
  public Unfoldr(Closure<Tuple> f, B init) 
  {
    this.f = f;
    this.state = f(init);
  }

  public synchronized A next() 
  {
    if (hasNext())
    {
      A curr = state.get(0);
      state = f(state.get(1));
      return curr;
    }
    else
    {
      throw java.lang.NoSuchElementException;
    }
  }

  public synchronized boolean hasNext() 
  {
    return (state != null);
  }

  public void remove() { throw UnsupportedOperationException; }

  private Closure<Tuple> f;

  private Tuple state;
}

def unfoldr = { f, init -> new Unfoldr(f, init) };

def u = unfoldr({ x -> if (x < 100) { new Tuple(x + 1, x + 1) } else null; }, 0);

for(e in u)
{
  print e;
  print "\n";
}
like image 242
Clinton Avatar asked May 27 '13 00:05

Clinton


People also ask

What are closures in Groovy?

A closure in Groovy is an open, anonymous, block of code that can take arguments, return a value and be assigned to a variable. A closure may reference variables declared in its surrounding scope.

Does Groovy have tuples?

Groovy also provides a Tuple2 class that can be used for tuple instance of only two elements. The elements are typed in a Tuple2 instance. Written with Groovy 2.4.


1 Answers

The problem you face is here basically Java generics and its inability to declare a variable list of types for a container. True, Tuple is especially bad for static compilation, since it contains not even the minimum of generics, but you have to consider that Tuple is basically a list with a arbitrary amount of elements. The maximum you can get is Tuple, where T is the base class for all elements. And if you are ok with that, then I suggest using any list instead. Defining Tuple as a tuple with two elements where the first has type A and the second the type B and then going to define Tuple where the third element has type C is not possible in Java. Instead you will need real different types like Tuple2 and Tuple3 to TupleN. I am explaining this in so much detail, because this is basically the same reason as of why there is no such information on Closure. Closure can be used to make calls using any number of arguments from 0 to N. But there is no way in generics to declare this.

In Groovy 2.2 you will be able to reaplace Closure in Unfoldr with any interface that fits your needs, without having to change the usage def u = unfoldr({ x -> if (x < 100) { new Tuple(x + 1, x + 1) } else null; }, 0);

like image 76
blackdrag Avatar answered Oct 07 '22 03:10

blackdrag