Handle Functions
What's new in Analytica 4.0? >
About Handles (varTerms)
A handle (formerly known as varTerm) is a reference or pointer to a variable, index, function, module, or other Analytica object. Using a handle lets you write variables or functions that works with the object itself rather than the value of the object. Usually, if you refer to variable X in an expression, say as:
Variable X := 100 Variable A := X
The value of A will be equal to the value of X, namely 100. But if you write:
Variable B := Handle(X)
Using a Handle lets you find or change the Title, Description, Inputs or Outputs. You can also create and use lists of handles to objects. For example, the list of indexes of an array, or the inputs or outputs of a variable.
If you define a variable as a list of variables:
Variable A := [X, Y, Z]
the value of A will be the result of evaluating X, Y, and Z. The index of A is a list of handles to X, Y, and Z. It usually shows the titles of X, Y, and Z. If you double-click a titles in the index in a Table window, it opens the Object view for that object. If "Show By Identifier" is on (from the Object menu, or if you toggle it with control-Y), the index shows identifiers rather than titles. Either way, you can double click to open the object view.
Some attributes consist of lists of handles, notably Inputs, Outputs, and Contains (the objects in a module). You can use these to write functions to find the ancestors, descendants, or contents of an object.
Handle(v)
Returns a handle (pointer or reference) to object v.
Function Handle( X : Variable ; AsIndex : optional boolean atomic )
If you want to create a user-defined function that returns a Handle, in most cases the return value needs to involve a call to the Handle function. If you simply place the identifier of a local variable (even if it declared as Variable) as the return value, it will be evaluated. For example, consider these two functions:
Function Fu1( X : Variable ) := X Function Fu2( X : Variable ) := Handle(X) Variable Va1 := 5
Suppose you evaluate Fu1(Va1) and Fu2(Va1). Fu1 returns the value of Va1, that is 5. Fu2 returns a handle to the Va1 object. Hence, to return a Handle, a call to Function Handlewas necessary.
You can declare a local variable to be a Handle using, for example,
var a := Handle(Va1) do ...
where Va1 is the identifier of an object. In the scope of this var declaration, a then becomes an alias for Va1. In other words, anywhere you might use the identifier Va1 in an expression, you could equivalently use a.
To create an alias to an index, use
var I := Handle( In1, AsIndex:True ) do ...
The local variable I will then serve as an alias to the original index In1 inside the scope of this var statement. The AsIndex parameter causes I's index values to be used when I appears in a value context (this is relevant when the original object is a self-indexed array, having both a value and an index value).
When an index has handles as elements, and you wish to subscript across that index, the recommended syntax is:
A[ I = Handle(x) ]
In this example, x would be the identifier appearing as one of the elements of I.
Function HandleFromIdentifier
HandleFromIdentifier( varName : atomic text )
(formerly GetVariableByName).
Finds an object in the global namespace having the indicated name and returns a handle to that object. If no such object exists, returns Null (use IsUndef to test for null if you worry about backward compatibility).
One danger with using this function is that Analytica has no dependency influence information. For example, the following expression
var x := HandleFromIdentifier("Va1") do x
evaluates Va1 and returns that value; however, if Va1 were to change, Analytica would have no way of knowing that this result needs to be invalidated. Obviously, in this example, it would better to use just the identifier Va1 in the expression, but as a basis of comparison, note that Analytica would be aware of the dependency influence if this variation were used:
var x:= Handle(Va1) do x
If the value of Va1 changes, it would know that this value needs to be re-computed.
Handle to Caller of a UDF
(note: This does not need to be mentioned in the user-guide)
A special case, HandleFromIdentifier("_Caller"), can be used in a user-defined function to obtain a handle to the variable or button that invoked the function. From a nested function, the variable or button that invoked the parent function is returned. The tag "_Caller" will not conflict with an identifier since identifiers may not begin with an underscore.
Using this, it is possible to create a function that bases its behavior based on a property of the variable that invokes it. Your function might, for example, use the value of a User-Defined Attribute (UDA) of the calling variable.
Function IndexesOf
IndexesOf( A : Array )
Returns a list of handles, each one serving as a handle to the indexes of array A.
This is similar to IndexNames(A), except that IndexesOf returns actual handles, while IndexNames returns the index identifiers (as text strings).
It is possible for an array to have more than one local index having identical names. Obviously, this is not recommended, but in the unusual case where this occurs, the index handles returned by IndexesOf are unambiguous.
Local Variables and Handles
The value of a local variable, like a global variable, may be a number, text, or handle or an array or scalar. If its value is a single handle (not an array), it acts as an alias to the object whose handle it contains. In that case, the identifier of the local variable is equivalent the identifier of that object in any expression expecting an identifier. For example:
VAR v := HandleFromIdentifier('X'); Title OF v --> 'Title of X'
This treatment of local variables when they contain a single handle is subject to change prior to the Analytica 4.0 release. See Proposed Change to Local Variables and Handles.
Enable comment auto-refresher