Block-expressions are the basic constructors for structured code. They allow you to group a sequence of expressions and evaluate them in sequence as though they were a single expression.
is, a parenthesized sequence of expressions with each
MAXScript also allows empty block-expressions, (). This is useful when incrementally building code in order to place an empty expression in a path to be filled in later. When evaluated, empty expressions yield the value undefined.
d = centre.x^2 - (p.x^2 + p.y^2)
newz = if d > 0 then sqrt d else p.z
if x < y then (print x; print y; u += 10; print u)
You can use a mixture of line breaks or semicolons:
print x; print y
u += 10
print u; print z
Because a block-expression
d = x^2 - y^2
if d > 0 then sqrt d else z
Here, the result of the block-expression is the result of the final if expression, which is then assigned to $box.pos.z.
Because the item in
parentheses can be any
(if a > b then c else d)[n + 1]
As described in Scope of Variables, top-level open parentheses in a script file or in the Listener create a new variable scope. Any block-expressions with the top-level block-expression do not create a new variable scope, even if the variable is explicitly declared as local in the inner block-expression. A variable’s scope extends into any block-expressions within the variable’s scope. If you declare a variable as local in a scope, the newly declared local variable hides any outer variables with the same name. Any reference to that variable name later in the local variable's scope refers to the new local variable. At the end of the local variable's scope, the next outer variable becomes visible again. This is shown in the following script:
1 -- result of line 1
3 -- output of line 7
3 -- result of block-expression lines 2 to 8
1 -- result of line 9
Any variable names used in a block-expression which have not been created at a higher scope level are implicitly declared as local in the present scope. This can result in unexpected execution results for scripts that are not set up correctly. For example, consider the following script:
(b=bend();addmodifier Objs b) -- create bend modifier and apply to objects
The first time you execute this script, the following error message is generated:
-- Unknown property: "angle" in undefined
If you execute the script again, it works properly. The reason is there are actually two variables with the name b - one is local to the block-expression and contains the bend modifier value, and the other is global and has the value undefined. During the second execution, global b exists, so the block-expression does not implicitly declare a new variable b, rather it uses the global variable b.
When writing scripts, it is also a good programming practice to explicitly declare as local all variables unless you really want them to be global variables. There are several reasons for this practice:
All the variable names used in the block or function will be together, which makes it easier to find the variable names and helps prevent using incorrect names in the script.
If more than one script is executing at the same time (for example, you are running a scripted utility and have a scripted controller in the scene) and both scripts use the same global variable name, the two scripts can interfere with one another. This can cause apparently random failures of one or both scripts.
You are sure you are using the correct variable in the event that a variable with the same name has already been declared at a higher scope, and you won't inadvertently change the higher-level variable's value.
Values of variables explicitly defined as local are displayed in error call stack trace-backs.
In 3ds Max R2.5, if a 3ds Max class, a MAXScript method, or a MAXScript read-only global variable has the same name as an implicitly declared local variable, a MAXScript runtime error will be generated if an assignment to that variable name occurs. Since the variable name already existed with a global scope, an implicitly declared local variable was not created. Since one or more new 3ds Max classes will be created by any third party plug-ins the user has loaded, you were not be able to tell ahead of time if a variable name was a global variable name. In 3ds Max 4 and higher, if the MAXScript compiler detects that the first reference to such a variable is an assignment, it will implicitly declare a local variable, rather than leaving it as a reference to a read-only system global. For example, executing the following expression in 3ds Max R2.5 would result in a value of Box, since Box is a 3ds Max object class. In 3ds Max 4 and higher, MAXScript detects that the first use of variable box is an assignment and creates an implicitly declared local variable box. The result of this expression in 3ds Max 4 and higher is the value undefined.
(if false do box=10;box)