Documentation

# LEVEL

Substitution depth of identifiers

MuPAD® notebooks will be removed in a future release. Use MATLAB® live scripts instead.

MATLAB live scripts support most MuPAD functionality, though there are some differences. For more information, see Convert MuPAD Notebooks to MATLAB Live Scripts.

## Description

The environment variable `LEVEL` determines the maximal substitution depth of identifiers.

Possible values: a positive integer smaller than 231.

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` determines the maximal recursion depth of this process.

Technically, evaluation of a MuPAD object works as follows. For a compound object, usually first the operands are evaluated recursively, and then the object itself is evaluated. E.g., if the object is a function call with arguments,the arguments are evaluated first, and then the function is executed with the evaluated arguments.

With respect to the evaluation of identifiers, the current substitution depth is recorded internally. Initially, this value is zero. If an identifier is encountered during the recursive evaluation process as described above and the current substitution depth is smaller than `LEVEL`, then the identifier is replaced by its value, the current substitution depth is increased by one, and evaluation proceeds recursively with the value of the identifier. After the identifier has been evaluated, the current substitution depth is reset to its previous value. If the current substitution depth equals `LEVEL`, however, then the recursion stops and the identifier remains unevaluated.

### Note

The default value of `LEVEL` at interactive level is `100`. However, the default value of `LEVEL` within a procedure is `1`. Then an identifier is only replaced by its value, which is not evaluated recursively.

The value of `LEVEL` may be changed within a procedure, but it is reset to `1` each time a new procedure is entered. After the procedure returns, `LEVEL` is reset to its previous value. See Example 3.

### Note

The evaluation of local variables and formal parameters of procedures, of type `DOM_VAR`, is not affected by `LEVEL`: they are always evaluated with substitution depth `1`. This means that a local variable or a formal parameter is replaced by its value when evaluated, but the value is not evaluated further.

See Example 3.

### Note

`LEVEL` does not affect the evaluation of arrays, tables and polynomials.

See Example 4.

The function `eval` evaluates its argument with substitution depth given by `LEVEL`, and then evaluates the result again with the same substitution depth.

The call `level(object, n)` evaluates its argument with substitution depth `n`, independent of the value of `LEVEL`.

If, during evaluation, the substitution depth `MAXLEVEL`, is reached, then the evaluation is terminated with an error. This is a heuristic for recognizing recursive definitions, as in the example ```delete a; a := a + 1; a```. Here, `a` would be replaced by `a + 1` infinitely often. Note that this has no effect if `MAXLEVEL` is greater than `LEVEL`. The default value of `MAXLEVEL` is `100`, i.e., it is equal to the default value of `LEVEL` at interactive level. However, unlike `LEVEL`, `MAXLEVEL` is not changed within a procedure, and hence recursive definitions are usually not recognized within procedures. See the help page of `MAXLEVEL` for examples.

The default value of `LEVEL` is `100` at interactive level; `LEVEL` has this value after starting or resetting the system via `reset`. Within a procedure, the default value is `1`. The command `delete LEVEL` restores the default value.

## Examples

### Example 1

We demonstrate the effect of various values of `LEVEL` at interactive level:

```delete a0, a1, a2, a3, a4, b: b := b + 1: a0 := a1: a1 := a2 + 2: a2 := a3 + a4: a3 := a4^2: a4 := 5:```
```LEVEL := 1: a0, a0 + a2, b; LEVEL := 2: a0, a0 + a2, b; LEVEL := 3: a0, a0 + a2, b; LEVEL := 4: a0, a0 + a2, b; LEVEL := 5: a0, a0 + a2, b; LEVEL := 6: a0, a0 + a2, b; delete LEVEL:```
` `
` `
` `
` `
` `
` `

### Example 2

In the following calls, the identifier `a` is fully evaluated:

```delete a, b, c: a := b: b := c: c := 7: a```
` `

After assigning the value `2` to `LEVEL`, `a` is evaluated only with depth two:

```LEVEL := 2: a; delete LEVEL:```
` `

If we set `MAXLEVEL` to `2` as well, evaluation of `a` produces an error, although there is no recursive definition involved:

`LEVEL := 2: MAXLEVEL := 2: a`
```Error: Recursive definition: Reached maximal evaluation level. ```
`delete LEVEL, MAXLEVEL:`

### Example 3

This example shows the difference between the evaluation of identifiers and local variables. By default, the value of `LEVEL` is `1` within a procedure, i.e., a global identifier is replaced by its value when evaluated, but there is no further recursive evaluation. This changes when `LEVEL` is assigned a bigger value inside the procedure:

```delete a0, a1, a2, a3: a0 := a1 + a2: a1 := a2 + a3: a2 := a3^2 - 1: a3 := 5: p := proc() save LEVEL; begin print(a0, eval(a0)): LEVEL := 2: print(a0, eval(a0)): end_proc:```
`p()`
` `
` `

In contrast, evaluation of a local variable replaces it by its value, without further evaluation. When `eval` is applied to an object containing a local variable, then the effect is an evaluation of the value of the local variable with substitution depth `LEVEL`:

```q := proc() save LEVEL; local x; begin x := a0: print(x, eval(x)): LEVEL := 2: print(x, eval(x)): end_proc: q()```
` `
` `

The command `x:=a0` assigns the value of the identifier `a0`, namely the unevaluated expression `a1+a2`, to the local variable `x`, and `x` is replaced by this value every time it is evaluated, independent of the value of `LEVEL`.

### Example 4

`LEVEL` does not affect on evaluation of `polynomials`:

```delete a, x: p := poly(a*x, [x]): a := 2: x := 3: p, eval(p); LEVEL := 1: p, eval(p); delete LEVEL:```
` `
` `

The same is true for `arrays` and `tables`:

```delete a, b: A := array(1..2, [a, b]): T := table(a = b): a := 1: b := 2: A, eval(A), T, eval(T); LEVEL := 1: A, eval(A), T, eval(T); delete LEVEL:```
` `
` `