Difference between revisions of "Attrib of Obj"

m
(Sub-attribute syntax)
 
(21 intermediate revisions by 3 users not shown)
Line 1: Line 1:
[[category:Meta-Inference Functions]]
+
[[Category:Meta-Inference Functions]]
[[category:Operators]]
+
[[Category:Operators]]
 +
[[Category: Attributes]]
 +
{{ReleaseBar}}
  
(enhanced in 4.0)
+
== ''Attrib'' Of ''Obj'' ==
  
= ''Attrib'' Of ''Obj'' =
+
Returns the value of attribute «Attrib» of object «Obj».  «Attrib» and «Obj» may each be an identifier, a text value containing identifiers, or a handle to the attribute or object.  For example:
  
Returns the value of attribute ''Attrib'' of the object identified by ''Obj''.
+
:<code>Units OF Time &rarr; 'Years'</code>
 +
:<code>'Units' OF 'Time' &rarr; 'Years'</code>
 +
:<code>'Units' OF [[HandleFromIdentifier]]('Time') &rarr; 'Years'</code>
  
Examples:
+
If the requested attribute is not set for that object, it returns [[Null]].
:Units of Time &rarr; 'Years'
+
This works if «Attrib» or «Obj» are arrays of attribute or object names or handles.
or
 
:'Units' of 'Time' &rarr; 'Years'
 
  
= Library =
+
=== Computing «obj» ===
  
Special
+
Sometimes you may want to use an expression for «obj» rather than just a literal identifier , especially when doing [[Meta-Inference]]. For example:
   
+
:<code>Decision A := 'Yes'</code>
= Using Computed Parameters =
+
:<code>Variable B := Handle(A)</code>
 +
:<code>Class OF B &rarr; Variable</code>
 +
You might have expected that the second expression would return <code>Decision</code>, the class of variable <code>'A'</code> whose handle is the value of <code>B</code>. But the parser naturally assumes you want the attribute of the object  <code>B</code>, not its value. If you want to get the value of the variable or expression in «Obj», you need use an expression that is not just the name of a variable. You can simply put parentheses around the identifier:
 +
:<code>Class OF (B) &rarr; Decision</code>
  
Both parameters, ''Attrib'' and ''Obj'', can be either statically or dynamically bound, which is to say, the identification of the attribute and object can be made either at parse time or at evaluation time.  Often in [[Meta-Inference]] algorithms, the attribute or object is a computed value, and thus the attribute or object isn't completely identified until the expression is evaluated.
+
This can be particularly useful if you want to get an attribute of a list of objects:
 +
:<code>INDEX Vars := ListOfHandles(X, Y, Z)</code>
 +
:<code>Class OF (Vars) &rarr; Array(Vars, [Decision, Variable, Index])</code>
  
If the ''Attrib'' parameter preceding the OF keyword is a literal attribute name, then it is bound at parse time. In this case only, the OF keyword is optional.  Otherwise, if the parameter preceding OF is any other expression, the expression is evaluated at run time, but must evaluate either to text containing the attribute name, to a [[varTerm]] of an attribute object, or to a list or array containing these, otherwise an error results. 
+
It's fine to use the name of a variable (or more complex expression) for «attrib». If «attrib» is not simply the identifier of an attribute, it evaluates the expression. It expects to find a handle to an attribute, or a text value with the identifier of an attribute, or an array of such handles or text values, for example:
 +
:<code>Variable Attribs := ['Class', 'Identifier', 'Value']</code>
 +
:<code>Attribs OF A&rarr; Array(Attribs, ['Decision', 'A', 'Yes'])</code>
  
If the ''Obj'' parameter following the Of keyword is an object identifier, then obj is bound at parse time.  This means that the attribute of the named object is returned, not the attribute of the object computed by the variableWhen using Attrib OF Obj in a [[Meta-Inference|meta-inference]] algorithm, you must keep this straight. The following example demonstrates.  Suppose global Variable objects, Va1 and Va2, are defined by expressions that identify an object, A, i.e.:
+
You can use '''OF''' to get attributes of a function:
 +
:<code>Description OF Evaluate</code>
 +
returns the description of the evaluate function, while
 +
:<code>Description OF Evaluate('Va1')</code>
 +
returns the description of <code>Va1</code>.
 +
 
 +
The '''OF''' operator parses in a right-associative fashion, so that:
 +
<code>Class OF Value OF B&rarr; Decision</code>
 +
parses as:
 +
:<code>Class OF (Value OF B)&rarr; Decision</code>
 +
 
 +
