Is anyone aware of where CF/Lucee document the beh...
# cfml-general
b
Is anyone aware of where CF/Lucee document the behavior of automatically-searched scopes when SETTING a variable. The lookup order for unscoped vars is pretty well documented when simply accessing a variable, but I can't find anything on how they behave when assigning a value. I always assumed the behaved the same, but I found out today setting an unscoped variable that already exists in a searched scope doesn't always update that existing variable. Code sample in the thread.
Copy code
variables.inVariables = "bar"
url.inURL = "bar"

// updates variables scope, as expected
inVariables = "brad"

// Does NOT find url var and instead creates a new one in the variables scope
inURL = "brad"

writedump(variables)
writedump(url)
And it's not just variables, you can also do this with the local scope, even though that's not a default assignment scope in CF
Copy code
function func() {
    local.inLocal = "bar"
    url.inURL = "bar"

    // updates local scope, as expected
    inLocal = "brad"
    
    // Does NOT find url var and instead creates a new one in the variables scope
    inURL = "brad"
    
    writedump(local)
    writedump(url)
}

func()
r
my understanding is when assigning a variable and you dont specify a scope it will always assign it to the variables scope
b
That is incorrect per my examples above 🙂
r
I remember reading something about that im goign to go look
b
Copy code
inLocal = "brad"
above "finds" the existing
local.inLocal
var and updates it instead
You can run both these exampes on lucee 6 and ACF 2023
d
I thought if you didn't specify a scope you were setting it in the local scope, except in a CFC, wehre the default is the variables scope of the CFC.
b
Local scope has never been a default assignment scope in CFML 😕
Unless you have local mode in Lucee enabled
r
oh i see why you saying. Yeah that does not sound right, does it have the same behaviour on previous versions of acf?
d
Sorry, spoke sloppily. I thought if you didn't specify a scope you were setting it in the variables scope, which in a CFC is the CFC's private variables scope, and outside a CFC is just the "global" unscoped variables scope. You're never setting something in an actual scope (form, url, server, session...) unless you specify that scope.
b
Got it-- nope CF has always allowed you to make unscoped assignments to at least local and arguments
Copy code
function foo( param ) {
    // updates arguments.param, does NOT create a new variables.param
    param = "something else"
    dump(arguments)
  }

  foo(  "initial value" )
I always assumed that worked for any variable in a scope that is automatically found via scope search. Meaning I assumed that if you access
foo
like
Copy code
#foo#
you'd be accessing the same foo that you'd be setting if you wrote
Copy code
foo = "bar"
but it only appears to work in some cases/scopes
I really don't like that as it seems to imply that unscoped variables may be associated with a different scope based on which side of the assignment they're on!
Copy code
url.foo = "bar";

baz = foo
foo = "new value"
It would seem reasonable, that the
foo
being used on the right hand side of the assignment is the same as the
foo
being set on the left hand side, but they are different variables/scopes.
d
You're right, arguments is an exception. It's like any passed or declared args are effectively in the method's CFC's variables scope. There's no separate foo inside a method with an argument named foo.
Copy code
<cfscript>
public function test(string foo="", string bar="") 
{ 
    writeOutput("foo=#foo# arguments.foo=#arguments.foo#<br>");
    foo = 1;
    writeOutput("foo=#foo# arguments.foo=#arguments.foo#<br>");
    
    writeOutput("bar=#bar# arguments.bar=#arguments.bar#<br>");
    arguments.bar = 1;
    writeOutput("bar=#bar# arguments.bar=#arguments.bar#<br>");
}
test();
</cfscript>
b
method's variables scope.
To be clear, a method doesn't have a variables scope. I can simply see the CFC or template's that it's running inside of.
👍 1
> There's no separate foo inside a method with an argument named foo. FWIW, there can be a
local.foo
and an
arguments.foo
inside the method.
b
I agree with what @Ryan Albrecht said earlier. When you have
inURL = "brad"
within a function, then that is equivalent to
variables.inURL = "brad"
. The reason why the update
local.inLocal = "bar"; inLocal = "brad";
happens without any confusion is because the second statement relies on the fact that
inLocal
is already stored in function-local scope. You said,
Copy code
It would seem reasonable, that the foo being used on the right hand side of the assignment is the same as the foo being set on the left hand side, but they are different variables/scopes.
I do think that they are indeed different. I do believe that the scope is determined by the left hand side of the assignment. Whereas the right hand side is the value of the assignment. Hence, given
Copy code
url.foo = "bar";
baz = foo;
(1)
baz
is in variables scope; (2) CFML determines its value by searching among the scopes for the existence of
foo
. It is found in the URL scope. So this code snippet tells us that the value of
variables.baz
is "bar".
g
To answer your initial question: I have never seen any documentation that provides any information about the mechanics of un-scoped variable setting. I have only ever been aware of discussions of any "ordering" - when it comes to searching for a previously "set" variable.
(and of course the "follow-up" of: Don't have any un-scoped variables because weird shit happens.)