You can define utility functions inside a procedure. For example,
define the utility function,
helper, inside the
f := proc(arguments) local helper, ...; begin helper := proc(...) begin ... end: ... code using helper(...) ... end:
helper function is not visible or accessible
f. Your users cannot see the
and therefore, they do not rely on a particular implementation of
this procedure. You can change its implementation without breaking
their code. At the same time,
helper can access
and modify arguments of
The major disadvantage of this approach is that your test files
helper directly. Since it is typically
recommended to start testing at the smallest possible building blocks,
this is a real disadvantage. Nevertheless, for many tasks the benefits
of this approach prevail over this disadvantage, especially if the
utility function must be able to modify the arguments of the calling
You can define utility functions outside a procedure. For example,
define the utility function,
helper, in the function
f := funcenv( proc(arguments) local ...; begin ... code using f::helper(...) ... end): f::helper := proc(...) begin ... end:
This approach does not require you to define the utility function
in the function environment of the procedure that uses it. Defining
a utility function in the function environment only helps you clarify
to people reading your code that you intend to call
or solely within
f. If you later decide to use
another procedure, you can move the utility function to a more generic
utility library. Again, this recommendation only helps you improve
readability of your code.
Defining utility functions outside the procedure that uses them does not hide utility functions. Therefore, this approach lets you:
Test utility functions directly.
Define a utility function and a function that uses it in different source files.
Use the same utility function for different procedures.
Defining utility functions outside the procedure that uses them has the following disadvantages:
Your users can access utility functions. If they rely on a particular implementation of the utility function, changing that implementation might affect their code.
The utility function cannot access local variables of the procedure that uses that utility function. The workaround is to pass these local variables as arguments to the utility function.
The utility function does not have privileged access to the arguments of the procedure that uses that utility function.
Defining the utility function far from the code line where you call it reduces readability of the code.
Be careful when defining utility functions in slots of a function
environment because MuPAD® uses these slots for overloading. Do
not define utility functions with such names as
f::simplify unless you want to use these utility
functions for overloading.
You can define a utility function and all procedures that use
it inside one procedure. In this case, you must also define the utility
function as a local variable of that outer procedure. The outer procedure
can be anonymous. For example, create the anonymous procedure that
has a local variable
helper and includes the utility
helper and two other procedures,
that use the utility function:
proc() local helper; option escape; begin helper := proc(...) ... end: f := proc(arguments) local ...; begin ... code using helper(...) ... end: g := proc(arguments) local ...; begin ... code using helper(...) ... end: end():
If you define a utility function in a closure, that function
is inaccessible to any external code. Your users cannot see and, therefore,
rely on a particular implementation of that utility function. Changing
it will not break their code. At the same time, this approach lets
you create more than one procedure that can access the utility function.
In the example, both
The disadvantage of this approach is that the helper function
cannot access the local variables of the procedures that use it. To
overcome this limitation, you can use the
context function or shared
overcome this limitation typically leads to unreadable and difficult
to maintain code. The problems with shared static variables resemble
the problems with global variables, especially for recursive calls.
The helper procedure can access and modify such variables, but all
other procedures inside the same outer procedure can access and modify