2013-05-27 9 views
7

Zrobiłem trochę programowania i Haskell, i chciałem zaimplementować niektóre funkcje przetwarzania list Haskella w Groovy. Poniżej znajduje się implementacja unfoldr. Zasadniczo A jest rodzajem wynikowego iteratora (tj. Listą) i B jest stanem.Wpisane krotki i zamknięcia w Groovy

Są dwie rzeczy, które chciałbym dać silniejsze typy do:

  1. które chciałbym móc powiedzieć Tuple<A,B> zamiast tylko Tuple
  2. że chciałbym być w stanie określić argumenty zamknięcia, a nie tylko typ wyniku.

Przykładowy kod, który generuje iterator, który wylicza od 1 do 100, znajduje się poniżej i jest połączony z ideonem 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"; 
} 
+0

Możesz zadeklarować typ argumentów zamknięcia i użyć 'CompileStatic', czy tego chcesz? Lub chcesz zadeklarować typ argumentu 'private Closure f'? Jak "zamknięcie prywatne f'? – Will

+0

Czy nie chcesz rzucić trochę światła na to? – Will

+0

Witaj Will. Przepraszam, teraz przekonwertowałem na używanie tablic, a nie krotek. Ale tak, "naprawdę potrzebowałem" prywatnego zamknięcia , C> f'. – Clinton

Odpowiedz

2

Problem twarz jest tu w zasadzie rodzajowych Java i jego niezdolność do deklarowania zmiennej listę typów na pojemniku. To prawda, że ​​Tuple jest szczególnie szkodliwy dla kompilacji statycznej, ponieważ nie zawiera nawet minimum elementów generycznych, ale trzeba wziąć pod uwagę, że Tuple jest po prostu listą z dowolną ilością elementów. Maksymalną wartością jest Tuple, gdzie T jest klasą podstawową dla wszystkich elementów. A jeśli wszystko jest w porządku, sugeruję użycie dowolnej listy. Definiowanie Tuple jako krotki z dwoma elementami, gdzie pierwszy ma typ A, a drugi typ B, a następnie definiuje Tuple, gdzie trzeci element ma typ C, nie jest możliwy w Javie. Zamiast tego będziesz potrzebował różnych typów, takich jak Tuple2 i Tuple3, do TupleN. Wyjaśniam to bardzo szczegółowo, ponieważ jest to zasadniczo ten sam powód, dlaczego nie ma takich informacji na temat Zamknięcia. Zamknięcia można używać do wykonywania połączeń za pomocą dowolnej liczby argumentów od 0 do N. Ale generics nie może tego zadeklarować.

W Groovy 2.2 będziesz mógł ponownie zamknąć Zamknięcie w Unfoldr z dowolnym interfejsem, który pasuje do twoich potrzeb, bez konieczności zmiany użycia def = upl. ({X -> if (x < 100) {new Tuple (x + 1, x + 1)} else null;}, 0);