Jazzschmidt
Jazzschmidt

Reputation: 1105

Nesting multiple Closures in Groovy

I am having trouble nesting multiple Closures in Groovy. Nesting only one works like a charm:

def nestedClosure = { Closure cl -> doSomething { cl() } }

But how can I programatically nest multiple closures from e.g. a list of Closures?

Suppose this example:

Closure main = { println "Hello world" }

Closure consumer1 = { x -> println("1"); x(); println("1 END") }
Closure consumer2 = { x -> println("2"); x(); println("2 END") }
Closure consumer3 = { x -> println("3"); x(); println("3 END") }

I want to somehow chain and nest these consumers to get the output of:

1
2
3
Hello world
3 END
2 END
1 END

Tried currying, insane loops and googling for quite a while now, but can't seem to get any working idea.

Upvotes: 2

Views: 273

Answers (1)

Jazzschmidt
Jazzschmidt

Reputation: 1105

The trick was to curry the last Closure with the deepest nested "main" Closure and consecutively currying the remaining Closures and overwriting main:

def main = { println "Hallo" }

Closure consumer1 = { x -> println("1"); x(); println("1 END") }
Closure consumer2 = { x -> println("2"); x(); println("2 END") }
Closure consumer3 = { x -> println("3"); x(); println("3 END") }

def consumers = [consumer1, consumer2, consumer3]

// Nest main in last closure
consumers.reverse().each {
    main = it.curry(main)
}

main()

Notce: since I internally used Consumer<Closure> to remain argument safety, I needed to curry Consumer.accept via Method pointer:

def main = { println "Hallo" }

Consumer<Closure> consumer1 = { x -> println("1"); x(); println("1 END") }
Consumer<Closure> consumer2 = { x -> println("2"); x(); println("2 END") }
Consumer<Closure> consumer3 = { x -> println("3"); x(); println("3 END") }

def consumers = [consumer1, consumer2, consumer3]

consumers.reverse().each {
    main = it.&accept.curry(main)
}

main()

Upvotes: 3

Related Questions