wood burning stoves 2.0*
The moose likes Groovy and the fly likes Groovy Puzzler Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Languages » Groovy
Bookmark "Groovy Puzzler" Watch "Groovy Puzzler" New topic
Author

Groovy Puzzler

Clifton Craig
Ranch Hand

Joined: May 26, 2006
Posts: 103
Can somebody tell me why this works:


while this doesn't?:


Holla at me...<br /><a href="http://codeforfun.wordpress.com" target="_blank" rel="nofollow">http://codeforfun.wordpress.com</a>
Tug Wilson
Ranch Hand

Joined: Dec 12, 2006
Posts: 33
list() returns String[]
listFiles() returns File[]

The Strings are file names.

File.toString() is a path.

So you will get differet results

In the first example you don't need it.toString()

In the seccond example you don't need to instantiate the File object
Clifton Craig
Ranch Hand

Joined: May 26, 2006
Posts: 103
I know all that. My problem is the second one throws a wierd error Something like:

no Signature of Script28.listAllFiles can be found...

The recursive call doesn't work and I don't understand why when all i did was change the parameter value.
Clifton Craig
Ranch Hand

Joined: May 26, 2006
Posts: 103
Actually I put the redundant toString and new File call in so that I can easily toggle between the two. I started with the first version and added the toString() for the revised version because what i really need in the closure is a File rather than a filename string. BTW, it works when you change it from a closure to a method. My question is why the closure throws an exception on the recursive call?
Tug Wilson
Ranch Hand

Joined: Dec 12, 2006
Posts: 33
You have two problems:

1/ listAllFiles isn't available to the closure as it isn't actually declared until the end of the statement which creates the closure

2/ you pass a File object to the recursive call which is expecting a String

This works:



Though I think this is slightly nicer


I think 1/ can be considered a bug. If you would be kind enough to raise a JIRA issue on the Groovy site somebody will take a look at it.
Tug Wilson
Ranch Hand

Joined: Dec 12, 2006
Posts: 33
In case you are wondering why your first example desn't complain that listallFiles is not defined...

It never calls listAllFiles recursivly. This is because File.list() returns file names not paths. So you are checking if there is a directory in the current working directory with the same name as a file in /home/ccc/jedit/4.2
Gregg Bolinger
GenRocket Founder
Ranch Hand

Joined: Jul 11, 2001
Posts: 15299
    
    6

That is some awesomely concise code considering what it's doing and the code I've written in the past in pure java to do the same thing.


GenRocket - Experts at Building Test Data
Clifton Craig
Ranch Hand

Joined: May 26, 2006
Posts: 103
Thanks Tug,

I knew it was something stoopid on my part. I completely overlooked how the first example wasn't recursively descending the file system.
Edward Povazan
Greenhorn

Joined: Dec 12, 2006
Posts: 3
Clifton, why not use eachFileRecurse?
Tug Wilson
Ranch Hand

Joined: Dec 12, 2006
Posts: 33
That is some awesomely concise code considering what it's doing and the code I've written in the past in pure java to do the same thing.


Yes - however, as Ed has pointed out, we can do better that that

Groovy adds lots of extra methods to standard Java classes which add useful functionality. So we have eachDir(), eachFile(), eachFileMatch() and eachFileRecurse(). These all take closures as their last parameter and call the closure with a File object parameter. The eachFileMatch method also takes a regexp to filter the file names.

This means that you can do stuff without all that tedious and error prone boilerplate code.

IDE's can often generate Java boilerplate code with a couple of keystrokes. However, you still have to read and maintain the verbiage. Conciseness of notation as a reading benefit not a writing benefit.
Jochen Theodorou
Greenhorn

Joined: Dec 13, 2006
Posts: 4
I think I should say an additional word about the recursive closure. The following lines are giving a quick (and incomplete) overview of the variable resolving process in Groovy. You may not understand all, just keep in mind that it is like an extension to the java way.

Given an expression like "a = b" it is a basic rule to evaluate the right side before the left side. That means we get first the value for b and then assign it to a. In an expression like "int i = 1" we evaluate the 1 to 1 (of course) and assign it to i. But when is i defined? It is defined after the right side is evaluated, because it is on the left side. If you think of Java, where you have an expression like "int i = i" and the later i is a field, then the newly declared i will be initialized with the value of the field i. Any subsequent calls to i in the same block of code will not access the field, but the new local variable i. So keeping that in mind and looking at a closure such as "def c = {c()}" makes it clear, that the c inside the closure is not the c outside.

If I write "c = {c()}" then there must have been either a variable/property c, a dynamic property or a reference to a binding. If not the assignment to c will fail. But this also means, that c is defined in the closure. Given that it works the c will be the closure. Then having a code like

explains itself. The c is known.

But there is more. You can influence the way the closure resolves the c by adding setting a delegate.

the delegate is used as last resort for the variable resolving process. When the closure asks the delegate, a map, for "c", it will answer with the value of d, which is the same as the closure itself. Builder do use this a lot.

I hope I made things not too unclear
Clifton Craig
Ranch Hand

Joined: May 26, 2006
Posts: 103
Ed,

Why not use eachFileRecurs?


Because I was born with slightly enlarged fingers and an arguably reduced cranium. Simply put my fat fingers no more than my small brain. That's a much more elegant approach and thanks for the tip.

Jochen,

I was initially assuming that the closure would not be available for reference inside itself but I felt I'd try it anyhow since Groovy has performed many other amazing and magical feats I got used to "trusting it" to figure out what my intentions were. When MY earlier example ran without error I naively figured that it was resolving the closure from within itself. It's not my fault though. You guys made the language too doggone good! Now people like me are looking for it to read our minds, automagically terminate and unwind inifinte recursive loops, understand swear words, and more! Stop doing such a good job and you won't get any more complaints from me.
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: Groovy Puzzler
 
Similar Threads
Read subdirectories and count files?
how sort a array of files and directories.. ?
Tiger in now available on Tiger !
Example of using Groovy Closure for a different programming style
Unfamiliar Scala syntax