Typed tuples and closures in Groovy
Asked Answered
C

1

7

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";
}
Cipher answered 27/5, 2013 at 0:59 Comment(5)
You can declare the type of the closure's arguments and use CompileStatic, is that what you want? Or you want to declare the private Closure<Tuple> f arguments type? Like private Closure<A1, A2, Tuple> f ?Ferity
wouldn't you like to shed some light on this?Ferity
Hi Will. Sorry, I've now converted to using arrays, not tuples. But yes, private Closure<Tuple<A, B>, C> f was what I was really looking for.Cipher
I think it can be done with interfaces. Are you still looking for an answer to this question?Ferity
Will, I half gave up, but I'd be really interested if there was an answer!Cipher
S
2

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);

Swindell answered 23/8, 2013 at 8:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.