@groovy.transform .TypeChecked
class Unfoldr< A, B> implements java.util .Iterator < A>
{
public Unfoldr( Closure< Object[ ] > f, B init)
{
this.f = f;
this.state = f( init) ;
}
public synchronized A next( ) throws java.util .NoSuchElementException
{
if ( hasNext( ) )
{
A curr = state[ 0 ] ;
state = f( state[ 1 ] ) ;
return curr;
}
else
{
throw new java.util .NoSuchElementException ( ) ;
}
}
public synchronized boolean hasNext( )
{
return state != null ;
}
public
void remove ( ) { throw UnsupportedOperationException
; }
private Closure< Object[ ] > f;
private Object[ ] state;
}
def currify( fn) {
{ Object... args ->
if ( args.size ( ) == fn.maximumNumberOfParameters ) {
fn( * args)
} else {
currify( fn.curry ( * args) )
}
}
} ;
def unfoldr = currify { f, init -> new Unfoldr( f, init) } ;
def map = currify { f, l -> unfoldr( { l2 -> if ( l2.hasNext ( ) ) { def e = l2.next ( ) ; return [ f( e) , l2] } else { return null ; } } , l.iterator ( ) ) }
def splitlist = currify {
n, l ->
unfoldr(
{
l2 ->
try
{
def a = new Object[ n] ;
for ( i in 0 ..( n- 1 ) )
{
a[ i] = l2.next ( ) ;
}
return [ a, l2] ;
}
catch ( java.util .NoSuchElementException e)
{
return null ;
}
} ,
l
)
} ;
Iterator.metaClass .rightShift = { PrintStream os -> delegate.each ( { x -> os.println ( x) } ) }
Iterator.metaClass .rightShift = { Closure f -> f( delegate) }
id = { x -> x }
f = currify { x -> x }
println "A: "
[ [ 1 , 2 ] , [ 3 , 4 ] ] .iterator ( ) >> System.out
println "B: "
[ 1 , 2 , 3 , 4 ] .iterator ( ) >> splitlist( 2 ) >> System.out
println "C: "
[ [ 1 , 2 ] , [ 3 , 4 ] ] .iterator ( ) >> map( id) >> System.out
println "D: "
[ 1 , 2 , 3 , 4 ] .iterator ( ) >> splitlist( 2 ) >> map( id) >> System.out
println "E: "
[ [ 1 , 2 ] , [ 3 , 4 ] ] .iterator ( ) >> map( f) >> System.out
println "F: "
[ 1 , 2 , 3 , 4 ] .iterator ( ) >> splitlist( 2 ) >> map( f) >> System.out
QGdyb292eS50cmFuc2Zvcm0uVHlwZUNoZWNrZWQKCmNsYXNzIFVuZm9sZHI8QSxCPiBpbXBsZW1lbnRzIGphdmEudXRpbC5JdGVyYXRvcjxBPgp7CiAgcHVibGljIFVuZm9sZHIoQ2xvc3VyZTxPYmplY3RbXT4gZiwgQiBpbml0KSAKICB7CiAgICB0aGlzLmYgPSBmOwogICAgdGhpcy5zdGF0ZSA9IGYoaW5pdCk7CiAgfQogIAogIHB1YmxpYyBzeW5jaHJvbml6ZWQgQSBuZXh0KCkgdGhyb3dzIGphdmEudXRpbC5Ob1N1Y2hFbGVtZW50RXhjZXB0aW9uCiAgewogICAgaWYgKGhhc05leHQoKSkKICAgIHsKICAgICAgQSBjdXJyID0gc3RhdGVbMF07CiAgICAgIHN0YXRlID0gZihzdGF0ZVsxXSk7CiAgICAgIHJldHVybiBjdXJyOwogICAgfQogICAgZWxzZQogICAgewogICAgICB0aHJvdyBuZXcgamF2YS51dGlsLk5vU3VjaEVsZW1lbnRFeGNlcHRpb24oKTsKICAgIH0KICB9CiAgCiAgcHVibGljIHN5bmNocm9uaXplZCBib29sZWFuIGhhc05leHQoKSAKICB7CiAgICByZXR1cm4gc3RhdGUgIT0gbnVsbDsKICB9CiAgCiAgcHVibGljIHZvaWQgcmVtb3ZlKCkgeyB0aHJvdyBVbnN1cHBvcnRlZE9wZXJhdGlvbkV4Y2VwdGlvbjsgfQoKICBwcml2YXRlIENsb3N1cmU8T2JqZWN0W10+IGY7CiAgCiAgcHJpdmF0ZSBPYmplY3RbXSBzdGF0ZTsKfQoKZGVmIGN1cnJpZnkoZm4pIHsKICAgIHsgT2JqZWN0Li4uIGFyZ3MgLT4KICAgICAgICBpZiAoYXJncy5zaXplKCkgPT0gZm4ubWF4aW11bU51bWJlck9mUGFyYW1ldGVycykgewogICAgICAgICAgICBmbigqYXJncykKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBjdXJyaWZ5KGZuLmN1cnJ5KCphcmdzKSkKICAgICAgICB9CiAgICB9Cn07CgpkZWYgdW5mb2xkciA9IGN1cnJpZnkgeyBmLCBpbml0IC0+IG5ldyBVbmZvbGRyKGYsIGluaXQpIH07CgpkZWYgbWFwID0gY3VycmlmeSB7IGYsIGwgLT4gdW5mb2xkcih7IGwyIC0+IGlmIChsMi5oYXNOZXh0KCkpIHsgZGVmIGUgPSBsMi5uZXh0KCk7IHJldHVybiBbZihlKSwgbDJdfSBlbHNlIHsgcmV0dXJuIG51bGw7IH0gfSAsIGwuaXRlcmF0b3IoKSl9CgpkZWYgc3BsaXRsaXN0ID0gY3VycmlmeSB7Cm4sIGwgLT4KICB1bmZvbGRyKAogICAgeyAKICAgICAgbDIgLT4gCiAgICAgICAgdHJ5IAogICAgICAgIHsgCiAgICAgICAgICBkZWYgYSA9IG5ldyBPYmplY3Rbbl07CiAgICAgICAgICBmb3IgKGkgaW4gMC4uKG4tMSkpCiAgICAgICAgICB7CiAgICAgICAgICAgIGFbaV0gPSBsMi5uZXh0KCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gW2EsIGwyXTsgCiAgICAgICAgfSAKICAgICAgICBjYXRjaCAoamF2YS51dGlsLk5vU3VjaEVsZW1lbnRFeGNlcHRpb24gZSkgCiAgICAgICAgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgfSwgCiAgICBsCiAgKQp9OwoKSXRlcmF0b3IubWV0YUNsYXNzLnJpZ2h0U2hpZnQgPSB7IFByaW50U3RyZWFtIG9zIC0+IGRlbGVnYXRlLmVhY2goeyB4IC0+IG9zLnByaW50bG4oeCkgfSkgfQpJdGVyYXRvci5tZXRhQ2xhc3MucmlnaHRTaGlmdCA9IHsgQ2xvc3VyZSBmIC0+IGYoZGVsZWdhdGUpIH0KCmlkID0geyB4IC0+IHggfQpmID0gY3VycmlmeSB7IHggLT4geCB9CgpwcmludGxuICJBOiAiCltbMSwyXSxbMyw0XV0uaXRlcmF0b3IoKSA+PiBTeXN0ZW0ub3V0CnByaW50bG4gIkI6ICIKWzEsMiwzLDRdLml0ZXJhdG9yKCkgPj4gc3BsaXRsaXN0KDIpID4+IFN5c3RlbS5vdXQKcHJpbnRsbiAiQzogIgpbWzEsMl0sWzMsNF1dLml0ZXJhdG9yKCkgPj4gbWFwKGlkKSA+PiBTeXN0ZW0ub3V0CnByaW50bG4gIkQ6ICIKWzEsMiwzLDRdLml0ZXJhdG9yKCkgPj4gc3BsaXRsaXN0KDIpID4+IG1hcChpZCkgPj4gU3lzdGVtLm91dApwcmludGxuICJFOiAiCltbMSwyXSxbMyw0XV0uaXRlcmF0b3IoKSA+PiBtYXAoZikgPj4gU3lzdGVtLm91dApwcmludGxuICJGOiAiClsxLDIsMyw0XS5pdGVyYXRvcigpID4+IHNwbGl0bGlzdCgyKSA+PiBtYXAoZikgPj4gU3lzdGVtLm91dAo=
stdout
A:
[1, 2]
[3, 4]
B:
[1, 2]
[3, 4]
C:
[1, 2]
[3, 4]
D:
[1, 2]
[3, 4]
E:
[1, 2]
[3, 4]
F:
stderr
Caught: java.lang.IllegalArgumentException: Can't curry 2 arguments for a closure with 1 parameters.
java.lang.IllegalArgumentException: Can't curry 2 arguments for a closure with 1 parameters.
at prog$_currify_closure8.doCall(prog.groovy:42)
at prog$_run_closure2_closure9.doCall(prog.groovy:49)
at Unfoldr.<init>(prog.groovy:8)
at prog$_run_closure1.doCall(prog.groovy:47)
at prog$_currify_closure8.doCall(prog.groovy:40)
at prog$_run_closure2.doCall(prog.groovy:49)
at prog$_currify_closure8.doCall(prog.groovy:40)
at prog$_run_closure5.doCall(prog.groovy:75)
at prog.run(prog.groovy:91)