Take this simple loop:
#i#
What is the output? My answer is the numbers 1-3 followed by 7-10. But I was dismayed to learn this evening that it doesn't seem to be the case on my server. There it outputs 1-10 with no breaks. Can someone please confirm that this is NOT normal behaviour? I'm running CF 8,0,1,195765 on x64 CentOS 5 (kernel 2.6.18-128.1.6.el5) with 64-bit Java 1.6.0_13.
Update: Clearly I'm just retarded. It works this way on Windows, on Railo, and everyone else confirms this is known behaviour. Somehow I've gone 10 years without running into this issue, probably because I always revert to CFSCRIPT when I do "weird" looping. Secure Tabs Online Legit
That syntax above is analogous to collection iteration (in Groovy):
(1..10).each { i -> println(i) if (i == 3) { i += 3 } }
It is NOT analogous to this for loop (also in Groovy):
for (i = 1; i <= 10; i += 1) { println(i) if (i == 3) { i += 3 } }
Weird.
I get the same thing as you. cf8 Ubuntu 32 bit. It looks like the cfif puts it into another scope. Try this:
You'll probably see, like I do:
1
2
3
blarg 6
4
5
6
7
8
9
10
However, I expected the same thing you expected.
Ah, comments in tags. I basically just put "blarg #i#" inside of the cfif block.
rather, tags in comments :-/
I fixed it for you. I haven't figured out how to make WordPress be more rational about that. Though I'll also admit I've invested like 20 seconds of effort on it. ;)
Not sure why you think this is unusual? You've specified that the loop runs from 1..10. Changing the loop variable inside the loop is not going to affect the actual loop :)
Hint: it works like this in some other languages too (but not all/most).
So it depends on which languages you have exposure to…
@Sean, I disagree with you. Although this is what it is doing, one should be able to manually change the step value.
I wold file that as a bug, because that is exactly what it is.
From the livedocs:
http://livedocs.adobe.com/coldfusion/8/htmldocs/Tags_j-l_11.html#1101087
Note: The to value is evaluated once, when the cfloop tag is encountered. Any change to this value within the loop block, or within the expression that evaluates to this value, does not affect the number of times the loop is executed.
It is definately a little strange…
Interesting. In cfscript, I guess since the conditions of the loop are more explicit, an equivalent loop produces different output:
for (i=1; i<=10; i++) {
writeOutput(i & ");
if (i==3) i+=3;
}
@Sean: makes sense, but still a little odd to me. Even more strange that cfloop and cfscript-for behave so differently — also makes sense, just odd. Another cfscript vs tags quirk, I guess.
Here's a tag-based alternative:
<cfset i = 1 />
<cfloop condition="i LTE 10″>
#i#<br />
<cfif i EQ 3>
<cfset i += 3 />
</cfif>
<cfset i++ />
</cfloop>
BTW, this also reminds me of a quirk I discovered a while back with grouped query output and the currentRow value. If you inspect the currentRow value within the inner cfoutput in a grouped query output, you'll find that it does not increment with inner loop iterations, but only the outer. I found this to be expected behavior. I can see both sides of the argument there.
To be clear, both examples in my prior comment produce the following output:
1
2
3
7
8
9
10
It seems as though cfloop resets the variable with every iteration of the loop, so once the loop starts over again, i gets reset. What's strange to me is that i is local to each iteration, but once it breaks from the loop, i is no longer a local variable. The following will out put "11″ after the loop (which also doesn't make sense).
#i#
#i#
oops. lets try the code again.
<cfloop from="1″ to="10″ index="i">
#i#<br />
</cfloop>
#i#
@sean
While I see your point, I don't think syntax conveys that semantic very well. (1..10).each { println it} (that's Groovy) clearly indicates that I'm taking each number from 1 to ten and printing it, because I'm iterating over a collection. With the CFLOOP syntax, I read it as a verbose for loop (i.e. for (i = 1; i <= 10; i += 1) { writeOutput(i) }), because stipulating a start and an end, not a collection of those values. The step value also supports this understanding, I think.
Obviously that's NOT the behaviour, and it seems really weird in a CFML context. I can't think of another place in the language where you have an implicit collection like that. Even worse, there's no way to create such a collection excepting the implicit one inside a CFLOOP (which can't be accessed).
I don't think the syntax could be much clearer – loop over the numbers from 1 to 10, and you can access the current index with "i". If you need absolute control over the index then you should set it before the loop, use a condition for the looping, and manage the index yourself during the loop. Not all looping constructs are created equal, but they all have their uses :)