The scope of the variable confuses me in MaxScript

The scope of the variable confuses me in MaxScript

Anonymous
Not applicable
1,783 Views
4 Replies
Message 1 of 5

The scope of the variable confuses me in MaxScript

Anonymous
Not applicable

In the maxscript help manual, the description of local variables makes me feel that its very similar to the scope rules of C language.  However, by writing a piece of test code, I feel that things are not so simple

 

global foo = 23, x = 20 --explicit declare foo,x ,scope is global
y = 10 --implicit declare y,scope is global
format "context level global: foo= %\n" foo
if x > y then
( -- start the first scope
      local fk = foo + 1 --first local variable fk,And assign the fk with the global foo
      local foo = y - 1 --declare a local foo,cover the global foo
       format "context level 1: foo= %\n" foo
       if (foo > 0) then
       (--start second scope
           local foo = y - x --nested local variable foo,cover the first local foo
           format " context level 2: foo= %\n" foo
       ) --end of second scope
       format "context level 1: foo= %\n" foo --this output is not value in level 1,but value in level 2, bewildering!
) --end of first scope
format "context level global: foo= %\n" foo --not 23, but -10, why?

 

The thing that confused me the most was if you Get rid of this code

local fk = foo + 1

the last line output global foo is 23 ,if I use foo and assigen it to fk, the last output is -10  !

 

 

0 Likes
Accepted solutions (1)
1,784 Views
4 Replies
Replies (4)
Message 2 of 5

Swordslayer
Advisor
Advisor

Yes, the if expression doesn't open a new scope. There's a list of when new scope is opened in the reference, under Scope of Variables:

 

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
Message 3 of 5

Anonymous
Not applicable

Thank you very much for answering my question . At your suggestion, I reconsidered the output of the code。I still don't understand why the last line "global foo " output is effected by Line 6 "local fk = foo + 1",if I comment out this line,the output is 23, if I keep this line work,the out put is -10 ?

0 Likes
Message 4 of 5

Swordslayer
Advisor
Advisor
Accepted solution

Okay, that's a bug. To make it go away it's enough to change the condition a bit. Here's the reduced code to reproduce:

 

global test = 10
(
	if test > 0 then
	(
		local test = -20
		&test
	)
)
format "test = %\n" test --> -20

The expression inside the if test returns Global:test, ie the local test is identical to the global one. It looks as if a local test variable was created by the if test implicitly yet at the same time the global one was used, and when you explicitly use 'local' later on, no error is raised as maxscript allows specifying local/global multiple times like this. To make it go away, you could use global lookup directly by prefixing the variable name with double colon:

 

global test = 10
(
	if ::test > 0 then --> explicitly accessing the global variable
	(
		local test = -20
		&test
	)
)
format "test = %\n" test --> 10
0 Likes
Message 5 of 5

larryminton
Autodesk
Autodesk

I'm adding a warning message being written to listener when a variable being explicitly declared as local when it has already been used in the local scope as a global (added in MAXX-50742). With that, the situation is more clear. Running your script the output is:

20
10
context level global: foo= 23
OK
Warning - Variable 'foo' explicitly declared local when already present as global in current scope - see 'Scope of Variables' in MAXScript help - filename: G:\3dswin\bin\x64\hybrid\scripts\ScopeTest.ms; line number: 8
Warning - Variable 'foo' explicitly declared local when already present as global in current scope - see 'Scope of Variables' in MAXScript help - filename: G:\3dswin\bin\x64\hybrid\scripts\ScopeTest.ms; line number: 13
context level 1: foo= 9
context level 2: foo= -10
context level 1: foo= -10
OK
context level global: foo= -10
OK

 

The first warning is because global foo has already been introduced into the local scope by the line:
local fk = foo + 1 --first local variable fk,And assign the fk with the global foo

 

The second warning is because the following is not true:
if (foo > 0) then
(--start second scope

 

As documented in 'Scope' as quoted above, mxs does not create a new scope whenever it hits a parenthesis (like most languages), it only creates a new scope in the specific cases listed.

 

So, by design, mxs does not create a new scope when it hits a parenthesis. Doing so is possible, but is a fairly major change that would likely have behavioral impact on existing scripts and would have performance impacts (latter is the reason for this behavior).

 

Note that the first issue can be worked around by saying:


local fk = ::foo + 1 --first local variable fk,And assign the fk with the global foo

with that, the output is:
20
10
context level global: foo= 23
OK
context level 1: foo= 9
context level 2: foo= -10
context level 1: foo= -10
OK
context level global: foo= 23
OK

 

Note that the second issue is still there because we are not creating a new context level 2 as assumed, we are still in context level 1.


Larry Minton
Principal Engineer, M&E-Design Animation
0 Likes