## `context` -- evaluate an object in the enclosing context

#### Introduction

Within a procedure, `context(`object`)` evaluates `object` in the context of the calling procedure.

#### Call(s)

`context(object)`

#### Parameters

`object` | - | any MuPAD object

#### Returns

the evaluated object.

#### Side Effects

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

#### Related Functions

`DOM_PROC`, `eval`, `freeze`, `hold`, `LEVEL`, `level`, `MAXLEVEL`, `proc`

#### Details

- Most MuPAD procedures evaluate their arguments before executing the body of the procedure. However, if the procedure is declared with option `hold`, then the arguments are passed to the procedure unevaluated. `context` serves to evaluate such arguments a posteriori from within the procedure.
- Like most MuPAD procedures, `context` first evaluates its argument `object` as usual in the context of the current procedure. Then the result is evaluated again in the dynamical context that was valid before the current procedure was called. The enclosing context is either the interactive level or the procedure that called the current procedure.
- `"`func_call"-methods of domains never evaluate their arguments, whether the option `hold` is used or not. See example 2.
- `context` 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 takes place with the value of `LEVEL` that is valid in the current procedure, which is `1` by default. The second evaluation uses the value of `LEVEL` that is valid in the enclosing context, which is usually `1` if the enclosing context is also a procedure, while it is `100` by default if the enclosing context is the interactive level. See example 3.

- The function `context` must not be called at interactive level, and `context` calls must not be nested. Thus it is not possible to evaluate an object in higher levels of the dynamical call stack. See example 4.

- `context` is a function of the system kernel.

#### Example 1

We define a procedure `f` with option `hold`. If this procedure is called with an identifier as argument, such as `a` below, the `identifier` itself is the actual argument inside of `f`. `context` may be used to get the value of `a` in the outer context:

    >> a := 2:
       f := proc(i)
              option hold;
            begin
              print(i, context(i), i^2 + 2, context(i^2 + 2));
            end_proc:
       f(a):

                                         2
                                  a, 2, a  + 2, 6

If a procedure with option `hold` is called from another procedure you will see strange effects if the procedure with option `hold` does not evaluate its formal parameters with `context`. Here, the value of the formal parameter `j` in `g` is the `variable` `i` which is defined in the context of procedure `f` and not its value `4`. When you want to access the value of this variable you have to use `context`, otherwise you see the output `DOM_VAR(0,2)` which is the variable `i` of `f` which has lost its scope:

    >> f := proc()
              local i;
            begin
              i := 4:
              g(i);
            end_proc:
       g := proc(j)
              option hold;
            begin
              print(j, eval(j), context(j));
              print(j + 1)
            end_proc:
       f()

                           DOM_VAR(0,2), DOM_VAR(0,2), 4

                                 DOM_VAR(0,2) + 1

#### Example 2

The `"`func_call" method of a domain is implicitly declared with `option hold`. We define a `"func_call"` method for the domain `DOM_STRING` of MuPAD strings. The slot routine converts its remaining arguments into strings and appends them to the first argument, which coincides with the string that is the 0th operand of the function call:

    >> unprotect(DOM_STRING):
       DOM_STRING::func_call :=
         string -> _concat(string, map(args(2..args(0)), expr2text)):
       a := 1:  "abc"(1, a, x)

                                     "abc1ax"

You see that the identifier `a` was added to the string, and not its value `1`. Use `context` to access the value that `a` has before the `"func_call"` method is invoked:

    >> DOM_STRING::func_call :=
         string -> _concat(string, map(context(args(2..args(0))),
                                       expr2text)):
       "abc"(1, a, x);
       delete DOM_STRING::func_call:  protect(DOM_STRING, Error):

                                     "abc11x"

#### Example 3

This example shows the influence of the environment variable `LEVEL` on the evaluation of `context` and the differences to the functions `eval` and `level`. `p` is a function with option `hold`. `x` is a formal parameter of this procedure. When evaluating their arguments `context`, `eval` and `level` all replace `x` first by its value `a`. Then `eval` evaluates `a` in the current context with `LEVEL = 1` and yields the value `b`. `context` evaluates `a` in the enclosing context (which is the interactive level) with `LEVEL = 100` and yields `c`. `level` always returns the result of the first evaluation step, which is `a`.

When the `LEVEL` of the interactive level is `1`, `context` returns `b` like `eval` since the second evaluation is performed with `LEVEL = 1` like in `eval`.

The local variable `b` of `p` does not influence the evaluation in `context`, `eval` and `level` since it is only a locally declared variable of type `DOM_VAR` which has nothing to do with the identifier `b`, which is the value of `a`:

    >> delete a, b, c:  a := b:  b := c:
       p := proc(x)
              option hold;
              local b;
            begin
              b := 2;
              eval(x), context(x), level(x), level(x,2);
            end:
       p(a);
       LEVEL := 1: p(a);
       delete LEVEL:

                                    b, c, a, a

                                    b, b, a, a

#### Example 4

The function `context` must not be called at interactive level:

    >> context(x)

          Error: Function call not allowed on interactive level [context]

#### Changes

- Due to the lexical scoping, `context` only makes sense in procedures with option `hold`.

Do you have questions or comments?
Copyright © SciFace Software GmbH & Co. KG 2000