Difference between revisions of "Attrib of Obj"

m
m
Line 5: Line 5:
 
== ''Attrib'' Of ''Obj'' ==
 
== ''Attrib'' Of ''Obj'' ==
  
Returns the value of attribute «Attrib» of the object identified by «Obj».  «Attrib» and «Obj» may be text identifiers, such as <code>'Title' OF 'Var92'</code>, or handles.  If the requested attribute is not set, it returns [[Null]].
+
Returns the value of attribute «Attrib» of the object identified by «Obj».  «Attrib» and «Obj» may each be an identifier (of the attribute or object), text containing identifiers, or handles to the attribute or object.  For example, I
  
==Examples:==
+
:<code>Units OF Time &rarr; 'Years'</code>
:<code>Units of Time &rarr; 'Years'</code>
+
:<code>'Units' OF 'Time' &rarr; 'Years'</code>
or
+
:<code>'Units' OF [[HandleFromIdentifier]]('Time') &rarr; 'Years'</code>
:<code>'Units' of 'Time' &rarr; 'Years'</code>
+
 
 +
If the requested attribute is not set for that object, it returns [[Null]].
  
 
== Using Computed Parameters ==
 
== Using Computed Parameters ==
  
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.
+
Parameters «Attrib» and «Obj» may 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.  In [[Meta-Inference]] algorithms, the attribute or object is often a computed value, and so isn't identified until the expression is evaluated.
  
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 [[Handle]] of an attribute object, or to a list or array containing these, otherwise an error results.   
+
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 [[Handle]] of an attribute object, or to a list or array containing these, otherwise an error results.   
  
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 variable.  When using '''Attrib Of Obj''' in a [[Meta-Inference|meta-inference]] algorithm, you must keep this straight.  The following example demonstrates.  Suppose global Variable objects, <code>Va1</code> and <code>Va2</code>, are defined by expressions that identify an object, <code>A</code>, i.e.:
+
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 variable.  When using '''Attrib OF Obj''' in a [[Meta-Inference|meta-inference]] algorithm, you must keep this straight.  The following example demonstrates.  Suppose global Variable objects, <code>Va1</code> and <code>Va2</code>, are defined by expressions that identify an object, <code>A</code>, i.e.:
  
 
:<code>Variable Va1 := Handle(A)</code>
 
:<code>Variable Va1 := Handle(A)</code>
Line 25: Line 26:
 
Then OF in the following cases evaluate as shown:
 
Then OF in the following cases evaluate as shown:
  
:<code>Identifier Of Va1 &rarr; 'Va1'      { statically bound }</code>
+
:<code>Identifier OF Va1 &rarr; 'Va1'      { statically bound }</code>
:<code>Identifier of Va2 &rarr; 'Va2'      { statically bound }</code>
+
:<code>Identifier OF Va2 &rarr; 'Va2'      { statically bound }</code>
  
 
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 [[Handle]], or a list or array of these.  In the above examples, the several variations are possible:
 
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 [[Handle]], or a list or array of these.  In the above examples, the several variations are possible:
Line 32: Line 33:
 
:<code>Var v:=Va1; Identifier Of v &rarr; 'A'</code>
 
:<code>Var v:=Va1; Identifier Of v &rarr; 'A'</code>
 
:<code>Var v:=Va2; Identifier Of v &rarr; 'A'</code>
 
:<code>Var v:=Va2; Identifier Of v &rarr; 'A'</code>
:<code>Identifier Of Value of Va1 &rarr; 'A'</code>
+
:<code>Identifier OF Value of Va1 &rarr; 'A'</code>
:<code>Identifier Of Mid(Va1) &rarr; 'A'</code>
+
:<code>Identifier OF Mid(Va1) &rarr; 'A'</code>
:<code>Identifier Of Evaluate('Va1') &rarr; 'A'</code>
+
:<code>Identifier OF Evaluate('Va1') &rarr; 'A'</code>
:<code>Identifier Of Evaluate(Handle(Va1)) &rarr; 'A'</code>
+
:<code>Identifier OF Evaluate(Handle(Va1)) &rarr; 'A'</code>
  
The '''Of'''  operator parses in a right-associative fashion, so that the third line above parses as <code>(Identifier Of (Value of Va1)</code>).  
+
The '''OF'''  operator parses in a right-associative fashion, so that the third line above parses as <code>(Identifier Of (Value of Va1)</code>).  
  
 
Of can be used to retrieve attributes of functions, so for example,  
 
