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 started learning Groovy, and understood that parentheses are optional in method calls, so
def list = [0, 1, 2, 3]
list.each ({ item ->
println "Item: $item"
})
is the same as
def list = [0, 1, 2, 3]
list.each { item ->
println "Item: $item"
}
But now found this example
def list = [0, 1, 2, 3]
list.each() { item ->
println "Item: $item"
}
which also works. How is it possible to first call method with empty parameter list, and then specify closure after it?
Things are a little different when closures are involved. There is a special facility for closures that occur as the last parameter (as explained here).
As another illustration, consider:
class Foo {
int bar(s, c) {
return c(s)
}
int abc(c, s) {
return c(s)
}
}
def foo = new Foo()
def s = "fox"
This is a classic style:
assert 3 == foo.bar(s, { it.size() })
Yet this will work for closures as last argument:
assert 3 == foo.bar(s) { it.size() }
This is classic:
assert 3 == foo.abc({ it.size() }, s)
But this won't work
// assert 3 == foo.abc({ it.size() }) s
No doubt the reasoning is that if there is only one parameter, as with List.each(), then the syntax is very elegant:
list.each { item -> println item }
PROBLEM
let x = (0..<10).splitEvery( 3 )
XCTAssertEqual( x, [(0...2),(3...5),(6...8),(9)], "implementation broken" )
COMMENTS
I am running into problems calculating number of elements in the Range, etc...
extension Range
{
func splitEvery( nInEach: Int ) -> [Range]
{
let n = self.endIndex - self.startIndex // ERROR - cannot invoke '-' with an argument list of type (T,T)
}
}
The values in a range are of ForwardIndexType, so you can only advance() them,
or compute the distance(), but the subtraction - is not defined. The advance amount has to be of the corresponding
type T.Distance. So this would be a possible implementation:
extension Range {
func splitEvery(nInEach: T.Distance) -> [Range] {
var result = [Range]() // Start with empty array
var from = self.startIndex
while from != self.endIndex {
// Advance position, but not beyond the end index:
let to = advance(from, nInEach, self.endIndex)
result.append(from ..< to)
// Continue with next interval:
from = to
}
return result
}
}
Example:
println( (0 ..< 10).splitEvery(3) )
// Output: [0..<3, 3..<6, 6..<9, 9..<10]
Note however that 0 ..< 10 is not a list (or array) of integers. To split an array into subarrays you could define a similar extension:
extension Array {
func splitEvery(nInEach: Int) -> [[T]] {
var result = [[T]]()
for from in stride(from: 0, to: self.count, by: nInEach) {
let to = advance(from, nInEach, self.count)
result.append(Array(self[from ..< to]))
}
return result
}
}
Example:
println( [1, 1, 2, 3, 5, 8, 13].splitEvery(3) )
// Output: [[1, 1, 2], [3, 5, 8], [13]]
A more general approach could be to split all sliceable objects. But Sliceable
is protocol and protocols cannot be extended. What you can do instead is to
define a function that takes the sliceable object as the first argument:
func splitEvery<S : Sliceable>(seq : S, nInEach : S.Index.Distance) -> [S.SubSlice] {
var result : [S.SubSlice] = []
var from = seq.startIndex
while from != seq.endIndex {
let to = advance(from, nInEach, seq.endIndex)
result.append(seq[from ..< to])
from = to
}
return result
}
(Note that this function is completely unrelated to the (extension) methods
defined above.)
Example:
println( splitEvery("abcdefg", 2) )
// Output: [ab, cd, ef, g]
println( splitEvery([3.1, 4.1, 5.9, 2.6, 5.3], 2) )
// Output: [[3.1, 4.1], [5.9, 2.6], [5.3]]
Ranges are not sliceable, but you could define a separate function that takes a
range argument:
func splitEvery<T>(range : Range<T>, nInEach : T.Distance) -> [Range<T>] {
var result : [Range<T>] = []
var from = range.startIndex
while from != range.endIndex {
let to = advance(from, nInEach, range.endIndex)
result.append(from ..< to)
from = to
}
return result
}
Example:
println( splitEvery(0 ..< 10, 3) )
// Output: [0..<3, 3..<6, 6..<9, 9..<10]
If I have two iterables and I want to create a third iterable by lazily intersecting them. How can this be done in groovy. I can and have done this using guava before.
Assuming you mean intersect by "joining the elements together, one at a time", I wrote a package groovy-stream which can do this lazily:
#Grab( 'com.bloidonia:groovy-stream:0.8.1' )
import groovy.stream.*
Iterable a = [ 1, 2, 3 ]
Iterable b = [ 4, 5, 6 ]
Stream.from( a )
.zip( b ) { x, y -> [ x, y ] }
.each { println it }
Which will print:
[1, 4]
[2, 5]
[3, 6]
Edit:
You could of course roll your own:
Iterable a = [ 1, 2, 3 ]
Iterable b = [ 4, 5, 6 ]
Iterable zip = new LazyZipper( a:a, b:b, joiner:{ x, y -> [ x, y ] } )
for( r in zip ) {
println r
}
class LazyZipper implements Iterable {
Iterable a
Iterable b
Closure joiner
class LazyIterator implements Iterator {
Iterator ia
Iterator ib
void remove() { throw new UnsupportedOperationException() }
boolean hasNext() { ia.hasNext() && ib.hasNext() }
Object next() { joiner( ia.next(), ib.next() ) }
}
Iterator iterator() {
new LazyIterator( ia:a.iterator(), ib:b.iterator() )
}
}
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) }