Details
-
Improvement
-
Status: Closed
-
Major
-
Resolution: Won't Fix
-
1.0-beta-5
-
None
-
None
Description
1> [1,2,3].each .inject(0) { i, f | println "${i} ${f}"; ++i }
2> go
0 1
1 2
2 3
1> import java.io.File
2> new File("test.txt").eachLine.inject(0) { i, line | println "${1} ${line}"; ++i }
3> go
No signature of method org.codehaus.groovy.runtime.MethodClosure.inject() is applicable for argument types: (java.lang.Integer, CommandLine8$1) values: [0, CommandLine8$1@5e179a]
The following from John Wilson:
[1,2,3].each creates a closure over the call of each on [1, 2, 3]. This is expected behaviour and is like myObject.myMethod producing a closure over the call of myMethod on myObject.
So:
a = [1,2,3].each
a
prints
1
2
3
Now the closure generated isn't your common or garden closure, it implements groovy.lang.Range
we can see that by running
for (i in a)
{println i}prints
1
2
3
Now groovy.lang.Range extends java.util.List so the closure is a Collection!
Because the closure is a collection you can call inject on it.
Now the interesting question is how does the system know to make the closure implement Range for each and can we make it do so for eachLine, eachByte, eachFile?
I'm afraid I don't know the answer to this. there's nothing I can see in DefaultGroovyMethods which would tell the compiler to do this. It may well be wired in behaviour.
The fact that this works for each looks to be an unintended consequence of wanting to make the closure a Range (which is useful elsewhere - e.g. in for loops).