Adam Tuttle

Entries Tagged as Centaur

Deciphering the new Local Scope

Recently it was announced that ColdFusion 9 will add a way to explicitly access the existing "var" scope inside functions, using a new scope named "local".

There has been some confusion, including on my own part, about exactly how it is implemented -- so I thought I would do what I can to clear it up.

For starters, and as is always a top priority with ColdFusion upgrades, old code shouldn't break because of this change. While it is true that the following two lines are analagous, they are both still supported for the forseeable future:

<cfset var foo="bar">
<cfset local.foo="bar">

In addition, you will be able to create var/local-scoped variables anywhere in the method, not just at the top. Right off the bat, this is awesome and can cut down on quite a bit of typing. This:

<cfset var foo=""><!--- or: <cfset local.foo = "" /> --->
<cfquery name="foo">...</cfquery>

can become this, if you like:

<cfquery name="local.foo">...</cfquery>

How awesome is that? I'll tell you. Really awesome.

Now, on to some trickier things...

The "local" scope gives you explicit access to variables set in this scope. The scope has always been there; CF9 is just adding the local scope so that you can explicitly access it (read from it).

Previously, the only way to read variables from this scope was to imply that was where you wanted them from, by not including a scope name. ColdFusion would then infer that -- since the variable exists in the unnamed local scope -- that's what you wanted. To put it more explicitly, ColdFusion checks for the requested variable in several different scopes, and inside a method the unnamed local scope is at the top of that list. The first scope that contained a matching variable would be the value you got back. Now we'll have an explicit way to specify which scope to read from, including the previously-unnamed local scope.

Does this mean you don't have to var-scope any more?

Absolutely not.

But now you have two choices: Use the "var" keyword, or the local scope. As before, (and, I'm sure, partly to maintain backwards compatibility) if you neglect to include one of these indications that the variable is local, it will go into the object's global "variables" scope, which if not taken into proper consideration, is not thread-safe.

What happens to <cfset var local=structNew()/> ?

Without the ability to explicitly reference the unnamed local scope, the convention of creating a var-scoped structure named "local" was adopted as a community standard over years since the popularization of CFCs. As a result, you'll see a lot of existing code that has a var-scoped "local" structure.

If no special exceptions were made, then what you might end up with would be your custom "local" structure inside the local scope, something like the following:

What the addition of the local scope might have looked like...

Seems logical, right? Well that's not what happens. For whatever reason, in their infinite wisdom (and who am I to argue?), Adobe decided the better thing to do was to detect this case, and force the new structure into the object's global "variables" scope, so instead, this is what you end up with: Update: It just gets ignored, as Ben Forta's post states. (The confusion here was that at the time he wrote that, the beta didn't do what he said it would. It's since been fixed.)

What the addition of the local scope actually looks like (update: only for a short period of time during the beta)

... With one small exception, that I've found so far: If you execute a query and assign it to the local scope, like my 2nd code sample above (<cfquery name="local.foo">), for some odd reason, a key named "cfquery.executiontime" is added to the object's global variables scope:

For the most part, you can probably ignore that. But, on the off chance that you need it, now you know where to find it. Oh, and notice that it's got a period as part of the key name, so you can't use "variables.cfquery.executiontime" (well, ok, it might work, I didn't try...), but you would be better off using the syntax: foo = variables['cfquery.executiontime']; ... and it's not thread-safe. So that's probably a bug, and will probably get fixed before release.

Scope precedence is still exactly the same as it was previously:

  1. Function local (UDFs and CFCs only)
  2. Thread local (inside threads only)
  3. Arguments
  4. Variables (local scope)
  5. Thread
  6. CGI
  7. Cffile
  8. URL
  9. Form
  10. Cookie
  11. Client

Server, Application, Session, Request, and Attributes scopes (still) require that they are explicitly named in order to read a variable from them. (Did I miss any?)

Published 2009-07-09 @ 03:22 in Centaur ColdFusion