## Documentation Center |

Delay evaluation

This functionality does not run in MATLAB.

`hold(``object`)

`hold(object)` prevents the evaluation of `object`.

When a MuPAD^{®} object is entered interactively, then the
system evaluates it and returns the evaluated result. When a MuPAD
object is passed as an argument to a procedure,
then the procedure usually evaluates the argument before processing
it. *Evaluation* means that identifiers are
replaced by their values and function calls are executed. `hold` is
intended to prevent such an evaluation when it is undesirable.

A typical application of `hold` is when a function
that can only process numerical arguments, but not symbolical ones,
is to be used as an expression. See Example 6.

Another possible reason for using `hold` is
efficiency. For example, if a function call `f(x, y)` with
symbolic arguments is passed as argument to another function, but
is known to return itself symbolically, then the possibly costly evaluation
of the "inner" function call can be avoided by passing
the expression `hold(f) (x, y)` as argument to the
"outer" function instead. Then the arguments `x,
y` are evaluated, but the call to `f` is
not executed. See examples Example 1 and Example 7.

Since using `hold` may lead to strange effects,
it is recommended to use it only when absolutely necessary.

`hold` only delays the evaluation of an object,
but cannot completely prevent it on the long run; see Example 5.

You can use `freeze` to
completely prevent the evaluation of a procedure or
a function environment.

A MuPAD procedure can be declared
with the option hold. This
has the effect that arguments are passed to the procedure unevaluatedly.
See the help page of `proc` for
details.

The functions `eval` or `level` can
be used to force a subsequent evaluation of an unevaluated object
(see example Example 2). In procedures
with `option
hold`, use `context` instead.

In the following two examples, the evaluation of a MuPAD expression
is prevented using `hold`:

x := 2: hold(3*0 - 1 + 2^2 + x)

hold(error("not really an error"))

Without `hold`, the results would be as follows:

x := 2: 3*0 - 1 + 2^2 + x

error("not really an error")

Error: not really an error

The following command prevents the evaluation of the operation `_plus`,
but not the evaluation of the operands:

hold(_plus)(3*0, -1, 2^2, x)

Note that in the preceding example, the arguments of the function
call are evaluated, because `hold` is applied only
to the function `_plus`. In the following example, the
argument of the function call is evaluated, despite that fact that `f` has
the option hold:

f := proc(a) option hold; begin return(a + 1) end_proc: x := 2: hold(f)(x)

This happens for the following reason. When `f` is
evaluated, the option `hold` prevents the evaluation
of the argument `x` of `f` (see
the next example). However, if the evaluation of `f` is
prevented by `hold`, then the option `hold` has
no effect, and MuPAD evaluates the operands, but not the function
call.

The following example shows the expected behavior:

f(x), hold(f(x))

The function `eval` undoes
the effect of `hold`. Note that it yields quite different
results, depending on how it is applied:

eval(f(x)), eval(hold(f)(x)), eval(hold(f(x))), eval(hold(f))(x)

Several `hold` calls can be nested to prevent
subsequent evaluations:

x := 2: hold(x), hold(hold(x))

The result of `hold ( hold(x) )` is the unevaluated
operand of the outer call of `hold`, that is, `hold(x)`. Applying `eval` evaluates
the result `hold(x)` and yields the unevaluated
identifier `x`:

eval(%)

Another application of `eval` yields
the value of `x`:

eval(%)

delete x, f:

The following command prevents the evaluation of the operation `_plus`,
replaces it by the operation `_mult`, and then evaluates the result:

eval(subsop(hold(_plus)(2, 3), 0 = _mult))

The function `domtype` evaluates
its arguments:

x := 0: domtype(x), domtype(sin), domtype(x + 2)

Using `hold`, the domain type of the unevaluated
objects can be determined: `x` and `sin` are identifiers,
and `x + 2` is an expression:

domtype(hold(x)), domtype(hold(sin)), domtype(hold(x + 2))

`hold` prevents only one evaluation of an object,
but it does not prevent evaluation at a later time. Thus using `hold` to
obtain a a symbol without a value is usually not a good idea:

x := 2: y := hold(x); y

In this example, deleting the
value of the identifier `x` makes it a symbol, and
using `hold` is not necessary:

delete x: y := x; y

However, the best way to obtain a new symbol without a value
is to use `genident`:

y := genident("z"); y

delete y:

Consider the piecewise defined function *f*(*x*) that
is identically zero on the negative real axis and equal to
on the positive
real axis:

f := x -> if x < 0 then 0 else exp(-x) end_if:

This function cannot be called with a symbolic argument, because
the condition *x* < 0 cannot
be decided:

f(x)

Error: Cannot evaluate to Boolean. [_less] Evaluating: f

We wish to integrate `f` numerically. However,
the numerical integrator expects
the function as an expression:

numeric::int(f(x), x = -2..2)

Error: Cannot evaluate to Boolean. [_less] Evaluating: f

The solution is to suppress premature evaluation of `f` when
passing the function with a symbolic argument. Inside the numerical
integrator, numerical values are substituted for *x* before
the function is called and evaluated:

numeric::int(hold(f)(x), x = -2..2)

The function `int` is
unable to compute a closed form of the following integral and returns
a symbolic `int` call:

int(sqrt(x)*sqrt(sqrt(x) + 1), x)

After the change of variables`sqrt(x)=t`,
a closed form can be computed:

t := time(): f := intlib::changevar(int(sqrt(x)*sqrt(sqrt(x) + 1), x), sqrt(x) = y); time() - t; eval(f)

Measuring computing times with `time` shows: Most of the time in the call
to `intlib::changevar` is
spent in re-evaluating the argument. This can be prevented by using `hold`:

t := time(): f := intlib::changevar(hold(int)(sqrt(x)*sqrt(sqrt(x) + 1), x), sqrt(x) = y); time() - t;

Was this topic helpful?