Consider the following:
Demo1:
Run it.
Demo2:
Run it.
With ColdFusion 9 local is supposed to be private to the method. In Demo 2 the code behaves as expected but in Demo 1 the local in the variables scope is over written.
I consider this a bug with the local scope but I'd like some feed back.
BTW how did I find this? A friend on mine had code similar to the example and was wondering why local went blank half way through a page. I tracked it back to a UDF that had:
cfset local = {}
OK so calling a variable in a .cfm local not all the common but it could ( and did ) happen.
Thoughts?
Ignore the < br />'s the syntax highligter adds them and I havn't got around to fixing it yet.
ReplyDeletePaul, this is not a bug. However it is pretty silly code if you are setting the local scope to a struct.
ReplyDeleteNice find.. Also, to add another angle to this issue. If you do this:
ReplyDeletein the function it blanks the struct entirely.
@Anon
ReplyDeleteHow is it not a bug?
@Dave
ReplyDeleteSorry Blogger strips out the tags.
I assume you did:
cfset local = ""
Dang it.. code wiped.. should have been:
ReplyDelete<cfset local = '' />
Paul, I think your problem is that in example one, you are not actually altering the local scope, but a variable called local. If you look at Ben Forta's blog entry from back in June http://forta.com/blog/index.cfm/2009/6/21/The-New-ColdFusion-LOCAL-Scope, if you define a variable called var local, you are actually creating a variable Local.local. Since you did not var the local variable name, you are creating the local variable in the variable scope variable.local, which would overwrite your original value.
ReplyDeleteDean
@Dean
ReplyDeleteThat's not correct
< cfset var local /> within a method in ColdFusion 9 is ignored. It dosn't create local.local
@Paul,
ReplyDeleteI misspoke, apparently this changes since the release. However on those same lines, if you name a variable called local without the var keyword (which apparently is ignored anyway), it places it into the variable scope.
Either way, it's odd behavior.
Interesting... I just tried setting one of the other scopes to an empty structure and it treated it the exact same way.
ReplyDeleteURL = {}
When I dumped the variable scope it was located there. I don't know if this is something new to CF9 or if it has always treated direct setting of protected structure (without key names) in this manner.
Both demos worked as expected on my machine.
ReplyDeleteIts not a bug because you need to understand what you are doing.
ReplyDeleteThis may change with the release of updater 1, but here is what you are doing. In the CFM page you are defining a local scope to a struct. ColdFusion has in its wisdom made a decision that it will convert this to a variable, and place it into the variables scope.
In you function because the scope doesn't exist, you are referencing the variable as variables.local.name without the variables scope.
Does that make more sense!
Sorry I went Annonymous before, because it refused to save my comment, by throwing an error.
But in my function which is CF9 local always exists? Its a scope so it has to exist?
ReplyDeletePaul,
ReplyDeleteIf you set local to a struct you are defining it back to the variables scope. That is by design.
Consider this:
ReplyDelete< cfset request = {} /> or < cfset session = {} />
It's ignored as thats nto that way to clear a scope.
Why if local is a scope withing a method is
< cfset local = {} /> behaving different to the way all scopes are treated?
Because Adobe wanted to be backward compatible on this, and chose to try to be smart about it. Unfortunetly they got it wrong.
ReplyDeleteThis is also tied to the local bug described on a few blogs a few months ago.
I would say it is related, but the local scope is different to other scopes. Due to trying to be backward compatable.
If you ran this over a line debugger, you would see the problem that Adobe tried to address here.
OK I see so it's intended then by Adobe for compatibility its just mighty confusing :)
ReplyDeleteI think I'm going to stick with leaving :
< cfset var local = {} />
At the top on my methods just incase ( also so it will work on other engines ).
Or just dont reset the local scope to a struct, there is no need to do that in a function with the local scope.
ReplyDeleteWhy you even tried is beyond me.
But as I said you may find it fixed, in CF 9 updater 1, because of the local bug blogged a few months ago.
But like I stated,
set local = {} says I am setting the variable local into the variables scope.
Where var local = {} says you are then creating a local.local variable instead.
And yes it is confusing if you don't understand what is happening.
@Glen I didn't try LOL I was working with someone who said "Why did local just become empty half way down the page?" I tracked it down to this. By var scoping local = {} in the UDF or simply removing the line local = {} its worked fine.
ReplyDeleteAlso < cfset var local = {} /> In a method will not create local.local its simply ignored by the engine.
Explain ignored Paul!!
ReplyDeleteSure:
ReplyDelete< cfscript>
tester();
void function tester() {
var local = {};
local.name = "Paul";
writeDump(local);
}
There is no local.local created see: http://cf9.kukiel.net/demos/local/demo3.cfm for the output.
Paul,
ReplyDeleteIf this is ignored, then why can I do this?
var local = {firstName='Glen', lastName='dunlop');
How is it being ignored then, the engine is basically taking the line and converting it to a private scope for the function. This is not what I would call being ignored.
Your correct seems it's not ignored.
ReplyDeleteBut var local = {} doesn't create local.local but that's a different story. I think I'm happy with the original issue not being a bug but an intended outcome. Regardless it was an interesting journey to back track the original issue to this and goes to show why scoping is important.
Actually it does.
ReplyDeleteLets take this example inside a function for a minute.
local.test = {firstName='Glen', lastName='dunlop');
writeDump(local);
This will dump the local scope out.
Now lets take these lines
var local = {firstName='Glen', lastName='dunlop');
writeDump(local);
It too will dump the local scope out.
So what is hapenning here is that, its easy to assume and I had to double check this myself. But in a sense you are typing local.name, and you are referencing it from the local scope. However you can't dump local.local, because the engine is smart enough to know what you are asking from it.
But it boils down to that this is not a bug, and it is working as expected.
Interesting. I guess what we think and what is really happening behind the scene can be 2 different things. Thanks for taking the time.
ReplyDeleteHere is a follow up:
ReplyDeletehttp://blog.kukiel.net/2009/12/coldfusion-9-and-local-scope-continued.html
to add another angle to this issue. If you do this: in the function it blanks the struct entirely.
ReplyDeleteif you are looking for a cheap vps that is reliable and the uptime is 99.9%