'''OF''' binds more tightly than [[operators|arithmetic operators]], but less tightly than the [[Subscript/Slice Operator]]. So, for example, to access an attribute of a local index of an object, parens are not necessary:
  
Variable Va1 := VarTerm(A)
+
:<code>Index I := 1..2;</code>
Variable Va2 := 'A'
+
:<code>Description OF I := "A simple index";</code>
 +
:<code>Var A := I^2;</code>
 +
:<code>Description OF A.I & "=" & A</code>
  
Then OF in the following cases evaluate as shown:
+
The last line parses as  
 +
:<code>((Description OF (A.I)) & "=") & A</code>
  
Identifier Of Va1 &rarr; 'Va1'      { statically bound }
+
== Assigning Values to Attributes ==
Identifier of Va2 &rarr; 'Va2'      { statically bound }
 
  
To dynamically reference the object computed by a variable, you must write the Of expression in such a way that the Obj parameter is not itself a valid object identifier. There are two method for doing this - using a local variable declared with [[Var..Do]] (which is just an alias for a value, and not a object that has identifiers), or by calling a function that returns the computed object identification. In either case, the resolved value can be either a textual identifier of the desired object, a [[varTerm]], or a list or array of these. In the above examples, the several variations are possible:
+
You can set the value of attributes using the syntax:
 +
:<code>''attrib'' OF ''obj'' := expr</code>
 +
As with the standard [[Assignment Operator :=]], you can use this only in the [[OnClick]] attribute of  a Button, [[OnChange]] of a Variable, [[Script]] attribute (obsolete), or a Function called from one of these. You may also assign to an attribute of a [[Local variable]] within a Definition.
  
Var v:=Va1; Identifier Of v &rarr; 'A'   
+
You may not assign to read-only attributes, like [[Inputs]], and [[Outputs]]. You can assign a handle to a module [[IsIn]], which has the effect of moving the object into that module. You can assign to the Value of a variable, but that is dangerous because it may be inconsistent with its Definition.
Var v:=Va2; Identifier Of v &rarr; 'A'   
 
Identifier Of (value of Va1) &rarr; 'A'
 
Identifier Of [[Mid]](Va1) &rarr; 'A'
 
Identifier Of [[Evaluate]]('Va1') &rarr; 'A'
 
Identifier Of [[Evaluate]](Va1) &rarr; 'A'
 
  
Note that the parens in the third line above are required so that it doesn't parse as
+
As with the simple construct,  «attrib» OF «obj» described above, «attrib» and «obj» may each be a simple identifier, a text value containing an identifier, or a handle to the attribute or object.  And if «obj» is a variable <code>X</code> containing a handle or text value referring to the object of interest, you must put parentheses around it <code>Title OF (X)</code> if you want the Title of what <code>X</code> refers to instead of <code>X</code> itself.
((Identifier Of Value) Of Va1) &rarr; A    { the [[varTerm]] A, same as Value of Va1 }
 
Also note that Of can be used to retrieve attributes of functions, so for example,
 
  
  Description Of Evaluate
+
However, for attribute assignment, «attrib» and «obj» must be atoms, not arrays. It does NOT array abstract.  
  
returns the description of the evaluate function, while
+
For most attributes, «expr» should to evaluate to text,  even in this case where it appears the attribute contains numbers:
 +
:<code>NodeColor OF Va1 := '16000,8000,65535'</code>
 +
 
 +
You may only assign a text value to the definition attribute, e.g.:
 +
:<code>Definition OF Va1 := "A + B"</code>
 +
 
 +
When you assign directly to a variable:
 +
:<code>Va1 := "A + B"</code>
 +
it sets the definition to the text value <code>'A+B'</code> (with quotes), rather than the expression <code>A+B</code> (without quotes) that depends on the values of A and B.
 +
 
 +
You may assign to attributes of a local index(declared using [[Index..Do]]).
 +
 
 +
To remove an attribute value, assign [[Null]] to it:
 +
:<code>Units of Va1 := Null</code>
 +
 
 +
''Note: Internally, Analytica distinguishes between an attribute set to the special value [[Null]], and an attribute that has no value.  However, it is not possible to set an attribute value to [[Null]] from an Analytica expression (although you can set value to lists or arrays containing [[Null]] elements).''
 +
 
 +
== No auto propagation of changes to attributes other than Definition and Identifier ==
 +
 
 +
