[Closed] local variable visible in higher scope??
hi All!
I can’t believe I’m the only one that was surprised to find out about it, but I didn’t find anything about this in the forum:
local variables are not dying at the end of the scope!!
if I run this simple script (3dsMax 2010), I get “two” printed out!!
(
(
((local d = "one"))
)
(
((local d = "two"))
)
print d
)
I also get “two” printed if I run this script:
(
local d = "outer scope"
(
((local d = "one"))
)
(
((local d = "two"))
)
print d
)
the inner scope variable replaces the higher scope variable! how can it be? am I hallucinate?
There are people who know better then me, but ( ) doesn’t necessary mean a different scope.
From the helpfile:
The initial MAXScript scope context is global, and new scope contexts are opened for the following:
Top-level open parentheses in a script file or in the Listener
Start of a function body
Start of a for loop body
Start of a utility, rollout, right-click menu, Macro Script, or tool definition
Start of a rollout, utility, right-click menu, Macro Script, or tool event handler
Start of a when body
So according to the help that means that your scope is only 1 context, namely the first ( ) you put up that takes your script out of the global scope, all following ( ) are in the same scope, because no statement in used.
Look up “scope of variables” in the mxs helpfile.
-Johan
Thank you Johan! so it means according to the helpfile that
IF…THEN…
doesn’t declare a new scope? very strange…
Have you read the mxs page carefully? I just read it a bit better and the part I’m quoting is about implicit variable declaration and in what scope they get created, explicit lexical scoping is what you are doing and the chapter isn’t very clear about which statements a new scope is created with. The example shows an if statement, but the comment is that it’s the first open parenthesis after the global scope, so that doesn’t necessarily imply that an if statement creates a local scope on it own.
Basically I don’t know, but what I do know is that just using parenthesis to create a scope is only working for the first set of parenthesis in a global scope, which statements after that besides the already mentioned do create a scope is something someone else has to clear up.
Why your code behaves like it does, makes sense to me in that regard that all your declarations are in the same scope,
-Johan
First bracket creates new scope, regardless of why the bracket is there.
In the Listener:
if true then myLocalVar = 10 else myLocalVar = 20
10
myLocalVar
10
if true then (myLocalVar2 = 10) else (myLocalVar2 = 20)
10
myLocalVar2
undefined
In the first example, myLocalVar ends up GLOBAL because the IF does not create a new scope and we are in the global scope.
In the second attempt, myLocalVar2 ends up local to the scope of then() because there is no outer scope and this is the first bracket encountered. As you can see, myLocalVar2 does not get initialized to 10 and ceases to exist the moment the expression is done.
Implicit local variables work just like explicit ones as long as there is no such variable in a higher scope. If you create an implicit variable in the global scope, it ends up global. If you create an implicit variable inside some brackets below the global scope, or a function, for loop etc. as listed previously, it ends up local, the same as an explicit one.
Using explicit declaration is useful if a global variable with the same name already exists and you don’t want to use it, or if a local variable with the same name already exists in a higher scope and you want to mask it and create a new one at the current level. Even if no global or higher scope local variables with that name exist, it is a GOOD IDEA to use explicit locals to ensure they will end up in the right scope.
Thank you bobo for pointing this out!
so there is no sense that the same code put in brackets doesn’t behave the same, isn’t it?? if you run this code:
(
if true then myLocalVar = 10 else myLocalVar = 20
print myLocalVar
if true then (myLocalVar2 = 10) else (myLocalVar2 = 20)
print myLocalVar2
)
myLocalVar2 is still exist outside the brackets! it’s not logical at all!
The code I posted was run in the LISTENER!
Your code is run from an editor, and the myLocalVar2 exists ONLY inside the local scope if you run the script.
If after that you type in the Listener
myLocalVar2
you get
undefined
the FIRST TIME.
At this point, just typing myLocalVar2 in the Listener has CREATED a NEW GLOBAL myLocalVar2 and running the script a second time causes it to LOOK UP the GLOBAL scope and SEE myLocalVar2 as already declared, albeit undefined. So it uses the same pointer and suddenly myLocalVar2 becomes 10 in the GLOBAL scope where you just declared it by checking it the first time…
That’s why I said it is a GLOOD IDEA to use explicit declarations, because if you prefix myLocalVar2 with local in your code, it would never go looking up into the global scope
(
if true then myLocalVar = 10 else myLocalVar = 20
print myLocalVar
if true then (local myLocalVar2 = 20) else (local myLocalVar2 = 200)
print myLocalVar2
)
Here, myLocalVar2 remains local with a value of 20, but if you go to the listener and ask for myLocalVar2 you will get the previous global one with value of 10
Hi,
although Johan’s and Bobo’s replies make perfect sense, i’ve found a slight inconsistency. In the previous post by Cannan he puts up an example. If you run it once the myLocalVar2 doesn’t exist outside of the brackets. When you run it a second time, it does. It has escaped to the global scope.
I’ve tried to illustrate this in my example. Running it twice will make myLocalVar12 escape to the global scope. If you want to try again, just change the names of the variables. I can’t explain this, can somebody else?
(
--first set of brackets define a local scope
--within this local scope the following variables are also explicitly declared as local
if true then (local myLocalVar9 = 10) else (local myLocalVar9 = 20)
)
format "myLocalVar9: %
" myLocalVar9 --this variable doesn't "escape" to a global scope
(
--first set of brackets define a local scope
--within this scope the variables should be implicitly local
if true then (myLocalVar12 = 10) else (myLocalVar12 = 20)
)
format "myLocalVar12: %
" myLocalVar12 --this variable does "escape" to a global scope the second time you run it
Klaas
grabjacket I’m “she” not “he” and that is very strange what you found…
I think that’s what happen when you have “exceptions” in programming language, programming language not suppose to have exceptions like natural language, either brackets define new scope or not, but it can’t be in some cases one way and in other cases the other way…
See my previous post. This is a bit like Schrödinger’s cat problem – in order to check whether the variable is in the global scope, you have to peek into the global scope which has the side effect of MAKING that variable global the moment you do so. Its value is still undefined, but the second time you run your script, it is already global and is “seen” by the code as such, so it “escapes” and get the value assigned.
@cannan: sorry about the he/she thing. I’m just assuming things here.
@Bobo: thanks for clearing that up. I thought it had to be something like that but I didn’t know that either printing or formatting a variable which doesn’t exist yet, creates it. What’s that I hear you say?
“Even if no global or higher scope local variables with that name exist, it is a GOOD IDEA to use explicit locals to ensure they will end up in the right scope.”
Lesson learned.
Klaas