Previous Page Next Page Contents

level -- evaluate an object with a specified substitution depth

Introduction

level(object, n) evaluates object with substitution depth n.

Call(s)

level(object)
level(object, n)

Parameters

object - any MuPAD object
n - a nonnegative integer less than 2^31

Returns

the evaluated object.

Further Documentation

Chapter 5 of the MuPAD Tutorial.

Related Functions

context, eval, hold, indexval, LEVEL, MAXLEVEL, val

Details

Example 1

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);
                              a0, a0 + a2, b
      
                              a0, a0 + a2, b
      
                          a1, a1 + a3 + a4, b + 1
      
                                       2
                        a2 + 2, a2 + a4  + 7, b + 2
      
                     a3 + a4 + 2, a3 + a4 + 32, b + 3
      
                           2        2
                         a4  + 7, a4  + 37, b + 4
      
                               32, 62, b + 5
      
                               32, 62, 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)
                                    2
                          a2 + 2, a4  + 5, b + 2
      
                                    2
                          a2 + 2, a4  + 5, b + 2

If the second argument is omitted, then this corresponds to a complete evaluation up to substitution depth MAXLEVEL - 1:

>> level(a0)
      Error: Recursive definition [See ?MAXLEVEL]
>> level(a2)
                                    30
>> level(b)
      Error: Recursive definition [See ?MAXLEVEL]
>> delete LEVEL, MAXLEVEL:

Example 2

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()
                                b, b, b, b
      
                                a, b, c, 42

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.

Example 3

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))
                             4, (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:
                             DOM_VAR(0,2), 42

Example 4

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) 
                      +-    -+  +-    -+  +-    -+  +-    -+
              [1, 2], | a, b |, | a, b |, | a, b |, | 1, 2 |
                      +-    -+  +-    -+  +-    -+  +-    -+

Example 5

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)
                                   b, 3
      Error: Wrong number of arguments [level]

Example 6

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)
                      poly(a x, [x]), poly(a x, [x])

Use mapcoeffs and the function eval to evaluate all coefficients:

>> mapcoeffs(p, eval)
                              poly(2 x, [x])

If you want to substitute a value for the indeterminate x, use evalp:

>> delete x: evalp(p, x = 3)
                                    3 a

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))
                                     6

Example 7

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);
                                       2
                           a2 + a3 + a3  - 1, 53

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 [See ?MAXLEVEL]
>> delete LEVEL: 
   MAXLEVEL := 3:
   eval(a0);
   delete MAXLEVEL:
      Error: Recursive definition [See ?MAXLEVEL]

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:
                                           2
                           53, a2 + a3 + a3  - 1

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()
                                    2
                        a2 + a3 + a3  - 1, a1 + a2

Example 8

The evaluation of an element of a user-defined 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)
                new(T, a), new(T, a), new(T, a), new(T, a)

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);
                new(T, 1), new(T, 1), new(T, 1), new(T, a)
>> delete e, T:

Changes




Do you have questions or comments?


Copyright © SciFace Software GmbH & Co. KG 2000