> There were no examples of this sort of usage
Well there's a difference betwixt “no example” and “no known example” :)
For me, the following used to be comparatively common:
1. I create a web component which uses a web-iterated index, and there's a
non-trivial functionality related to the index. Something like this (simplified
for a short example, in reality there would be considerably more complex
index-based functionality than just the nameAtIndex below):
=== code part
def index, list=...
def nameAtIndex() { def item=list[index];
item.title?:item.description?:item.toString() }
=== web part
<wo:repeat index="$index" count="$list.count"><wo:string
value="$nameAtIndex"/></wo>
===
2. later I bump to a need to iterate programmatically reusing the added
functionality.
Instead of fully refactoring the code (which would be definitely better, but
there might not be time enough for that), I often simply reuse the existing
code as-is:
=== [current-case]
for (index=0; index<list.count; index++) println nameAtIndex() // works like a
charm
===
Now it so happened my iterable was not index-based, but list-based, like this:
=== code part
def item, list=...
def itemName() { item.title?:item.description?:item.toString() }
=== web part
<wo:select list="$list" item="$item" displayName="$itemName"/>
===
thus my reuse-the-existing-code attempt was quite nicely plain:
=== [possible-case]
for (item in list) println itemName() // does not work at all, alas
===
and I've been pretty surprised it does not work as expected. Took me some time
to find that although I did not write for (def item in list), I still must use
(luckily one-liner) boilerplate which definitely should not be needed here: for
(def x in list) { item=x; ... } :(
Now I sort of fear in future, when I upgrade to G5, I will have to re-write in
a similar way all the [current-case] cases in all my projects.
Quite the contrary, it would be definitely nice if in future I could use
[possible-case], too.
All the best,
OC
> On 5. 9. 2025, at 18:12, Milles, Eric (TR Technology)
> <[email protected]> wrote:
>
> 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>
>