I've noticed that I can't shadow variables in closures. For example, in a function:
x = [1, 2, 3]
def foo() {
def item = 'whatever'
x.findAll{ item -> item > 1 }
}
foo()
// org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
// /private/tmp/foo.groovy: 4: The current scope already contains a variable of the name item
// # line 4, column 14.
// x.findAll{ item -> item > 1 }
// ^
This is a problem for me, because I want to define a DSL with closures, which implicitly define it and surprise my users:
def callClosure(body) {
body()
}
x = [1, 2, 3]
callClosure { x.findAll{ it -> it > 1 } } // same error
Is it possible to define closures with variables, even if they might shadow the enclosing scope?
I've tried this:
callClosure { x.findAll{ def it -> it > 1 } }
callClosure { x.findAll{ final it -> it > 1 } }
but both produce the same error.
Can I declare parameters in my closures such that I don't need to worry about them being defined in parent scopes?
I have a utility method that needs to check if a Map<String,Integer> contains entries (keys) whose values are all zero (0):
def mapIsAllZeros(Map<String,Integer> toCheck) {
println toCheck
toCheck.each {
if(it.value != 0) {
return false
} else {
println "Value is : " + it.value
}
}
println "Returning true..."
true
}
Hence:
Map<String,Integer> m1 = new HashMap<String,Integer>()
m1.put("fizz", 0)
m1.put("buzz", 0)
Map<String,Integer> m2 = new HashMap<String,Integer>()
m2.put("fizz", 0)
m2.put("buzz", 1)
boolean m1Check = mapIsAllZeros(m1) // TRUE
boolean m2Check = mapIsAllZeros(m2) // FALSE
However when I run this method passing it m2 I get:
[fizz:0, buzz:1]
Value is : 0
Value is : 0
Returning true...
What's going on?
each can not return. use find instead. also this can be done in one line: [fizz:0, buzz:1].every{!it.value}
def mapIsAllZeros(Map<String,Integer> toCheck) {
return toCheck.values().every{it==0}
}
assert !mapIsAllZeros([fizz: 0, buzz: 1])
assert !mapIsAllZeros([fizz: 1, buzz: 1])
assert mapIsAllZeros([fizz: 0, buzz: 0])
assert !mapIsAllZeros([fizz: null, buzz: null])
Edit: thanks to #dmahapatro: as the methods's name suggest a proper check against zero, let's not work with groovy-truth, so null:s wont result into something misleading
The problem here is that the return statement returns from the each closure, not from the mapIsAllZeros method. I.e. the closure returns false and then each continues the iteration.
So you should use something other than each. For instance, using find:
boolean mapIsAllZeros(Map<String, Integer> toCheck) {
!(toCheck.find { it.value != 0 })
}
Another alternative is to use a for loop:
boolean mapIsAllZeros(Map<String, Integer> toCheck) {
for (entry in toCheck.entrySet()) {
if (entry.value != 0)
return false
}
return true
}
The problem with returning from each closure was already clarified well, nevertheless You can also use the following piece of code (method name borrowed from #Steinar)
boolean mapIsAllZeros(Map<String, Integer> toCheck) {
!toCheck.values().contains(0)
}
Simple and uses API that is well known.
A solution comparing unique values:
def mapIsAllZeros(map) {
map*.value.unique() == [0]
}
assert !mapIsAllZeros([fizz: 0, buzz: 1])
assert !mapIsAllZeros([fizz: 1, buzz: 1])
assert mapIsAllZeros([fizz: 0, buzz: 0])
Because there are not enough answers here.
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)
As a newbie question, granted that a switch statement could be used, can the match operator be used on a list iterator
def myList = [1, 2, 3, 4]
myList.each {
it.match {
case /1/ => println "ONE!"
// etc.
}
}
Do you mean something like as:
def myList = [1, 2, 3, 4]
myList.each {
switch(it) {
case ~/1/ : println "ONE!"; break
case ~/2/ : println "TWO!"; break
}
}
(I'm not groovy expert - suggestions are desirable)
A groovy way to do it is to use a map of closures:
def caseMap = [ 1 : { println "ONE!" },
2 : { println "TWO!" },
]
def myList = [1, 2, 3, 4]
myList.each {
if (caseMap.containsKey(it)) {
caseMap[it]()
}
}
You may need to put parens around caseMap[it].
I have a collection of objects that I want to break up into a collection of collections, where each sequential group of 3 elements is in one collection.
For example, if I have
def l = [1,4,2,4,5,9]
I want to turn this into:
def r = [[1,4,2], [4,5,9]]
I'm doing it now by iterating over the collection and breaking it up.. but I then need to pass those 'groups' into a parallelized function that processes them.. It would be nice to eliminate this O(n) pre-processing work and just say something like
l.slice(3).collectParallel { subC -> process(subC) }
I've found the step method on the Range class, but it looks like that only acts on the indices. Any clever ideas?
Update:
I don't think this is a duplicate of the referenced link, although it's very close. As suggested below, it's more of the iterator-type thing I'm looking for.. the sub-collections will then be passed into a GPars collectParallel. Ideally I wouldn't need to allocate an entire new collection.
Check out groovy 1.8.6. There is a new collate method on List.
def list = [1, 2, 3, 4]
assert list.collate(4) == [[1, 2, 3, 4]] // gets you everything
assert list.collate(2) == [[1, 2], [3, 4]] //splits evenly
assert list.collate(3) == [[1, 2, 3], [4]] // won't split evenly, remainder in last list.
Take a look at the Groovy List documentation for more info because there are a couple of other params that give you some other options, including dropping the remainder.
As far as your parallel processing goes, you can cruise through the lists with gpars.
def list = [1, 2, 3, 4, 5]
GParsPool.withPool {
list.collate(2).eachParallel {
println it
}
}
If I understand you correctly, you're currently copying the elements from the original collection into the sub-collections. For more suggestions along those lines, checkout the answers to the following question: Split collection into sub collections in Groovy
It sounds like what you're instead looking for is a way for the sub-collections to effectively be a view into the original collection. If that's the case, check out the List.subList() method. You could either loop over the indices from 0 to size() in increments of 3 (or whatever slice size you choose) or you could get fancier and build an Iterable/List which would hide the details from the caller. Here's an implementation of the latter, inspired by Ted's answer.
class Slicer implements Iterator {
private List backingList
private int sliceSize
private int index
Slicer(List backingList, int sliceSize) {
this.backingList = backingList
this.sliceSize = sliceSize
}
Object next() {
if (!hasNext()) {
throw new NoSuchElementException()
}
def ret
if (index + sliceSize <= backingList.size()) {
ret = backingList.subList(index, index+sliceSize)
} else if (hasNext()) {
ret = backingList.subList(index, backingList.size())
}
index += sliceSize
return ret
}
boolean hasNext() {
return index < backingList.size()
}
void remove() {
throw new UnsupportedOperationException() //I'm lazy ;)
}
}
I like both solutions but here is a slightly improved version of the first solution that I like very much:
class Slicer implements Iterator {
private List backingList
private int sliceSize
private int index
Slicer(List backingList, int sliceSize) {
this.backingList = backingList;
int ss = sliceSize;
// negitive sliceSize = -N means, split the list into N equal (or near equal) pieces
if( sliceSize < 0) {
ss = -sliceSize;
ss = (int)((backingList.size()+ss-1)/ss);
}
this.sliceSize = ss
}
Object next() {
if (!hasNext()) {
throw new NoSuchElementException()
}
def ret = backingList.subList(index, Math.min(index+sliceSize , backingList.size()) );
index += sliceSize
return ret
}
boolean hasNext() {
return index < backingList.size() - 1
}
void remove() {
throw new UnsupportedOperationException() //I'm lazy ;)
}
List asList() {
this.collect { new ArrayList(it) }
}
List flatten() {
backingList.asImmutable()
}
}
// ======== TESTS
def a = [1,2,3,4,5,6,7,8];
assert [1,2,3,4,5,6,7,8] == a;
assert [[1, 2], [3, 4], [5, 6], [7, 8]] == new Slicer(a,2).asList();
assert [[1,2,3], [4,5,6], [7,8]] == (new Slicer(a,3)).collect { it } // alternative to asList but inner items are subList
assert [3, 2, 1, 6, 5, 4, 8, 7] == ((new Slicer(a,3)).collect { it.reverse() } ).flatten()
// show flatten iterator
//new Slicer(a,2).flattenEach { print it }
//println ""
// negetive slice into N pieces, in this example we split it into 2 pieces
assert [[1, 2, 3, 4], [5, 6, 7, 8]] == new Slicer(a,-2).collect { it as List } // same asList
assert [[1, 2, 3], [4, 5, 6], [7, 8]] == new Slicer(a,-3).asList()
//assert a == (new Slicer(a,3)).flattenCollect { it }
assert [9..10, 19..20, 29..30] == ( (new Slicer(1..30,2)).findAll { slice -> !(slice[1] % 10) } )
assert [[9, 10], [19, 20], [29, 30]] == ( (new Slicer(1..30,2)).findAll { slice -> !(slice[1] % 10) }.collect { it.flatten() } )
println( (new Slicer(1..30,2)).findAll { slice -> !(slice[1] % 10) } )
println( (new Slicer(1..30,2)).findAll { slice -> !(slice[1] % 10) }.collect { it.flatten() } )
There isn't anything built in to do exactly what you want, but if we #Delegate calls to the native lists's iterator, we can write our own class that works just like an Iterator that returns the chunks you're looking for:
class Slicer {
protected Integer sliceSize
#Delegate Iterator iterator
Slicer(objectWithIterator, Integer sliceSize) {
this.iterator = objectWithIterator.iterator()
this.sliceSize = sliceSize
}
Object next() {
List currentSlice = []
while(hasNext() && currentSlice.size() < sliceSize) {
currentSlice << this.iterator.next()
}
return currentSlice
}
}
assert [[1,4,2], [4,5,9]] == new Slicer([1,4,2,4,5,9], 3).collect { it }
Because it has all of the methods that a normal Iterator does, you get the groovy syntactic sugar methods for free with lazy evaluation on anything that has an iterator() method, like a range:
assert [5,6] == new Slicer(1..100, 2).find { slice -> slice.first() == 5 }
assert [[9, 10], [19, 20], [29, 30]] == new Slicer(1..30, 2).findAll { slice -> !(slice[1] % 10) }