eval -- evaluate an object
Introductioneval(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)
Parametersobject |
- | any MuPAD object |
Returnsthe evaluated object.
Side
Effectseval is sensitive to the value of the environment
variable LEVEL, which
determines the maximal substitution depth for identifiers.
Further
DocumentationChapter 5 of the MuPAD Tutorial.
Related
Functionscontext, evalassign, evalp, freeze, hold, indexval, LEVEL, level, MAXLEVEL, MAXDEPTH, val
Detailseval 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.
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
examples 3 and 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.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.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.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.eval is a function of the system kernel.
Example
1subs
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
2The function hold prevents the evaluation of its
argument. A later evaluation can be forced with eval:
>> hold(1 + 1); eval(%)
1 + 1
2
Example
3When 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
4This 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
5In 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
6Similarly, 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
7Polynomials 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
8The 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)
eval now works on all functions. Up to release 1.4.2,
eval only evaluated the functions args, coeff, evalp, expr, hold, input, last, lcoeff, nthcoeff, subs, subsex, subsop, tcoeff, and text2expr.DOM_VAR) in
eval has changed. See sections "The LEVEL-Problem" and
"Symbols and Variables" of the document "From MuPAD 1.4 to MuPAD
2.0" for details.