-
Bug
-
Resolution: Unresolved
-
Minor
-
None
-
Jenkins 2.319.3
When running a closure is applied to a list of lists though a method like `findAll`, the multiple assignment does not destructure the inner lists into individual variables, but set the first variable to the inner list, and the other variables to null.
If I run the following script as a pipeline:
#!/usr/bin/groovy def res = [:] [["tata", 123, 1], ["toto", 456, 2], ["titi", null, 3]].findAll { k, v, x -> println "${k}, ${v}, ${x}"; v != null }.each { k, v, x -> res[k] = v } println res
I would expect that my lists of 3 items are destructured into k, v and x. This way, I could only keep the lists whose second item is not null.
Instead, I get this output:
[tata, 123, 1], null, null [toto, 456, 2], null, null [titi, null, 3], null, null {}
If I run the same code in the Jenkins console, I get
tata, 123, 1 toto, 456, 2 titi, null, 3 [tata:123, toto:456]
The multiple assignment works properly if done on a map:
#!/usr/bin/groovy def res = [:] ["tata": 123, "toto": 456,"titi": null].findAll{ k, v -> v != null }.each{ k, v -> res[k] = v } println res
it gives:
{tata=123, toto=45
Note that it behaves properly when the code is run outside of Jenkins.
[JENKINS-68159] Multiple assignment in closure in pipeline does not destructure lists
Description |
Original:
When running a closure is applied to a list of lists though a method like `findAll`, the multiple assignment does not destructure the inner lists into individual variables, but set the first variable to the inner list, and the other variables to null.
If I run the following script as a pipeline: ``` #!/usr/bin/groovy def res = [:] [["tata", 123, 1], ["toto", 456, 2], ["titi", null, 3]].findAll { k, v, x -> println "${k}, ${v}, ${x}"; v != null }.each { k, v, x -> res[k] = v } println res ``` I would expect that my lists of 3 items are destructured into k, v and x. This way, I could only keep the lists whose second item is not null. Instead, I get this output: ``` [tata, 123, 1], null, null [toto, 456, 2], null, null [titi, null, 3], null, null {} ``` If I run the same code in the Jenkins console, I get ``` tata, 123, 1 toto, 456, 2 titi, null, 3 [tata:123, toto:456] ``` The multiple assignment works properly if done on a map: ``` #!/usr/bin/groovy def res = [:] ["tata": 123, "toto": 456,"titi": null].findAll { k, v -> v != null }.each { k, v -> res[k] = v } println res ``` it gives: ``` {tata=123, toto=456} ``` |
New:
When running a closure is applied to a list of lists though a method like `findAll`, the multiple assignment does not destructure the inner lists into individual variables, but set the first variable to the inner list, and the other variables to null.
If I run the following script as a pipeline: {code:java} #!/usr/bin/groovy def res = [:] [["tata", 123, 1], ["toto", 456, 2], ["titi", null, 3]].findAll { k, v, x -> println "${k}, ${v}, ${x}"; v != null }.each { k, v, x -> res[k] = v } println res {code} I would expect that my lists of 3 items are destructured into k, v and x. This way, I could only keep the lists whose second item is not null. Instead, I get this output: {code:java} [tata, 123, 1], null, null [toto, 456, 2], null, null [titi, null, 3], null, null {}{code} If I run the same code in the Jenkins console, I get {noformat} tata, 123, 1 toto, 456, 2 titi, null, 3 [tata:123, toto:456]{noformat} The multiple assignment works properly if done on a map: {code:java} #!/usr/bin/groovy def res = [:] ["tata": 123, "toto": 456,"titi": null].findAll{ k, v -> v != null }.each{ k, v -> res[k] = v } println res{code} it gives: {code:java} {tata=123, toto=45{code} Note that it behaves properly when the code is run outside of Jenkins. |
Some unusual Groovy syntax that is apparently not implemented. https://github.com/jenkinsci/workflow-cps-plugin/#known-limitations