Local functions and local value captures
- The feature described in this page is experimental and not officially "exposed" or supported and is subject to change in future releases. It requires Analytica 6.0 or later.
Local functions
A local function is a callable entity that is defined within an expression. It does not exist in the global namespace, so like a local value its identifier is only visible within the local scope. In addition, unlike a UDF, a local function is a type of value rather than an object -- i.e., it behaves as a data type and has no attributes of its own.
You can treat a local function as you would a data element like a number -- you can have arrays of local functions, can assign local functions to other local function identifiers, etc. Calling a local function uses the same syntax as any other function call in Analytica. Local functions array abstract and use the same parameter declaration syntax and qualifiers that UDFs use.
In other programming languages, these are called lambda functions, or sometimes just lambdas.
Local functions have an extra special power, which is that they can capture other local values. This is described below.
A local function is created within an expression using the following syntax:
- Function «ident»( «parameter declarations» ) : «expression» Do «body»
or
- Function «ident»( «parameter declarations» ) : « expression»;
- ...
It is important to note the use of a colon (and not :=
, which has a different meaning) between the parameter declaration and the «expression» that defines the function.
The following is a simple example that computes [math]\displaystyle{ x^2 ( x^2 + 1) }[/math]:
Function sqr(x) : x^2 Do sqr(x) * (sqr(x) + 1)
Local function identifiers
A local function identifier is an identifier with local scope that can hold either a local function or a function object (such as a built-in function or a UDF). Local function identifiers must be declared along with a parameter declaration. There is a subtle distinction between the terms "local function" and "local function identifier". Basically a local function identifier is a name of a local that can hold a function (whether local or global) and be called using the standard calling syntax, whereas a local function is the actual data value that corresponds to one particular function. You can assign to a local function identifier, therefore changing which function it is holding.
When you declare a local function as shown in the previous section, you also declare a local function identifier. The converse is not true. There are several ways you can declare a local function identifier without declaring a now local function, show here by example.
Function F1( x,y );
- Initially F1 is Null. Your code will probably assign a function to it later.
Function F2( x,y ) := «expression»;
- Here «expression» must evaluate to one of: (1) A handle to a built-in function with compatible parameters, (2) A handle to a UDF with compatible parameters, (3) A local function with compatible parameters, (4) Null, or (5) An array of any of these.
- Notice that
:=
is used to separate the parameters from the expression. This is an assignment and as opposed to a definition which uses a colon.
- Function Quadrature( f : Function ( x ) atom ; x1,x2 : atom )
- Here a parameter of a parent function, Quadrature, is declared to be a local function identifier. The caller might pass a handle to a function object (UDF or built-in function), a local function, or Null.
Calling
The syntax for calling a local function identifier is exactly the same as the syntax for calling any other function in Analytica. The identifier is followed by a left parenthesis, the arguments to be passed, and a closing parenthesis. You can use positional or named calling syntax just as with a function.
One slight difference is that a local function identifier might actual hold an array of functions, or might be Null. When it has an array of functions, it array abstracts, calling each function with the given arguments and collecting the results. When you attempt to call a Null, the result is Null.
Enable comment auto-refresher