Of can be used to retrieve attributes of functions, so for example,  
  
:<code>Description Of Evaluate</code>
+
:<code>Description OF Evaluate</code>
  
 
returns the description of the evaluate function, while  
 
returns the description of the evaluate function, while  
  
:<code>Description Of Evaluate('Va1')</code>
+
:<code>Description OF Evaluate('Va1')</code>
  
 
returns the description of <code>Va1</code>.
 
returns the description of <code>Va1</code>.
Line 52: Line 53:
  
 
:<code>index I := 1..2;</code>
 
:<code>index I := 1..2;</code>
:<code>Description of I := "A simple index";</code>
+
:<code>Description OF I := "A simple index";</code>
 
:<code>Var A := I^2;</code>
 
:<code>Var A := I^2;</code>
 
:<code>Description of A.I & "=" & A</code>
 
:<code>Description of A.I & "=" & A</code>
Line 62: Line 63:
  
 
You can set the value of attributes using the syntax:
 
You can set the value of attributes using the syntax:
<code>''attrib'' Of ''obj'' := expr</code>
+
<code>''attrib'' OF ''obj'' := expr</code>
in the [[OnClick]] attribute of  a Button, [[OnChange]] of a Variable, [[Script]] attribute (obsolete), or a Function called from one of these. (These same limitation applies to the standard [[Assignment Operator :=|assignment]]).
+
As with the standard [[Assignment Operator :=|assignment]]), 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.
 
 
The same considerations as to whether «attrib» and «obj» are statically bound or dynamically resolved apply; however, attribute assignment does NOT automatically array abstract.  Thus, «attrib» and «obj» must be atomic, and if «expr» is an array, the array value is assigned to the attribute.  For most attributes, «expr» should to evaluate to text, although some attributes expect numbers. An example is this:
 
  
:<code>NodeColor OF Va1 := '16000,8000,65535'</code>
+
You cannot assign to read-only attributes, usually internally computed 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 Value of a variable, but that is dangerous because it may be inconsistent with its Definition.
  
If you use assignment directly from a script (as opposed to using it from a definition attribute, such as a User-Defined Function called from a script), you must surround the expression with parens, i.e.
+
As with getting an attribute of an object, «attrib» and «obj» may each be a simple identifier, text containing an identifier, or a handle to the attribute or object.   And they may be statically bound or dynamically resolved in the same way. However, for attribute assignment, «attrib» and «obj» must be atoms. It does NOT automatically array abstract. 
:<code>(NodeColor OF Va1 := '16000,8000,65535')</code>
 
  
This is because typescript has its own syntax, and an assignment expression qualifies as valid typescript, but is interpreted differently (the right-hand side is not evaluated in typescript). The parentheses identify this to the typescript interpreter as an expression, rather than a typescript command.
+
If «expr» is an array, the array value is assigned to the attribute. For most attributes, «expr» should to evaluate to text, although some attributes expect numbers. An example is this:
  
Because Analytica imposes restrictions on side-effects, so that it can maintain dependencies among variables consistently, assignment to attributes of global objects is not permitted while a variable is being evaluated.  You may assign to attributes of local indexes (declared using [[Index..Do]]) at any time, but assignment to attributes of global objects is only permitted from typescript (e.g., from a button's Script attribute), or from a function that is invoked from typescript.
+
:<code>NodeColor OF Va1 := '16000,8000,65535'</code>
  
You also cannot assign to read-only attributes (usually internal attributes computed by Analytica).
+
Because Analytica imposes restrictions on side-effects, so that it can maintain dependencies among variables consistently, assignment to attributes of global objects is not permitted while a variable is being evaluated.  You may assign to attributes of local indexes (declared using [[Index..Do]]).
  
To remove an attribute value, assign it to [[Null]]:
+
To remove an attribute value, assign [[Null]] to it:
 
:<code>Units of Va1 := Null</code>
 
:<code>Units of Va1 := Null</code>
  
''Note: Internally, Analytica distinguishes between an attribute set to the special value [[Null]], and and 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).''
+
''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).''
  
When assigning to the definition attribute, the right-hand side should evaluate to a text string, e.g.:
+
You may only assign a text value to the definition attribute, e.g.:
:<code>Definition of Va1 := "A" & "+" & "B"</code>
+
:<code>Definition OF Va1 := "A + B"</code>
  