Analytica maintains dependencies between variables specified in their Definitions, as reflected in the influence arrows.  So, if you change the definition of variable, <code>A</code>, it invalidates the value of any variable <code>B</code> that depends on <code>A</code>, and recomputes <code>B</code> when needed.  It also automatically propagates any change to an identifier to update any definitions that use that identifier. This works for CheckAttribute, OnClick, and OnChange attributes.
 +
But not other attributes! So if you (or some Analytica code) change, say, the Units  of <code>A</code>, it will not invalidate or recompute <code>B</code> if it depends on the Units of <code>A</code>:
 +
 
 +
:<code>A := 20</code>
 +
:<code>Units OF A := 'KW'</code>
 +
:<code>B := IF Units OF A = 'KW' THEN 1000*A ELSE IF Units of A = 'MW' THEN 1M*A ELSE A</code>
 +
:<code>B &rarr; 20000</code> { Because Units of A are KW }
 +
:<code>Units OF A := 'MW'</code>
 +
:<code>B &rarr; 20000</code> { Changing Units of A did not cause B to be recomputed }
 +
 
 +
{{Release|6.1||
 +
==Sub-Attributes ==
 +
There are several attributes in Analytica that store multiple fields separated by commas, namely these attributes: [[NodeInfo]], [[NodeLocation]], [[NodeSize]], [[DefaultSize]], [[FontStyle]], [[NodeFont]], [[DiagState]], [[WindState]], [[ValueState]], [[OutlinerState]], [[DefnState]], [[NumberFormat]], [[ProbabilityNumberFmt]], [[DensityNumberFormat]], and [[FileInfo]].  We refer to these fields as ''sub-attributes''. For example, the [[NodeLocation]] attribute has three sub-attributes: x, y and z, encoding the x, y location (in pixels) of the center of a node on a diagram, along with its z-index (which determines which nodes appear above of other nodes when they overlap).
  
  Description Of Evaluate('Va1')
+
When you need to access a sub-attribute, you can do so using a special syntax ''«attribute»::«fieldNum»'' or ''«attribute»::«fieldName»''.  
 +
For example, to obtain the y value of the [[NodeLocation]] of <code>Va1</code>, use either
 +
* <code>NodeLocation::2 of Va1</code>
 +
* <code>NodeLocation::y of Va1</code>
 +
The result is either numeric or Null in this case (no need to use [[ParseNumber]]). Similarly, to set a sub-attribute, use either syntax within the attribute assignment, e.g.,
 +
* <code>NodeLocation::2 of Va1 :{{=}} 200 </code>
 +
* <code>NodeLocation::y of Va1 :{{=}} 200</code>
 +
}}
  
returns the description of Va1.
 
 
= See Also =
 
  
 +
== See Also ==
 +
* [[Attributes]]
 +
* [[Objects and Values]]
 +
* [[Assignment Operator :=]]
 +
* [[Handle]] function
 
* [[Meta-Inference]]
 
* [[Meta-Inference]]

Latest revision as of 21:11, 7 December 2021



Release:

4.6  •  5.0  •  5.1  •  5.2  •  5.3  •  5.4  •  6.0  •  6.1  •  6.2  •  6.3  •  6.4  •  6.5


Attrib Of Obj

Returns the value of attribute «Attrib» of object «Obj». «Attrib» and «Obj» may each be an identifier, a text value containing identifiers, or a handle to the attribute or object. For example:

Units OF Time → 'Years'
'Units' OF 'Time' → 'Years'
'Units' OF HandleFromIdentifier('Time') → 'Years'

If the requested attribute is not set for that object, it returns Null. This works if «Attrib» or «Obj» are arrays of attribute or object names or handles.

Computing «obj»

Sometimes you may want to use an expression for «obj» rather than just a literal identifier , especially when doing Meta-Inference. For example:

Decision A := 'Yes'
Variable B := Handle(A)
Class OF B → Variable

You might have expected that the second expression would return Decision, the class of variable 'A' whose handle is the value of B. But the parser naturally assumes you want the attribute of the object B, not its value. If you want to get the value of the variable or expression in «Obj», you need use an expression that is not just the name of a variable. You can simply put parentheses around the identifier:

Class OF (B) → Decision

This can be particularly useful if you want to get an attribute of a list of objects:

INDEX Vars := ListOfHandles(X, Y, Z)
Class OF (Vars) → Array(Vars, [Decision, Variable, Index])

It's fine to use the name of a variable (or more complex expression) for «attrib». If «attrib» is not simply the identifier of an attribute, it evaluates the expression. It expects to find a handle to an attribute, or a text value with the identifier of an attribute, or an array of such handles or text values, for example:

