When using CFML and CF9 I usually var scope my loop variables; in this case local.i
, for example:
<cfloop list="#this.list#" index="local.i">
<cfif Len(local.i) GT 10>
// do something
</cfif>
</cfloop>
I recently started converting some stuff into CFScript, and (to my disappointment I found out that there is no way to loop over a list in CFScript) I'm wondering if I should still var scope my loop variables, and how:
for (i = 1; LTE ListLen(this.list); i = i + 1 ) {
if (Len(ListGetAt(this.list, i) GT 10)) {
// do something
}
}
Should I be doing local.i = 1
and local.i = local.i + 1
istead of the sample code in my example? Is it necessary?
EDIT: I should also ask if the CFScript form of my CFML loop is correct; I ask because I just noticed that my CFML loop uses a ,
(comma and space) for the delimiter
argument, which seems non-existence in the CFScript version of the loop.
The VARIABLES scope is the default scope in ColdFusion. i.e. if a variable is declared in . cfm and . cfc file without explicitly prefixing a scope, or without 'var' to a variable inside a function, ColdFusion assigns VARIABLES scope to that variable.
Local (function local) Contains variables that are declared inside a user-defined function or ColdFusion component method and exist only while a function executes. For more information, seeWriting and Calling User-Defined Functions. Request. Used to hold data that must be available for the duration of one HTTP request.
All functions still use the variables scope by default if you don't specify one, which would make omitting it not-thread-safe. Wherever you previously should have used var
you should now use local
.
As for the comma+space delimiter, two things:
In case you aren't aware, the delimiters argument of list function is not for multi-character delimiters, it is for multiple delimiters; so your list will be split for each occurrence of a comma, as well as each occurrence of a space.
You use the same argument as part of your listLen
and listGetAt
methods, like so:
for (i = 1; LTE ListLen(this.list, ', '); i = i + 1 ) {
if (Len(ListGetAt(this.list, i, ', ') GT 10)) {
// do something
}
}
You definitely need to use the local scope as Adam says, but in the case of loops I think there's a strong case for using the "var" keyword rather than the "local" prefix for the sake of readability. With CF9 you're no longer forced to place var declarations at the top of the function, so all you need do is add "var" to your "for" condition statement for all the index "i" variables to become thread safe.
Taking in Ben's good point about saving the length of the list before starting the loop, and using the more concise i++ increment style your code would be:
var listLength = ListLen( this.list );
for (var i = 1; LTE listLength; i++ ) {
if (Len(ListGetAt(this.list, i) GT 10)) {
// do something
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With