freeze, unfreeze
--
create an inactive or active copy of a functionfreeze(f)
creates an inactive copy of the function
f
.
unfreeze(object)
reactivates all inactive functions
occurring in object
and evaluates the result.
freeze(f)
unfreeze(object)
f |
- | a procedure or a function environment |
object |
- | any MuPAD object |
freeze
returns an object of the same type as
f
. unfreeze
returns the evaluation of
object
after reactivating all inactive functions in
it.
ff := freeze(f)
returns a function that is an
``inactive'' copy of the argument f
. This means:
ff
only evaluates its arguments, but does not compute
anything else,ff
is printed in the same way
as f
,ff
calls have the same type as symbolic f
calls,f
is a function
environment, then ff
has all the slots of f
.ff
evaluates its incoming parameters even if the
function f
has the procedure option
hold
.freeze
can be used when many operations with
f
are to be performed that require f
only in
its symbolic form, but f
need not be executed. See
example 2.eval
nor
level
can enforce the
evaluation of an inactive function; see example 2.unfreeze(object)
reactivates all inactive functions
occurring in object
, proceeding recursively along the
structure of object
, and then evaluates the result.unfreeze
uses misc::maprec
to proceed recursively
along the structure of object
. This means that for
basic domains
such as arrays, tables, lists, or polynomials, the function unfreeze
is
applied to each operand of object
.
Note that if object
is an element of a library domain
, then the behavior of
unfreeze
is specified by the method "maprec"
which overloads the function misc::maprec
. If this method
does not exist, then unfreeze
has no effect on
object
. See example 5.
unfreeze
does not operate on the body of procedures,
therefore it is recommended not to embed inactive functions inside
procedures.We create an inactive form of the function environment
int
:
>> _int := freeze(int): F := _int(x*exp(x^2), x = 0..1)
2 int(x exp(x ), x = 0..1)
The inactive form of int
keeps every
information that is known about the function int
, e.g.,
the output, the type, and the "float"
slot for
floating-point evaluation:
>> F, type(F), float(F)
2 int(x exp(x ), x = 0..1), "int", 0.8591409142
The original function environment int
is not modified by
freeze
:
>> int(x*exp(x^2), x = 0..1)
exp(1) ------ - 1/2 2
Use unfreeze
to reactivate the inactive
function _int
and evaluate the result:
>> unfreeze(F), unfreeze(F + 1/2)
exp(1) exp(1) ------ - 1/2, ------ 2 2
The function student::riemann
makes use of
freeze
in order to return a result where the function
sum
is preserved in its
symbolic form:
>> a:= student::riemann(sin(x), x = 0..PI)
/ / PI (i3 + 1/2) \ \ PI sum| sin| ------------- |, i3 = 0..3 | \ \ 4 / / ----------------------------------------- 4
Only when applying unfreeze
the sum is
computed:
>> unfreeze(a)
1/2 1/2 1/2 1/2 PI ((2 + 2) + (2 - 2 ) ) ---------------------------------- 4
>> float(%)
2.052344306
We demonstrate the difference between hold
and freeze
. The
result of the command S := hold(sum)(...)
does not contain
an inactive version of sum
, but the unevaluated identifier sum
:
>> S := hold(sum)(1/n^2, n = 1..infinity)
/ 1 \ sum| --, n = 1..infinity | | 2 | \ n /
The next time S
is evaluated, the
identifier sum
is replaced by its value, the function environment sum
, and the procedure computing the
value of the infinite sum is invoked:
>> S
2 PI --- 6
In contrast, evaluation of the result of
freeze
does not lead to an evaluation of the inactive
function:
>> S := freeze(sum)(1/n^2, n = 1..infinity)
/ 1 \ sum| --, n = 1..infinity | | 2 | \ n /
>> S
/ 1 \ sum| --, n = 1..infinity | | 2 | \ n /
An inactive function does not even react to eval
:
>> eval(S)
/ 1 \ sum| --, n = 1..infinity | | 2 | \ n /
The only way to undo a freeze
is to use
unfreeze
, which reactivates the inactive function in
S
and then evaluates the result:
>> unfreeze(S)
2 PI --- 6
Note that freeze(f)
does not change the
object f
but returns a copy of f
in an
inactive form. This means that computations with the inactive version
of f
may contain the original function f
.
For example, if we create an inactive version of the sine function:
>> Sin := freeze(sin):
and expand the term Sin(x+y)
, then the
result is expressed in terms of the (original) sine function
sin
:
>> expand(Sin(x + y))
cos(x) sin(y) + cos(y) sin(x)
The function unfreeze
uses misc::maprec
to operate recursively
along the structure of object
. For example, if
object
is an array containing inactive functions, such
as:
>> a := array(1..2, [freeze(int)(sin(x), x = 0..2*PI), freeze(sum)(k^2, k = 1..n)] )
+- 2 -+ | int(sin(x), x = 0..2 PI), sum(k , k = 1..n) | +- -+
then unfreeze(a)
operates on the operands
of a
:
>> unfreeze(a)
+- -+ | 2 3 | | n n n | | 0, - + -- + -- | | 6 2 3 | +- -+
This means that for library domains, the effect of
unfreeze
is specified by the method "maprec"
.
If the domain does not implement this method, then
unfreeze
does not operate on the objects of this domain.
For example, we create a dummy domain and an object containing an
inactive function as its operand:
>> dummy := newDomain("dummy"): o := new(dummy, freeze(int)(sin(x), x = 0..2*PI))
new(dummy, int(sin(x), x = 0..2 PI))
The function unfreeze
applied to the object
o
has no effect:
>> unfreeze(o)
new(dummy, int(sin(x), x = 0..2 PI))
If we overload the function misc::maprec
in
order to operate on the first operand of objects of the domain
dummy
, then unfreeze
operates on
o
as desired:
>> dummy::maprec := x -> extsubsop(x, 1 = misc::maprec(extop(x,1), args(2..args(0))) ): unfreeze(o)
new(dummy, 0)
[
[