String.eachLine(Closure closure) allows to iterate a String line by line:
"""aaaaaaaaaaaaa
bbbbbbbbbbbbb
ccccccccccccc""".eachLine { println "[$it]" }
// Produces:
[aaaaaaaaaaaaa]
[bbbbbbbbbbbbb]
[ccccccccccccc]
Similarly, File.eachFile(groovy.lang.Closure) iterates over all directory files:
new File( "." ).eachFile{ println "[${ it.canonicalPath }]" }
// Produces:
[D:\Winny\java\groovy-1.7.4\bin\grape]
[D:\Winny\java\groovy-1.7.4\bin\grape.bat]
[D:\Winny\java\groovy-1.7.4\bin\groovy]
[D:\Winny\java\groovy-1.7.4\bin\groovy.bat]
...
In fact, Object.each(groovy.lang.Closure) is the most general way to iterate over “parts” of an object:
new File( "groovy.bat" ).withReader { it.each{ println "[$it]" }}
// Produces:
[@if "%DEBUG%" == "" @echo off]
[]
[@rem ]
[@rem $Revision: 19763 $ $Date: 2010-04-05 14:33:24 +0200 (Mo, 05. Apr 2010) $]
[@rem ]
...
Here I use a fact that File.withReader(groovy.lang.Closure) passes java.io.LineNumberReader into a closure and its "each" iterates over lines. That’s how we get each line of "groovy.bat" printed.
It actually became a habit to "each { .. }" Groovy objects to see the iteration $it.
But wouldn’t it be better if "each" was splitting objects to chunks, returning a list of them ?
Object.metaClass.splitWith = { String methodName ->
MetaMethod m = delegate.metaClass.pickMethod( methodName, Closure.class )
assert m
def result = []
m.doMethodInvoke( delegate, { result << it } )
result
}
def files = new File( "d:/Winny/java/groovy-1.7.4" ).splitWith( 'eachFileRecurse' )
println "Largest file is of size ${ files*.length().max() } bytes"
// Produces:
Largest file is of size 5370870 bytes
Now we can “split” any object using its iterating methods:
// There are 15458 directories in "C:/Windows"
assert 15458 ==
new File( "C:/Windows" ).splitWith( 'eachDirRecurse' ).size()
// There are 14 non-empty lines in "groovy.bat"
assert 14 ==
new File( "groovy.bat" ).text.splitWith( 'eachLine' ).findAll{ it }.size()
// There are 24 permutations of [ 1, 2, 3, 4 ]
assert 24 ==
[ 1, 2, 3, 4 ].splitWith( 'eachPermutation' ).size()
// Splitting an Iterator with "each" bring back the original List
assert [ 1, 2, 3, 4 ] ==
[ 1, 2, 3, 4 ].iterator().splitWith( 'each' )
// Cleanup file data by trim()-ing and filtering out empty lines
new File( .. ).text.splitWith( 'eachLine' )*.trim().findAll{ it }
splitWith() allows one to break an object into chunks of data without having to make a full stop and iterate, storing away each $it in a List:
println [ 1, 2, 3, 4 ].splitWith( 'eachPermutation' ).size()
// vs.
def result = []
[ 1, 2, 3, 4 ].eachPermutation{ result << it }
println result.size()




