eval

Evaluate an object

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.

Syntax

eval(object)

Description

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.

eval serves to request the evaluation of unevaluated or partially evaluated objects. Evaluation means that identifiers are replaced by their values and function calls are executed.

Usually, every system function automatically evaluates its arguments and returns a fully evaluated object, and using eval is only necessary in exceptional cases. For example, the functions map, op, and subs may return objects that are not fully evaluated. See Example 1.

Like most other MuPAD® functions, eval first evaluates its argument. Then it evaluates the result again. At interactive level, the second evaluation usually has no effect, but this is different within procedures. See Example 3 and Example 4.

eval is sensitive to the value of the environment variable LEVEL, which determines the maximal depth of the recursive process that replaces an identifier by its value during evaluation. The evaluation of the argument and the subsequent evaluation of the result both take place with substitution depth LEVEL. See Example 3.

If a local variable or a formal parameter, of type DOM_VAR, of a procedure occurs in object, then it is always replaced by its value when eval evaluates its argument, independent of the value of LEVEL. At the subsequent second evaluation, the value of the local variable is evaluated with substitution depth given by LEVEL, which usually is 1. Cf. Example 4.

The behavior of eval within a procedure may sometimes not be what you expect, since the default substitution depth within procedures is 1 and eval evaluates with this substitution depth. Use level to request a complete evaluation within a procedure; see the corresponding help page for details.

eval enforces the evaluation of expressions of the form hold(x): eval(hold(x)) is equivalent to x. Cf. Example 2.

eval accepts expression sequences as arguments. See Example 3. In particular, the call eval() returns the empty sequence null().

eval does not recursively descend into arrays. Use the call map(object, eval) to evaluate the entries of an array. Cf. Example 5.

eval does not recursively descend into tables. Use the call map(object, eval) to evaluate the entries of a table.

However, it is not possible to evaluate the indices of a given table. If you want to do this, create a new table with the evaluated operands of the old one. Cf. Example 6.

Polynomials are not further evaluated by eval. Use evalp to substitute values for the indeterminates of a polynomial, and use the call mapcoeffs(object, eval) to evaluate all coefficients. Cf. Example 7.

The evaluation of elements of a user-defined domain depends on the implementation of the domain. Usually, domain elements remain unevaluated. 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 twice when eval is invoked. Cf. Example 8.

Environment Interactions

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

Examples

Example 1

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

subs(ln(x), x = 1)

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

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

text2expr does not evaluate its result either:

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

Example 2

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

hold(1 + 1);  eval(%)

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;

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

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)

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

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

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)

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)

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

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)

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

eval(evalp(p, x = 3))

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)

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)

Parameters

object

Any MuPAD object

Return Values

Evaluated object.