Previous Page Next Page Contents

eval -- evaluate an object

Introduction

eval(object) evaluates its argument object by recursively replacing the identifiers occurring in it by their values and executing function calls, and then evaluates the result again.

Call(s)

eval(object)

Parameters

object - any MuPAD object

Returns

the evaluated object.

Side Effects

eval is sensitive to the value of the environment variable LEVEL, which determines the maximal substitution depth for identifiers.

Further Documentation

Chapter 5 of the MuPAD Tutorial.

Related Functions

context, evalassign, evalp, freeze, hold, indexval, LEVEL, level, MAXLEVEL, MAXDEPTH, val

Details

Example 1

subs performs a substitution, but does not evaluate the result:

>> subs(ln(x), x = 1)
                                   ln(1)

An explicit call of eval is necessary to evaluate the result:

>> eval(subs(ln(x), x = 1))
                                     0

text2expr does not evaluate its result either:

>> a := c:
   text2expr("a + a"), eval(text2expr("a + a"))
                                a + a, 2 c

Example 2

The function hold prevents the evaluation of its argument. A later evaluation can be forced with eval:

>> hold(1 + 1);  eval(%)
                                   1 + 1
      
                                     2

Example 3

When an object is evaluated, identifiers are replaced by their values recursively. The maximal recursion depth of this process is given by the environment variable LEVEL:

>> delete a0, a1, a2, a3, a4:
   a0 := a1:  a1 := a2 + 2:  a2 := a3 + a4:  a3 := a4^2:  a4 := 5:
>> LEVEL := 1:  a0, a0 + a2;
   LEVEL := 2:  a0, a0 + a2;
   LEVEL := 3:  a0, a0 + a2;
   LEVEL := 4:  a0, a0 + a2;
   LEVEL := 5:  a0, a0 + a2;
                             a1, a1 + a3 + a4
      
                                          2
                           a2 + 2, a2 + a4  + 7
      
                         a3 + a4 + 2, a3 + a4 + 32
      
                               2        2
                             a4  + 7, a4  + 37
      
                                  32, 62

eval first evaluates its argument and then evaluates the result again. Both evaluations happen with substitution depth given by LEVEL:

>> LEVEL := 1:  eval(a0, a0 + a2);
   LEVEL := 2:  eval(a0, a0 + a2);
   LEVEL := 3:  eval(a0, a0 + a2);
                                          2
                           a2 + 2, a2 + a4  + 7
      
                               2        2
                             a4  + 7, a4  + 37
      
                                  32, 62

Since the default value of LEVEL is 100, eval usually has no effect at interactive level:

>> delete LEVEL:
   a0, eval(a0), a0 + a2, eval(a0 + a2)
                              32, 32, 62, 62

Example 4

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

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

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 5

In contrast to lists and sets, evaluation of an array does not evaluate its entries. Thus eval has no effect for arrays either. Use map to evaluate all entries of an array:

>> delete a, b:  
   L := [a, b]:  A := array(1..2, L):  a := 1:   b := 2:
   L, A, eval(A), map(A, eval)
                           +-    -+  +-    -+  +-    -+
                   [1, 2], | a, b |, | a, b |, | 1, 2 |
                           +-    -+  +-    -+  +-    -+

The call map(A, gamma) does not evaluate the entries of the array A before applying the function gamma. Map the function gamma@eval to enforce the evaluation:

>> map(A, gamma), map(A, gamma@eval)
                     +-                  -+  +-    -+
                     | gamma(a), gamma(b) |, | 1, 1 |
                     +-                  -+  +-    -+

Example 6

Similarly, evaluation of a table does not evaluate its entries, and you can use map to achieve this. However, this does not affect the indices:

>> delete a, b:
   T := table(a = b):  a := 1:  b := 2:
   T, eval(T), map(T, eval)
                        table(    table(    table(
                          a = b ,   a = b ,   a = 2
                        )         )         )

If you want a table with evaluated indices as well, create a new table from the evaluated operands of the old table. Using eval is necessary here since the operand function op does not evaluate the returned operands:

>> op(T), table(eval(op(T)))
                                     table(
                              a = b,   1 = 2
                                     )

Example 7

Polynomials are inert when evaluated, and also eval has no effect:

>> delete a, x:  p := poly(a*x, [x]):  a := 2:  x := 3:
   p, eval(p), map(p, eval)
              poly(a x, [x]), poly(a x, [x]), poly(a x, [x])

Use mapcoeffs 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:

>> eval(evalp(p, x = 3))
                                     6

Example 8

The evaluation of an element of a user-defined domains depends on the implementation of the domain. Usually, it is not evaluated further:

>> delete a:  T := newDomain("T"):  
   e := new(T, a):  a := 1:
   e, eval(e), map(e, eval), 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, eval(e), map(e, eval), val(e)
                new(T, 1), new(T, 1), new(T, 1), new(T, a)

Changes




Do you have questions or comments?


Copyright © SciFace Software GmbH & Co. KG 2000