The intention was not to "cripple" anything.  There were no examples of this 
sort of usage and allowing arbitrary expressions, like closures, was strange at 
first glance.  It is quite costly for the parser to explore so many 
alternatives at the start of the for statement.

https://github.com/apache/groovy/pull/2174

It was discussed that old scripts might use "for (v = 1; ...; ...)" to interact 
with the script binding.  We did not have examples at the time of declaring 
variable(s) outside of the loop statement and then referencing them in the 
initialization segment.

If this change is reversed for 5.0.1, it would not change the "strange" 
difference between classic for and enhanced for in terms of variable 
declaration vs. reference when no type is given.


________________________________
From: OCsite <[email protected]>
Sent: Friday, September 5, 2025 11:01 AM
To: [email protected] <[email protected]>
Cc: Milles, Eric (TR Technology) <[email protected]>
Subject: [EXT] Re: Ugly inconsistence betw. for and for/in

External Email: Use caution with links and attachments.

P.S.

it's quite unfortunate to cripple the language by forbidding that

among others also since it would break legacy code which relies on [1] — 
without any gain for that :(

All the best,
OC

On 5. 9. 2025, at 17:55, OCsite <[email protected]> wrote:

Well I would argue that's terribly wrong, for it does not bring any new 
functionality, just limits the existing one. Sometimes the form

===
def foo, bar // [1]
...
for (foo=1, bar=2, ....) // works with the very variables [1]
===

makes perfect sense and it's quite unfortunate to cripple the language by 
forbidding that :( And when the user does not want to use existing variables, 
nothing easier (and more logical and intuitive) than simply adding def.

All the best,
OC

On 5. 9. 2025, at 17:17, Milles, Eric (TR Technology) via dev 
<[email protected]<mailto:[email protected]>> wrote:

NOTE: Groovy 5 removes the expression list support from the first part of a 
classic form — variable declaration is the only option.

So, "for (foo = 1, bar = 2;' ...; ...)" is no longer possible.  You must write 
"for (def foo = 1, bar = 2; ...; ...)" or "for (def (foo,bar) = [1,2]; ...; 
...)".


forControl
  : enhancedForControl
  | originalForControl
;

enhancedForControl
  : (indexVariable COMMA)? variableModifiersOpt type? identifier (COLON | IN) 
expression
;

indexVariable
  : (BuiltInPrimitiveType | DEF | VAR)? identifier
;

originalForControl
  : forInit? SEMI expression? SEMI forUpdate?
;

forInit
  : localVariableDeclaration
;

forUpdate
  : expressionList[false]
;


________________________________
From: Milles, Eric (TR Technology) via dev 
<[email protected]<mailto:[email protected]>>
Sent: Friday, September 5, 2025 10:02 AM
To: Groovy_Developers <[email protected]<mailto:[email protected]>>
Cc: Milles, Eric (TR Technology) 
<[email protected]<mailto:[email protected]>>
Subject: Re: Ugly inconsistence betw. for and for/in

for-each and for-in always declare a new collection variable, which may have 
its type elided.  And now an index variable is also supported.

def foo = null
for (foo : []) {}
for (foo in []) {}

should produce an error of duplicate variable declared in outer scope.


for (classic) is a sequence of three expressions.  I don't think there is a 
hard requirement of a variable declaration expression as the first expression.  
So "foo = 1" is seen as an assignment not a declaration.  There may be some 
history where the variables were all set into script binding


________________________________
From: Ondra Cada <[email protected]<mailto:[email protected]>>
Sent: Thursday, September 4, 2025 5:54 PM
To: Groovy_Developers <[email protected]<mailto:[email protected]>>
Subject: [EXT] Ugly inconsistence betw. for and for/in

External Email: Use caution with links and attachments.

Hi there,

I've just bumped into the problem that the c-like for properly scopes/does not 
scope based on whether its control variable is declared or just used, whilst 
for/in always scopes, regardless the form (see the example below for detailed 
explanation).

Is this a bug or an intended behaviour?

It would be nice to fix it so that for/in does not scope when there's no 
declaration, but I fear it might be a breaking change for legacy code :(

Thanks and all the best,
OC

===
5 ocs /tmp> <q.groovy
class Foo {
  def foo
  def bar() { println "foo='$foo'" }
  def test() {
    println "Should not change"
    for (def foo in [1,2]) bar()
    println "Precisely like does not here"
    for (def foo=1; foo<3; foo++) bar()
    println "Should change but does not"
    for (foo in [1,2]) bar()
    println "Precisely like does here"
    for (foo=1; foo<3; foo++) bar()
  }
  static main(args) {
    Foo.newInstance().test()
  }
}
6 ocs /tmp> groovy q
Should not change
foo='null'
foo='null'
Precisely like does not here
foo='null'
foo='null'
Should change but does not
foo='null'
foo='null'
Precisely like does here
foo='1'
foo='2'
7 ocs /tmp> groovy -version
Groovy Version: 4.0.27 JVM: 1.8.0_452 Vendor: Tencent OS: Mac OS X
8 ocs /tmp>

Reply via email to