eval
-- evaluate an objecteval(
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(object)
object |
- | any MuPAD object |
the evaluated object.
eval
is sensitive to the value of the environment
variable LEVEL
, which
determines the maximal substitution depth for identifiers.
Chapter 5 of the MuPAD Tutorial.
context
, evalassign
, evalp
, freeze
, hold
, indexval
, LEVEL
, level
, MAXLEVEL
, MAXDEPTH
, val
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.
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.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
The function hold
prevents the evaluation of its
argument. A later evaluation can be forced with eval
:
>> hold(1 + 1); eval(%)
1 + 1 2
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
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
:
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 | +- -+ +- -+
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 )
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
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)
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.