Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you do nested iterators in groovy?

Tags:

Does groovy support any kind of nested iterator notation?

In the example below, I want to somehow get the projectName value, that came from the outer iterator, into my inner iterator. Is this possible without storing in a variable? In my example I get a runtuime error that "project" is not found

it.myprojects.project.each{
     println("Project name: " + it.projectName)
    it.myroles.role.each{
         Role role = new Role()
             role.setName(project.projectName)//how do I get projectName here without storting it in a variable in the outer loop?
    }
}
like image 337
Derek Avatar asked Sep 24 '10 17:09

Derek


2 Answers

Those it variables are not iterators, they are closure parameters. The name it is not short for "iterator", it literally means "it", used as a default name for single-parameter closures. However, you can use explicit (and thus different nested) names like this:

it.myprojects.project.each{ project ->
     println("Project name: " + project.projectName)
     project.myroles.role.each{ role->
         Role r= new Role()
         r.setName(project.projectName)
    }
}

Actually, I'd advise against using the each method at all and use real loops instead:

for(project in it.myprojects.project){
     println("Project name: " + project.projectName)
     for(role in project.myroles.role){
         Role r= new Role()
         r.setName(project.projectName)
    }
}

This is better because closures make the code much harder to debug, and also potentially slower. And in this case, there isn't really any advantage in using closures anyway.

like image 199
Michael Borgwardt Avatar answered Jan 03 '23 11:01

Michael Borgwardt


It feels like this should work:

it.myprojects.project.each{ project->
     println("Project name: " + project.projectName)
     it.myroles.role.each{
         Role role = new Role()
         role.setName(project.projectName)
    }
}

Also, you can reference the outer closure using the owner variable

it.myprojects.project.each{ 
     println("Project name: " + it.projectName)
     it.myroles.role.each{
         Role role = new Role()
             role.setName(owner.projectName)
    }
}

However, I don't see a reason for iterating over roles if all you seem to be doing is creating new instances of the Role class. Perhaps something like this will be simpler:

it.myprojects.project.each{ 
     println("Project name: " + it.projectName)
     it.myroles.role.size().times {
         Role role = new Role()
         role.setName(owner.projectName)
    }
}
like image 26
mfloryan Avatar answered Jan 03 '23 10:01

mfloryan