Difference between revisions of "Handles to Objects"
Jhernandez3 (talk | contribs) |
Jhernandez3 (talk | contribs) m |
||
Line 15: | Line 15: | ||
:<code>Variable A := [X, Y, Z]</code> | :<code>Variable A := [X, Y, Z]</code> | ||
− | the variable will have a self index that is a list of handles to those variables. In a table result view of A (or other variable that uses this index), the index A will usually show the titles of the variables. See “List of variables” on page 175 for more. In an expression, the handles in the self index can | + | the variable will have a self index that is a list of handles to those variables. In a table result view of A (or other variable that uses this index), the index A will usually show the titles of the variables. See “List of variables” on page 175 for more. In an expression, the handles in the self index can be accessed using IndexValue(A). The main value of A (either mid value or a probabilistic view of A) contains the results of evaluating X, Y and Z. |
− | be accessed using IndexValue(A). The main value of A (either mid value or a probabilistic view of A) contains the results of evaluating X, Y and Z. | ||
== Handle(o) == | == Handle(o) == | ||
Returns a handle to an Analytica object, given its identifier <code>o</code>. | Returns a handle to an Analytica object, given its identifier <code>o</code>. | ||
− | <code>Handle(Va1) ¨ Va1</code> | + | :<code>Handle(Va1) ¨ Va1</code> |
== HandleFromIdentifier(text) == | == HandleFromIdentifier(text) == | ||
Returns a handle to global object (i.e., not a local variable or parameter), given its identifier as <code>text</code>. | Returns a handle to global object (i.e., not a local variable or parameter), given its identifier as <code>text</code>. | ||
− | <code>Variable B := 99< | + | :<code>Variable B := 99</code> |
+ | :<code>HandleFromIdentifier("B") → Va1</code> | ||
The dependency maintenance is unaware of the dependency on the object. Hence, any changes to the variable <code>B</code> above will not cause the result to recompute. | The dependency maintenance is unaware of the dependency on the object. Hence, any changes to the variable <code>B</code> above will not cause the result to recompute. | ||
Line 33: | Line 33: | ||
Returns a list of handles to the specified Analytica objects, given their identifiers. | Returns a list of handles to the specified Analytica objects, given their identifiers. | ||
− | <code>ListOfHandles(Va1,Va2,Va3) ¨ [Va1,Va2,Va3]</code> | + | :<code>ListOfHandles(Va1,Va2,Va3) ¨ [Va1,Va2,Va3]</code> |
== Indexes of Handles == | == Indexes of Handles == | ||
Line 41: | Line 41: | ||
its definition to obtain its mid or sample value, and the values that are recognized by Subscript (i.e., a[i=x]), while a meta-index (having its metaOnly attribute set to 1) does not evaluate the objects in the list. The following comparisons demonstrates the similarities and differences. | its definition to obtain its mid or sample value, and the values that are recognized by Subscript (i.e., a[i=x]), while a meta-index (having its metaOnly attribute set to 1) does not evaluate the objects in the list. The following comparisons demonstrates the similarities and differences. | ||
− | <code>Constant E:= exp(1)< | + | :<code>Constant E:= exp(1)</code> |
+ | :<code>Variable X := -1</code> | ||
:{| border="1"; | :{| border="1"; | ||
Line 81: | Line 82: | ||
The construct, <code>MetaIndex i := indexExpr</code>, declares a local meta-index (see [http://wiki.analytica.com/index.php?title=Local_Indexes Local indexes]). This should generally be used in lieu of the Index <code>i := indexExpr</code> construct when <code>indexExpr</code> evaluates to a list of handles. | The construct, <code>MetaIndex i := indexExpr</code>, declares a local meta-index (see [http://wiki.analytica.com/index.php?title=Local_Indexes Local indexes]). This should generally be used in lieu of the Index <code>i := indexExpr</code> construct when <code>indexExpr</code> evaluates to a list of handles. | ||
− | <code>MetaIndex I := contains of Revenue_Module;< | + | :<code>MetaIndex I := contains of Revenue_Module;</code> |
− | Description of (I)</code> | + | :<code>Description of (I)</code> |
== IndexesOf(X) == | == IndexesOf(X) == | ||
Line 88: | Line 89: | ||
== Local Variables and Handles == | == Local Variables and Handles == | ||
− | When you declare and use local variables that might hold handles, you should declare these local variables using <code>MetaVar..Do or LocalAlias..Do</code>, rather than <code>Var..Do or For..Do</code>. When local variables hold handles, there are two semantic interpretations — the local variable could either be a | + | When you declare and use local variables that might hold handles, you should declare these local variables using <code>MetaVar..Do or LocalAlias..Do</code>, rather than <code>Var..Do or For..Do</code>. When local variables hold handles, there are two semantic interpretations — the local variable could either be a storage location for a handle to an object, or it could act as an alias to the object. The <code>Meta-Var..Do</code> or <code>LocalAlias..Do</code> declarations makes this distinction clear. |
− | storage location for a handle to an object, or it could act as an alias to the object. The <code>Meta-Var..Do</code> or <code>LocalAlias..Do</code> declarations makes this distinction clear. | ||
== MetaVar..Do == | == MetaVar..Do == | ||
The construct, <code>MetaVar temp := expr</code>, declares a local variable named <code>temp</code> that holds an atomic value or an array of values, some of which might be handles. When the value is a handle, the handle is treated as just another entity, whose datatype happens to be a handle. If you assign another handle or value to temp, you simply change the contents of the local variable, and do not alter the object that the handle points to. Use this construct to manage collections of handles. | The construct, <code>MetaVar temp := expr</code>, declares a local variable named <code>temp</code> that holds an atomic value or an array of values, some of which might be handles. When the value is a handle, the handle is treated as just another entity, whose datatype happens to be a handle. If you assign another handle or value to temp, you simply change the contents of the local variable, and do not alter the object that the handle points to. Use this construct to manage collections of handles. | ||
− | <code>MetaVar hRevModule := Handle(Revenue_module);< | + | :<code>MetaVar hRevModule := Handle(Revenue_module);</code> |
+ | :<code>MetaVar hExpModule := Handle(Expense_module);</code> | ||
+ | :<code>MetaIndex m := [hRevModule,hExpModule];</code> | ||
+ | :<code>...</code> | ||
For the next example, suppose a global variable named <code>Hy</code> exists with a definition of <code>Handle(Y)</code>. | For the next example, suppose a global variable named <code>Hy</code> exists with a definition of <code>Handle(Y)</code>. | ||
− | <code>MetaVar a := Handle(X);< | + | :<code>MetaVar a := Handle(X);</code> |
+ | :<code>a := Hy</code> | ||
Following the assignment, the local variable <code>a</code> contains a handle to <code>Y</code>. The variable <code>X</code> is unaltered. You should compare this to the same example using <code>LocalAlias..Do</code> in the following section. | Following the assignment, the local variable <code>a</code> contains a handle to <code>Y</code>. The variable <code>X</code> is unaltered. You should compare this to the same example using <code>LocalAlias..Do</code> in the following section. | ||
Line 104: | Line 108: | ||
When you need to iterate over a collection of handles, you can use, e.g., | When you need to iterate over a collection of handles, you can use, e.g., | ||
− | <code>MetaVar h[ ] := Contains of Revenue_module;</code> | + | :<code>MetaVar h[ ] := Contains of Revenue_module;</code> |
You can assign non-handle values, such as numbers or text, to a local variable declared with <code>MetaVar</code>. When you do so, there is no difference between <code>MetaVar..Do</code> and <code>Var..Do</code>. | You can assign non-handle values, such as numbers or text, to a local variable declared with <code>MetaVar</code>. When you do so, there is no difference between <code>MetaVar..Do</code> and <code>Var..Do</code>. | ||
Line 111: | Line 115: | ||
The construct, <code>LocalAlias temp := expr</code>, evaluates <code>expr</code> and declares a local variable named <code>temp</code> that holds a single atomic value. When <code>expr</code> evaluates to a handle, the local variable identifier acts as an exact alias to the object pointed to by the handle. | The construct, <code>LocalAlias temp := expr</code>, evaluates <code>expr</code> and declares a local variable named <code>temp</code> that holds a single atomic value. When <code>expr</code> evaluates to a handle, the local variable identifier acts as an exact alias to the object pointed to by the handle. | ||
− | <code>LocalAlias r := Handle(Rate_input) Do r := r * 1.1</code> | + | :<code>LocalAlias r := Handle(Rate_input) Do r := r * 1.1</code> |
The preceding expression is functionally identical to<ref>This expression contains a side-effect to a global variable. Side-effects to global variables are only allowed in expressions or user-defined functions that are run directly from button scripts. This would cause an error if attempted from a variable’s definition.</ref> | The preceding expression is functionally identical to<ref>This expression contains a side-effect to a global variable. Side-effects to global variables are only allowed in expressions or user-defined functions that are run directly from button scripts. This would cause an error if attempted from a variable’s definition.</ref> | ||
− | <code>Rate_input := Rate_input * 1.1</code> | + | :<code>Rate_input := Rate_input * 1.1</code> |
For the next example, suppose a global variable named <code>Hy</code> exists with a definition of <code>Handle(Y)</code>. | For the next example, suppose a global variable named <code>Hy</code> exists with a definition of <code>Handle(Y)</code>. | ||
− | <code>LocalAlias a := Handle(X)< | + | :<code>LocalAlias a := Handle(X)</code> |
+ | :<code>a := Hy</code> | ||
This expression is functionally identical to | This expression is functionally identical to | ||
− | <code>X := Hy</code> | + | :<code>X := Hy</code> |
The expression, if evaluated in a context where side-effects are permitted, would alter the definition of <code>X</code>. Following the assignment to <code>a</code>, the local variable <code>a</code> continues to be an alias to <code>X</code>. You should compare this to the same example for <code>MetaVar..Do</code> in the preceding section. | The expression, if evaluated in a context where side-effects are permitted, would alter the definition of <code>X</code>. Following the assignment to <code>a</code>, the local variable <code>a</code> continues to be an alias to <code>X</code>. You should compare this to the same example for <code>MetaVar..Do</code> in the preceding section. | ||
Line 129: | Line 134: | ||
When <code>expr</code> is an array of handles, then the body expression is iterated for each alias. The following expression increases the definition of every global variable within an indicated module to a value 1.1 times its initial value. | When <code>expr</code> is an array of handles, then the body expression is iterated for each alias. The following expression increases the definition of every global variable within an indicated module to a value 1.1 times its initial value. | ||
− | <code>LocalAlias x := Contains of Input_module;< | + | :<code>LocalAlias x := Contains of Input_module;</code> |
− | x := x * 1.1</code> | + | :<code>x := x * 1.1</code> |
The rule for <code>LocalAlias</code> is that the result for the expressions using <code>temp</code> are identical to what you would get if you replaced every occurrence of <code>temp</code> within those expressions with the identifier for the variable pointed to by the handle, and then evaluated the expressions<ref>Not every object in Analytica lives in the global namespace (e.g., local indexes), so this rule doesn’t literally apply for handles to objects not in the global namespace. For these, we cannot replace the local name with an identifier since no global identifier exists for the object pointed to by the handle.</ref>. | The rule for <code>LocalAlias</code> is that the result for the expressions using <code>temp</code> are identical to what you would get if you replaced every occurrence of <code>temp</code> within those expressions with the identifier for the variable pointed to by the handle, and then evaluated the expressions<ref>Not every object in Analytica lives in the global namespace (e.g., local indexes), so this rule doesn’t literally apply for handles to objects not in the global namespace. For these, we cannot replace the local name with an identifier since no global identifier exists for the object pointed to by the handle.</ref>. | ||
Line 137: | Line 142: | ||
just want a simple alias. If you write | just want a simple alias. If you write | ||
− | <code>LocalAlias x := y</code> | + | :<code>LocalAlias x := y</code> |
then this assigns to <code>x</code> the value of <code>y</code>, not a handle to the object <code>y</code>. If <code>y</code> happens to hold a handle to <code>z</code>, then <code>x</code> becomes an alias to <code>z</code>, not an alias to <code>y</code>. To obtain an alias for <code>y</code>, you must use | then this assigns to <code>x</code> the value of <code>y</code>, not a handle to the object <code>y</code>. If <code>y</code> happens to hold a handle to <code>z</code>, then <code>x</code> becomes an alias to <code>z</code>, not an alias to <code>y</code>. To obtain an alias for <code>y</code>, you must use | ||
− | <code>LocalAlias x := Handle(y);</code> | + | :<code>LocalAlias x := Handle(y);</code> |
You can assign non-handle values, such as numbers and text, to a <code>LocalAlias</code> variable. When you do so, the local variable identifier serves as an alias for a single value, and is the same as | You can assign non-handle values, such as numbers and text, to a <code>LocalAlias</code> variable. When you do so, the local variable identifier serves as an alias for a single value, and is the same as | ||
− | <code>Var temp[] := expr;.</code> | + | :<code>Var temp[] := expr;.</code> |
== Conversions between MetaVar and LocalAlias == | == Conversions between MetaVar and LocalAlias == | ||
Line 151: | Line 156: | ||
following expression is an error | following expression is an error | ||
− | <code>MetaVar hr := Handle(Revenue) Do hr - Expenses { Error }</code> | + | :<code>MetaVar hr := Handle(Revenue) Do hr - Expenses { Error }</code> |
The expression is attempting to subtract the value of expenses (a number) from a handle. In this example, we need the <code>LocalAlias</code> semantics instead, so given <code>hr</code> we can convert using | The expression is attempting to subtract the value of expenses (a number) from a handle. In this example, we need the <code>LocalAlias</code> semantics instead, so given <code>hr</code> we can convert using | ||
− | <code>MetaVar hr := Handle(Revenue);< | + | :<code>MetaVar hr := Handle(Revenue);</code> |
− | LocalAlias r := hr;< | + | :<code>LocalAlias r := hr;</code> |
− | r - Expenses</code> | + | :<code>r - Expenses</code> |
A <code>MetaVar</code> can also be dereferenced by using the [http://wiki.analytica.com/index.php?title=Evaluate Evaluate]() function: | A <code>MetaVar</code> can also be dereferenced by using the [http://wiki.analytica.com/index.php?title=Evaluate Evaluate]() function: | ||
− | <code>MetaVar hr := Handle(Revenue) Do Evaluate(hr) - Expenses</code> | + | :<code>MetaVar hr := Handle(Revenue) Do Evaluate(hr) - Expenses</code> |
− | + | In the other direction, when a <code>LocalAlias</code>, <code>r</code>, is an alias for another object and you need the handle to the object, use <code>Handle(r)</code>. It is legal to use the <code>Handle()</code> function on a local variable declared using <code>LocalAlias</code>, but it is an error to apply the <code>Handle()</code> function to a local variable defined using <code>MetaVar</code>. This is because a local variable is not an object (it is just a name for a value), and since handles can only point to objects, there is no such thing as a handle to a local variable<ref>A local index is an object, so you can have a handle to a local index. The '''Index..Do''' and '''MetaIndex..Do''' constructs create an index object, along with a local variable name that has '''LocalAlias''' semantics for the index object.</ref>. | |
<footer>References and Data Structures / {{PAGENAME}} / Dialog Functions</footer> | <footer>References and Data Structures / {{PAGENAME}} / Dialog Functions</footer> |
Revision as of 14:55, 20 December 2015
A handle is a pointer to a variable, function, module, or other object. Using a handle lets you write variables or functions that work with the object itself, for example to access its attributes — instead of just its value which is what you usually get when you mention a variable by identifier in an expression.
Viewing handles
In a table result, a handle in an index or content cell usually shows the title of the object. If you select Show by identifier from the Object menu (or press Control+y), it toggles to show identifiers instead of titles (as it does in the node diagrams). If you double-click a cell containing a handle (title or identifier) it opens its Object window (as it does when you double-click a node in a diagram).
Attributes that contain handles
The attributes, inputs, outputs, and contains (the list of objects in a module) each consist of a list of handles to objects. The attribute isIn is a single handle to the module that contains this object — the inverse of contains.
List of variables: [v1, v2, ... vn]
If you define a variable as a list of variables, for example,
Variable A := [X, Y, Z]
the variable will have a self index that is a list of handles to those variables. In a table result view of A (or other variable that uses this index), the index A will usually show the titles of the variables. See “List of variables” on page 175 for more. In an expression, the handles in the self index can be accessed using IndexValue(A). The main value of A (either mid value or a probabilistic view of A) contains the results of evaluating X, Y and Z.
Handle(o)
Returns a handle to an Analytica object, given its identifier o
.
Handle(Va1) ¨ Va1
HandleFromIdentifier(text)
Returns a handle to global object (i.e., not a local variable or parameter), given its identifier as text
.
Variable B := 99
HandleFromIdentifier("B") → Va1
The dependency maintenance is unaware of the dependency on the object. Hence, any changes to the variable B
above will not cause the result to recompute.
ListOfHandles(identifiers...)
Returns a list of handles to the specified Analytica objects, given their identifiers.
ListOfHandles(Va1,Va2,Va3) ¨ [Va1,Va2,Va3]
Indexes of Handles
MetaOnly attribute
When an index object is defined as a list of identifiers, the MetaOnly attribute controls whether it is treated as a general index or a meta-index. Meta-indexes are useful when reasoning about the structure or contents of the model itself. A general index evaluates the variables appearing in its definition to obtain its mid or sample value, and the values that are recognized by Subscript (i.e., a[i=x]), while a meta-index (having its metaOnly attribute set to 1) does not evaluate the objects in the list. The following comparisons demonstrates the similarities and differences.
Constant E:= exp(1)
Variable X := -1
General Index Meta-Index Index I0 := [E,X,Pi,True] Index I1 := [E,X,Pi,True] MetaOnly of I0 := 0 {or not set} MetaOnly of I1 := 1 Variable A0 := Table(I0)(1,2,3,4) Variable A1 := Table(I1)(1,2,3,4) IndexValue(I0) → [E,X,Pi,True] IndexValue(I1) → [E,X,Pi,True] Mid(I0) → 2.718,-1,3.142,1] Mid(I1) →[E,X,Pi,True] A0[I0=Handle(E)] → 1 A1[I1=Handle(E)] → 1 A0[I0=Handle(True)] → 4 A1[I1=Handle(True)] → 4 A0[I0=E] → 1 A1[I1=E] → Error:-2.718 not in I1 A0[I0=-1] → 2 A1[I1=-1] → Error:-1 not in I1 A0[I0=True] → 4 A1[I1=True] → Error:1 not in I1
MetaIndex..Do
The construct, MetaIndex i := indexExpr
, declares a local meta-index (see Local indexes). This should generally be used in lieu of the Index i := indexExpr
construct when indexExpr
evaluates to a list of handles.
MetaIndex I := contains of Revenue_Module;
Description of (I)
IndexesOf(X)
Returns the indexes of an array value as a list of handles. The first element of the list is null, rather than a handle, when X
has an implicit dimension (also known as a null-index).
Local Variables and Handles
When you declare and use local variables that might hold handles, you should declare these local variables using MetaVar..Do or LocalAlias..Do
, rather than Var..Do or For..Do
. When local variables hold handles, there are two semantic interpretations — the local variable could either be a storage location for a handle to an object, or it could act as an alias to the object. The Meta-Var..Do
or LocalAlias..Do
declarations makes this distinction clear.
MetaVar..Do
The construct, MetaVar temp := expr
, declares a local variable named temp
that holds an atomic value or an array of values, some of which might be handles. When the value is a handle, the handle is treated as just another entity, whose datatype happens to be a handle. If you assign another handle or value to temp, you simply change the contents of the local variable, and do not alter the object that the handle points to. Use this construct to manage collections of handles.
MetaVar hRevModule := Handle(Revenue_module);
MetaVar hExpModule := Handle(Expense_module);
MetaIndex m := [hRevModule,hExpModule];
...
For the next example, suppose a global variable named Hy
exists with a definition of Handle(Y)
.
MetaVar a := Handle(X);
a := Hy
Following the assignment, the local variable a
contains a handle to Y
. The variable X
is unaltered. You should compare this to the same example using LocalAlias..Do
in the following section.
When you need to iterate over a collection of handles, you can use, e.g.,
MetaVar h[ ] := Contains of Revenue_module;
You can assign non-handle values, such as numbers or text, to a local variable declared with MetaVar
. When you do so, there is no difference between MetaVar..Do
and Var..Do
.
LocalAlias..Do
The construct, LocalAlias temp := expr
, evaluates expr
and declares a local variable named temp
that holds a single atomic value. When expr
evaluates to a handle, the local variable identifier acts as an exact alias to the object pointed to by the handle.
LocalAlias r := Handle(Rate_input) Do r := r * 1.1
The preceding expression is functionally identical to[1]
Rate_input := Rate_input * 1.1
For the next example, suppose a global variable named Hy
exists with a definition of Handle(Y)
.
LocalAlias a := Handle(X)
a := Hy
This expression is functionally identical to
X := Hy
The expression, if evaluated in a context where side-effects are permitted, would alter the definition of X
. Following the assignment to a
, the local variable a
continues to be an alias to X
. You should compare this to the same example for MetaVar..Do
in the preceding section.
When expr
is an array of handles, then the body expression is iterated for each alias. The following expression increases the definition of every global variable within an indicated module to a value 1.1 times its initial value.
LocalAlias x := Contains of Input_module;
x := x * 1.1
The rule for LocalAlias
is that the result for the expressions using temp
are identical to what you would get if you replaced every occurrence of temp
within those expressions with the identifier for the variable pointed to by the handle, and then evaluated the expressions[2].
An easy mistake to make when using LocalAlias
is to forget that expr
is evaluated before the assignment. This feature allows you to compute the handle to the object that will be aliased, but it also means that you need to remember to surround an identifier with a call to Handle()
when you
just want a simple alias. If you write
LocalAlias x := y
then this assigns to x
the value of y
, not a handle to the object y
. If y
happens to hold a handle to z
, then x
becomes an alias to z
, not an alias to y
. To obtain an alias for y
, you must use
LocalAlias x := Handle(y);
You can assign non-handle values, such as numbers and text, to a LocalAlias
variable. When you do so, the local variable identifier serves as an alias for a single value, and is the same as
Var temp[] := expr;.
Conversions between MetaVar and LocalAlias
When writing expressions that manipulate handles in local variables, you may sometimes need to convert between MetaVar
and LocalAlias
semantics. When a MetaVar
holds a handle, its value is an entity with the data type of handle. Since subtraction is not defined for a handle, the
following expression is an error
MetaVar hr := Handle(Revenue) Do hr - Expenses { Error }
The expression is attempting to subtract the value of expenses (a number) from a handle. In this example, we need the LocalAlias
semantics instead, so given hr
we can convert using
MetaVar hr := Handle(Revenue);
LocalAlias r := hr;
r - Expenses
A MetaVar
can also be dereferenced by using the Evaluate() function:
MetaVar hr := Handle(Revenue) Do Evaluate(hr) - Expenses
In the other direction, when a LocalAlias
, r
, is an alias for another object and you need the handle to the object, use Handle(r)
. It is legal to use the Handle()
function on a local variable declared using LocalAlias
, but it is an error to apply the Handle()
function to a local variable defined using MetaVar
. This is because a local variable is not an object (it is just a name for a value), and since handles can only point to objects, there is no such thing as a handle to a local variable[3].
- ↑ This expression contains a side-effect to a global variable. Side-effects to global variables are only allowed in expressions or user-defined functions that are run directly from button scripts. This would cause an error if attempted from a variable’s definition.
- ↑ Not every object in Analytica lives in the global namespace (e.g., local indexes), so this rule doesn’t literally apply for handles to objects not in the global namespace. For these, we cannot replace the local name with an identifier since no global identifier exists for the object pointed to by the handle.
- ↑ A local index is an object, so you can have a handle to a local index. The Index..Do and MetaIndex..Do constructs create an index object, along with a local variable name that has LocalAlias semantics for the index object.
Enable comment auto-refresher