How to select specific field using Groovy Closure - groovy

Given:
class FruitBasket {
int apples = 0
int oranges = 0
}
I need to pick out apples from each FruitBasket. The work need to be done in processFruit:
def processFruit(list, picker) {
list.each {
println "processing " + picker(it)
}
}
def processAll() {
List fruitList = [
new FruitBasket("apples": 2, "oranges": 4),
new FruitBasket("apples": 3, "oranges": 5)
]
processFruit(fruitList, applePicker)
}
def applePicker(FruitBasket f) {
return f.getApples()
}
but it is complaining # runtime that
No such property: applePicker for class: FooTest
possibly a problem with the closures FruitBasket arg...

In that code, applePicker is a method, not a closure.
You can either use a method handle to pass the method as a parameter like so:
processFruit(fruitList, this.&applePicker)
Or change it to an actual closure:
def applePicker = { FruitBasket f -> return f.getApples()    }

You are passing applePicker to processFruit, but it is a method. You can only pass closures this way. Redefine applePicker as a closure like so:
applePicker = { FruitBasket f ->
return f.getApples()
}
Or convert the method to a closure when processFruit is called:
processFruit(fruitList, this.&applePicker)

Related

Idiomatic means of choosing class constructor in groovy

I have a class like this:
in foo.groovy
class Foo {
String thing
Integer other
Foo(String thing) {
this.thing = thing
}
Foo(Integer other) {
this.other = other
}
}
return Foo.class
Now I would like to invoke these constructors. What I am doing is:
Other.groovy
def foo = evaluate(new File(ClassLoader.getSystemResource('foo.groovy').file)).newInstance(10)
def foo2 = evaluate(new File(ClassLoader.getSystemResource('foo.groovy').file)).newInstance("thing")
But this doesn't seem like the correct way of doing it. Ideally I would like to actually name the file Foo.groovy but then I get an error because it automatically declares the class for me. Basically, I want it to work like a classic Java class
Maybe I'm missing something here, but:
class Foo {
String thing
Integer other
Foo(String thing) {
this.thing = thing
}
Foo(Integer other) {
this.other = other
}
}
def x = new Foo(10)
assert x.other == 10 // true
def y = new Foo("foo")
assert y​​​​.thing​ == "foo"​​ // true
What are you trying to accomplish here other than that?
Edit: Try it here.

Is there a way to mimic map like access (using brackets) to get method on an arbitrary object

Is there a way in groovy where I can use brackets to access the get function like with maps? Something like this:
class Foo<V> {
String bar = "Bar:"
V get(Object lal) {
return bar + lal
}
}
def f = new Foo()
println(f["xxx"])
PS I would like to avoid extending the whole Map interface.
It works this way:
class Foo {
String bar = "Bar:"
def getAt(String lal) {
return bar + lal
}
def getAt(int i) {
return bar + i
}
}
def f = new Foo()
println(f["xxx"])
println(f[0])
You need to pass concrete object class.

Call method multiple times with each member of a collection as parameter

Let's say that I have a collection of parameters
def params = ['a','b','c']
Is there a short way to run a method that accepts a single parameter once for every element of a collection to replace this:
params.each {
foo(it)
}
with something more declarative (like a "reverse" spread operator)?
You can use collect:
def params = ['a','b','c']
def foo(param) {
'foo-' + param
}
assert ['foo-a', 'foo-b', 'foo-c'] == params.collect { foo(it) }
Or just a closure
def foo = { a -> a + 2 }
def modified = list.collect foo
You can use method pointer:
def l = [1,2,3]
l.each(new A().&lol)
class A {
def lol(l) {
println l
}
}
Or add a method that will do the task you need:
def l = [1,2,3]
List.metaClass.all = { c ->
delegate.collect(c)
}
l.all(new A().&lol)
class A {
def lol(l) {
println l
return l+2
}
}

Getting "calling" list size in list closure

I need to get the "calling" list size in a Groovy list closure, e.g.:
def foo = [1,2,3,4,5]
def bar = foo.findAll {
someCondition(it)
}.collect {
processElement(it, <self>.size())
}
where <self> is the list resulting from filtering foo with findAll.
Of course, one can save the intermediate result and get its size, but is it possible to do without it?
The best I can currently think of is:
def bar = foo.findAll { someCondition(it) }
.with { list ->
list.collect { processElement(it, list.size()) }
}
But this just uses with instead of an intermediate result.
Or, you could use the delegate of a Closure:
def foo = [1,2,3,4,5]
def collector = { it -> processElement(it, delegate.size()) }
(collector.delegate = foo.findAll { someCondition(it) }).collect collector
But this is just using the delegate as an intermediate result ;-)

How can a Groovy closure curry itself for repetition?

I'm implementing Groovy step definitions for Cucumber-JVM and I want a step to be able store itself so that the next step can repeat it n times.
Given(~'the (\\S+) is in the blender') { String thing ->
// do stuff...
context.repeatable = self.curry(thing)
}
What should "self" be in the above code?
I can't use "this" as that refers to the enclosing object (whatever that is in this case, maybe the script).
Since curry is a method of the Closure class, directly invoking curry applies to the closure, both if it is named:
def context
test = { String thing ->
context = curry(thing)
thing.toUpperCase()
}
test('hello')
println context.call()
test('world')
println context.call()
=>
HELLO
WORLD
or anonymous:
def context
['test'].each { String thing ->
context = curry(thing)
thing.toUpperCase()
}
println context.call()
=>
TEST
You can try using unreferenced curry method passing the received parameters:
clos = { String text ->
if (text) {
println "text=$text"
a = curry null
a()
} else {
println "done"
}
}
clos "closure text"
Will print:
text=closure text
done
Update
You can also use clone():
closure = {
def clone = clone()
}

Resources