7

我做了一些编程和 Haskell,想在 Groovy 中实现一些 Haskell 列表处理功能。下面是一个实现unfoldr。基本上A是生成的迭代器的类型(即列表)并且B是状态。

有两件事我想给更强的类型:

  1. 我想能够说Tuple<A,B>,而不仅仅是Tuple
  2. 我希望能够定义闭包的参数,而不仅仅是结果类型。

下面是生成从 1 到 100 枚举的迭代器的示例代码,并在ideone 上链接。

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";
}
4

1 回答 1

2

您在这里面临的问题基本上是 Java 泛型以及它无法为容器声明类型的变量列表。确实,Tuple 对静态编译特别不利,因为它甚至不包含最少的泛型,但是您必须考虑到 Tuple 基本上是一个包含任意数量元素的列表。您可以获得的最大值是 Tuple,其中 T 是所有元素的基类。如果您对此表示满意,那么我建议您改用任何列表。将元组定义为具有两个元素的元组,其中第一个元素的类型为 A,第二个元素的类型为 B,然后在 Java 中定义第三个元素的类型为 C 的元组是不可能的。相反,您将需要真正的不同类型,例如 Tuple2 和 Tuple3 到 TupleN。这个我解释的很详细 因为这与为什么 Closure 上没有此类信息的原因基本相同。闭包可用于使用从 0 到 N 的任意数量的参数进行调用。但在泛型中没有办法声明这一点。

在 Groovy 2.2 中,您将能够在 Unfoldr 中使用适合您需要的任何接口重新放置 Closure,而无需更改用法 def u = expandr({ x -> if (x < 100) { new Tuple(x + 1, x + 1) } 否则为空; }, 0);

于 2013-08-23T08:01:19.573 回答