Evaluate an object with a specified substitution depth
This functionality does not run in MATLAB.
level(object
) level(object
,n
)
level(object, n)
evaluates object
with
substitution depth n
.
When a MuPAD^{®} object is evaluated, identifiers occurring
in it are replaced by their values. This happens recursively, i.e.,
if the values themselves contain identifiers, then these are replaced
as well. level
serves to evaluate an object with
a specified recursion depth for this substitution process.
With level(object, 0)
, object
is
evaluated without replacing any identifier occurring
in it by its value. In most cases, but not always, this equivalent
to hold(object)
, and object
is
returned unevaluated. See Example 3.
With level(object, 1)
, all identifiers occurring in object
are
replaced by their values, but not recursively, and then all function
calls in the result of the substitution are executed. This is how
objects are evaluated within a procedure by
default.
The call level(object)
is equivalent to level(object,
MAXLEVEL)
, i.e., identifiers occurring in object
are
recursively replaced by their values up to substitution depth MAXLEVEL
 1
, and an error occurs if the substitution depth MAXLEVEL
is
reached. Usually, this leads to a complete evaluation of object
.
See Example 1.
You can use level
without a second argument
to request the complete evaluation of an object not containing local
variables or formal parameters within a procedure.
This may be necessary since by default, objects are evaluated with
substitution depth 1
within procedures. See Example 2.
Otherwise, it should never be necessary to use level
.
Note:

level
works by temporarily setting the value
of LEVEL
to n
,
or to 2^{31}  1 if n
is
not given. However, the value of MAXLEVEL
remains unchanged. If the substitution
depth MAXLEVEL
is
reached, then an error message is returned. See LEVEL
and MAXLEVEL
for
more information on these environment variables.
In contrast to most other functions, level
does
not flatten its
first argument if it is an expression sequence.
See Example 5.
level
does not recursively descend into arrays
, tables
, matrices
or polynomials
.
Use the call map(object, eval)
to evaluate the
entries of an array, a table, a matrix or mapcoeffs(object,
eval)
to evaluate the coefficients of a polynomial. See Example 4 and Example 6.
Further information concerning the evaluation of arrays, tables,
matrices or polynomials can be found on the eval
help page.
The maximal substitution depth of level
depends
on the environment variable MAXLEVEL
, while the maximum evaluation
depth of the function eval
depends
on the environment variable LEVEL
. See Example 7.
Because eval
evaluates the result again there
is a difference between evaluating an expression with depth n by level
in
comparison with eval
. See Example 7.
As mentioned level
does not affect the evaluation
of local variables and formal parameters, of type DOM_VAR
, in procedures. Here eval
behaves
different. See Example 7 and the eval
help page for more
information.
The result of level(hold(x))
is always x
,
because a full evaluation of hold(x)
leads to x
.
The same does not hold for eval(hold(x))
, because eval
first
evaluates its argument and then evaluates the result again.
The evaluation of elements of a userdefined domain depends
on the implementation of the domain. Usually domain elements remain
unevaluated by level
. If the domain has a slot "evaluate"
,
the corresponding slot routine is called with the domain element as
argument at each evaluation, and hence it is called once when level
is
invoked. Cf. Example 8.
We demonstrate the effect of level
for various
values of the second parameter:
delete a0, a1, a2, a3, a4, b: b := b + 1: a0 := a1: a1 := a2 + 2: a2 := a3 + a4: a3 := a4^2: a4 := 5:
hold(a0), hold(a0 + a2), hold(b); level(a0, 0), level(a0 + a2, 0), level(b, 0); level(a0, 1), level(a0 + a2, 1), level(b, 1); level(a0, 2), level(a0 + a2, 2), level(b, 2); level(a0, 3), level(a0 + a2, 3), level(b, 3); level(a0, 4), level(a0 + a2, 4), level(b, 4); level(a0, 5), level(a0 + a2, 5), level(b, 5); level(a0, 6), level(a0 + a2, 6), level(b, 6);
Evaluating object
by just typing object
at
the command prompt is equivalent to level(object, LEVEL)
:
LEVEL := 2: MAXLEVEL := 4: a0, a2, b; level(a0, LEVEL), level(a2, LEVEL), level(b, LEVEL)
If the second argument is omitted, then this corresponds to
a complete evaluation up to substitution depth MAXLEVEL 
1
:
level(a0)
Error: Recursive definition, the maximal evaluation level is reached.
level(a2)
level(b)
Error: Recursive definition, the maximal evaluation level is reached.
delete LEVEL, MAXLEVEL:
We demonstrate the behavior of level
in procedures:
delete a, b, c: a := b: b := c: c := 42: p := proc() local x; begin x := a: print(level(x, 0), x, level(x, 2), level(x)): print(level(a, 0), a, level(a, 2), level(a)): end_proc: p()
Since a
is evaluated with the default substitution
depth 1
, the assignment x:=a
sets
the value of the local variable x
to the unevaluated
identifier b
. You can see that any evaluation of x
,
whether level
is used or not, simply replaces x
by
its value b
, but no further recursive evaluation
happens. In contrast, evaluation of the identifier a
takes
place with the default substitution depth 1
, and level(a,
2)
evaluates it with substitution depth 2
.
Thus level
without a second argument can
be used to request the complete evaluation of an object not containing
any local variables or formal parameters.
There are some rare cases where level(object, 0)
and hold(object)
behaves
different. This is the case if object
is not an
identifier, e.g., a nameless function, because level
influences
only the evaluation of identifiers:
level((x > x^2)(2),0), hold((x > x^2)(2))
For the same reason level(object, 0)
and hold(object)
behave
differently if object
is a local variable of a
procedure:
f:=proc() local x; begin x := 42; hold(x), level(x, 0); end_proc: f(); delete f:
In contrast to lists and sets, evaluation of an array does
not evaluate its entries. Thus level
has no effect
for arrays either. The same holds for tables and matrices. Use map
to evaluate all
entries of an array. On the eval
help
page further examples can be found:
delete a, b: L := [a, b]: A := array(1..2, L): a := 1: b := 2: L, A, level(A), map(A, level), map(A, eval)
The first argument of level
may be an expression
sequence, which is not flattened. However, it must be enclosed in
parentheses:
delete a, b: a := b: b := 3: level((a, b), 1); level(a, b, 1)
Error: The number of arguments is incorrect. [level]
Polynomials
are
inert when evaluated, and so level
has no effect:
delete a, x: p := poly(a*x, [x]): a := 2: x := 3: p, level(p)
Use mapcoeffs
and
the function eval
to
evaluate all coefficients:
mapcoeffs(p, eval)
If you want to substitute a value for the indeterminate x
,
use evalp
:
delete x: evalp(p, x = 3)
As you can see, the result of an evalp
call may contain unevaluated identifiers,
and you can evaluate them by an application of eval
. It is necessary to use eval
instead
of level
because level
does
not evaluate its result:
eval(evalp(p, x = 3))
The subtle difference between level
and eval
is shown. The evaluation
depth of eval
is limited by the environment variable LEVEL
. level
pays
no attention to LEVEL
, but rather continues evaluating
its argument either as many times as the second argument implies or
until it has been evaluated completely:
delete a0, a1, a2, a3: a0 := a1 + a2: a1 := a2 + a3: a2 := a3^2  1: a3 := 5: LEVEL := 1: eval(a0), level(a0);
If the evaluation depth exceeds the value of MAXLEVEL
,
an error is raised in both cases:
delete LEVEL: MAXLEVEL := 3: level(a0);
Error: Recursive definition, the maximal evaluation level is reached.
delete LEVEL: MAXLEVEL := 3: eval(a0); delete MAXLEVEL:
Error: Recursive definition, the maximal evaluation level is reached.
It is not the same evaluating an expression ex
with eval
and
an evaluation depth n and
by level((ex, n))
, because eval
evaluates
its result:
LEVEL := 2: eval(a0), level(a0, 2); delete LEVEL:
level
does not affect the evaluation of local
variables of type DOM_VAR
while eval
evaluates
them with evaluation depth LEVEL
, which is one
in a procedure:
p := proc() local x; begin x := a0: print(eval(x), level(x)): end_proc: p()
The evaluation of an element of a userdefined domain depends on the implementation of the domain. Usually it is not further evaluated:
delete a: T := newDomain("T"): e := new(T, a): a := 1: e, level(e), map(e, level), val(e)
If the slot "evaluate"
exists, the corresponding
slot routine is called for a domain element each time it is evaluated.
We implement the routine T::evaluate
, which simply
evaluates all internal operands of its argument, for our domain T
.
The unevaluated domain element can still be accessed via val
:
T::evaluate := x > new(T, eval(extop(x))): e, level(e), map(e, level), val(e);
delete e, T:

Any MuPAD object 

A nonnegative integer less than 2^{31} 
Evaluated object.