Variable Attribs := ['Class', 'Identifier', 'Value']
Attribs OF A→ Array(Attribs, ['Decision', 'A', 'Yes'])

You can use OF to get attributes of a function:

Description OF Evaluate

returns the description of the evaluate function, while

Description OF Evaluate('Va1')

returns the description of Va1.

The OF operator parses in a right-associative fashion, so that: Class OF Value OF B→ Decision parses as:

Class OF (Value OF B)→ Decision

OF binds more tightly than arithmetic operators, but less tightly than the Subscript/Slice Operator. So, for example, to access an attribute of a local index of an object, parens are not necessary:

Index I := 1..2;
Description OF I := "A simple index";
Var A := I^2;
Description OF A.I & "=" & A

The last line parses as

((Description OF (A.I)) & "=") & A

Assigning Values to Attributes

You can set the value of attributes using the syntax:

attrib OF obj := expr

As with the standard Assignment Operator :=, you can use this only in the OnClick attribute of a Button, OnChange of a Variable, Script attribute (obsolete), or a Function called from one of these. You may also assign to an attribute of a Local variable within a Definition.

You may not assign to read-only attributes, like Inputs, and Outputs. You can assign a handle to a module IsIn, which has the effect of moving the object into that module. You can assign to the Value of a variable, but that is dangerous because it may be inconsistent with its Definition.

As with the simple construct, «attrib» OF «obj» described above, «attrib» and «obj» may each be a simple identifier, a text value containing an identifier, or a handle to the attribute or object. And if «obj» is a variable X containing a handle or text value referring to the object of interest, you must put parentheses around it Title OF (X) if you want the Title of what X refers to instead of X itself.

However, for attribute assignment, «attrib» and «obj» must be atoms, not arrays. It does NOT array abstract.

For most attributes, «expr» should to evaluate to text, even in this case where it appears the attribute contains numbers:

NodeColor OF Va1 := '16000,8000,65535'

You may only assign a text value to the definition attribute, e.g.:

Definition OF Va1 := "A + B"

When you assign directly to a variable:

Va1 := "A + B"

it sets the definition to the text value 'A+B' (with quotes), rather than the expression A+B (without quotes) that depends on the values of A and B.

You may assign to attributes of a local index(declared using Index..Do).

To remove an attribute value, assign Null to it:

Units of Va1 := Null

Note: Internally, Analytica distinguishes between an attribute set to the special value Null, and an attribute that has no value. However, it is not possible to set an attribute value to Null from an Analytica expression (although you can set value to lists or arrays containing Null elements).

No auto propagation of changes to attributes other than Definition and Identifier

Analytica maintains dependencies between variables specified in their Definitions, as reflected in the influence arrows. So, if you change the definition of variable, A, it invalidates the value of any variable B that depends on A, and recomputes B when needed. It also automatically propagates any change to an identifier to update any definitions that use that identifier. This works for CheckAttribute, OnClick, and OnChange attributes. But not other attributes! So if you (or some Analytica code) change, say, the Units of A, it will not invalidate or recompute B if it depends on the Units of A:

A := 20
Units OF A := 'KW'
B := IF Units OF A = 'KW' THEN 1000*A ELSE IF Units of A = 'MW' THEN 1M*A ELSE A
B → 20000 { Because Units of A are KW }
Units OF A := 'MW'
B → 20000 { Changing Units of A did not cause B to be recomputed }

Sub-Attributes

There are several attributes in Analytica that store multiple fields separated by commas, namely these attributes: NodeInfo, NodeLocation, NodeSize, DefaultSize, FontStyle, NodeFont, DiagState, WindState, ValueState, OutlinerState, DefnState, NumberFormat, ProbabilityNumberFmt, DensityNumberFormat, and FileInfo. We refer to these fields as sub-attributes. For example, the NodeLocation attribute has three sub-attributes: x, y and z, encoding the x, y location (in pixels) of the center of a node on a diagram, along with its z-index (which determines which nodes appear above of other nodes when they overlap).

When you need to access a sub-attribute, you can do so using a special syntax «attribute»::«fieldNum» or «attribute»::«fieldName». For example, to obtain the y value of the NodeLocation of Va1, use either

  • NodeLocation::2 of Va1
  • NodeLocation::y of Va1

The result is either numeric or Null in this case (no need to use ParseNumber). Similarly, to set a sub-attribute, use either syntax within the attribute assignment, e.g.,

  • NodeLocation::2 of Va1 := 200
  • NodeLocation::y of Va1 := 200


See Also

Comments


You are not allowed to post comments.