Documentation Center

  • Trial Software
  • Product Updates

Variables Inside Procedures

Closures

When you call a procedure, MuPAD® allocates memory for the local variables, marks them as uninitialized, and evaluates the body of the procedure. At the end of a procedure call, MuPAD destroys local variables freeing the allocated memory. Now suppose that the result of a procedure call refers to local variables of that procedure. For example, the returned value of this procedure refers to its local variable z:

f :=
proc(x, y)
  local z;
begin
  z := x + y;
  return(z);
end:

In this case, the variable z is replaced by its value at the end of the procedure call. Therefore, the returned value of the procedure is the value of the variable z, not the variable z itself:

f(1, 2)

Use hold to suppress evaluation of the variable z. Now the procedure returns an object of type DOM_VAR:

f :=
proc(x, y)
  local z;
begin
  z := x + y;
  return(hold(z));
end:
f(1, 2)

Objects of type DOM_VAR represent local variables and can only be used inside procedures. An object of type DOM_VAR returned as a result of a procedure call is useless because it does not have any connection to the procedure.

You can access local variables of a procedure if you either declare them in that procedure or declare them in a lexically enclosing procedure. For example, in the following code the procedure g can access and modify the variable x of the enclosing procedure f:

f :=
proc(x)
  local g;
begin
  g := proc()
  begin
    x := x+1;
  end:
  g();
end:
f(2)

Instead of returning the result of the procedure call g(), you can return g itself. In this case, the returned value retains a link to the variable x of the procedure call. For reasons of memory management, f must declare that it will return something holding a reference to a local variable. To declare it, use option escape:

f :=
proc(x)
  local g;
  option escape;
begin
  g := proc()
  begin
    x := x+1;
  end:
  g;
end:
h := f(2):
i := f(17):
h(); h(); i(); h()

This programming construct is called a closure. It is supported in many programming languages.

Static Variables

Alternative to Static Variables in MuPAD

Many programming languages support the concept of static variables. Static variables are local variables the values of which are not reset in each call to a procedure. The value of a static variable is initialized during the first call to a procedure. In each subsequent call, a procedure remembers the value of a static variable from the previous call.

Although MuPAD does not let you declare a variable inside a procedure as a static variable, you can still use the concept of static variables while programming in MuPAD.

When defining a procedure with proc, you often assign the procedure to an identifier. However, MuPAD lets you use anonymous procedures. Also, you can define one procedure inside another procedure. Thus, you can implement the alternative to a static variable in MuPAD as a nested procedure where:

  1. The outer procedure has a local variable. The outer procedure can be anonymous.

  2. The inner procedure uses the local variable of the outer procedure. For the inner procedure that variable is not local, and therefore it does not reset its value in each call.

For example, this code implements cnt as a static variable in MuPAD:

proc()
  local cnt;
  option escape;
begin
  cnt := 0;
  f :=
  proc()
  begin
    cnt := cnt + 1;
  end:
end():
f(); f(); f()

Shared Static Variables

The technique of creating static variables in MuPAD lets you create shared static variables by creating several inner procedures. The inner procedures use the same local variable of the outer procedure. For inner procedures that variable is not local, and therefore it does not reset its value:

proc()
  local x, y;
  option escape;
begin
  x := 0; 
  y := 0;
  f := () -> (x := x + y; [x, y]);
  g := n -> (y := y + n; [x, y]);
end_proc():
f();
g(2);
f();
f()

Was this topic helpful?