Note that when you assign directly to a variable, the definition is set to a literal or to an edit table of literals equal to the actual value.  <code>(Va1 := "A"&"+"&"B")</code> would set the definition to <code>'A+B'</code> (with quotes), rather than just <code>A+B</code> (an expression without quotes).
+
Note that 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.
  
== Dependency Maintenance ==
+
== No dependency maintenance for attributes other than Definition and Identifier ==  
  
Analytica's dependency maintenance mechanism does NOT maintain dependencies between arbitrary attributes.  So, for example, if you have a variable, <code>Va2</code>, that references the <code>Description of Va1</code> from within its definition, once <code>Va2</code> is computed it will not be automatically refreshed or invalidated in the event that the description of <code>Va1</code> changes.
+
Analytica automatically maintains dependencies between Definitions to values of dependent variables, so that if you change the definition of variable, <code>A</code>, it will invalidate the value of any variable <code>B</code> that depends on the value of <code>A</code>, and recompute <code>B</code> when needed.  It also automatically propagates any change to an identifier to update any definitions that use that identifier. This does not work for other attributes: So if you (or some Analytica code) changes, say, the Title  of <code>A</code>, it will not invalidate or recompute <code>B</code> if it depends on the Title 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 }
  
 
== See Also ==
 
== See Also ==
Line 97: Line 103:
 
* [[Objects and Values]]
 
* [[Objects and Values]]
 
* [[Assignment Operator :=]]  
 
* [[Assignment Operator :=]]  
* [[VarTerm]] function
+
* [[Handle]] function
 
* [[Meta-Inference]]
 
* [[Meta-Inference]]

Revision as of 22:21, 16 May 2017


Attrib Of Obj

Returns the value of attribute «Attrib» of the object identified by «Obj». «Attrib» and «Obj» may each be an identifier (of the attribute or object), text containing identifiers, or handles to the attribute or object. For example, I

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.

Using Computed Parameters

Parameters «Attrib» and «Obj» may 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. In Meta-Inference algorithms, the attribute or object is often a computed value, and so isn't identified until the expression is evaluated.

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 Handle of an attribute object, or to a list or array containing these, otherwise an error results.

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 variable. When using Attrib OF Obj in a 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.:

Variable Va1 := Handle(A)
Variable Va2 := 'A'

Then OF in the following cases evaluate as shown:

Identifier OF Va1 → 'Va1' { statically bound }
Identifier OF Va2 → '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 Handle, or a list or array of these. In the above examples, the several variations are possible:

Var v:=Va1; Identifier Of v → 'A'
Var v:=Va2; Identifier Of v → 'A'
Identifier OF Value of Va1 → 'A'
Identifier OF Mid(Va1) → 'A'
Identifier OF Evaluate('Va1') → 'A'
Identifier OF Evaluate(Handle(Va1)) → 'A'

The OF operator parses in a right-associative fashion, so that the third line above parses as (Identifier Of (Value of Va1)).

Of can be used to retrieve attributes of functions, so for example,

Description OF Evaluate

returns the description of the evaluate function, while

Description OF Evaluate('Va1')

returns the description of Va1.

Of binds more tightly than the x^y operator, 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), 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 cannot assign to read-only attributes, usually internally computed 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 Value of a variable, but that is dangerous because it may be inconsistent with its Definition.

As with getting an attribute of an object, «attrib» and «obj» may each be a simple identifier, text containing an identifier, or a handle to the attribute or object. And they may be statically bound or dynamically resolved in the same way. However, for attribute assignment, «attrib» and «obj» must be atoms. It does NOT automatically array abstract.

If «expr» is an array, the array value is assigned to the attribute. For most attributes, «expr» should to evaluate to text, although some attributes expect numbers. An example is this:

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

Because Analytica imposes restrictions on side-effects, so that it can maintain dependencies among variables consistently, assignment to attributes of global objects is not permitted while a variable is being evaluated. You may assign to attributes of local indexes (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).

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

Definition OF Va1 := "A + B"

Note that 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.

No dependency maintenance for attributes other than Definition and Identifier

Analytica automatically maintains dependencies between Definitions to values of dependent variables, so that if you change the definition of variable, A, it will invalidate the value of any variable B that depends on the value of A, and recompute B when needed. It also automatically propagates any change to an identifier to update any definitions that use that identifier. This does not work for other attributes: So if you (or some Analytica code) changes, say, the Title of A, it will not invalidate or recompute B if it depends on the Title 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 }

See Also

Comments


You are not allowed to post comments.