Difference between revisions of "ComputedBy"

(category top-level functions)
 
(7 intermediate revisions by 4 users not shown)
Line 2: Line 2:
 
[[category:Top level functions]]
 
[[category:Top level functions]]
  
= ComputedBy(X) =
+
== ComputedBy(X'', initial'') ==
  
''(Analytica 4.1 or later)''
+
Used to indicate that the value of a variable is computed as a [[side effects|side effect]] of a different variable «X».  
  
Used to indicate that the value of a variable is computed as a side-effect of a different variable ''X''.  
+
When a variable '''A''', has the definition <code>ComputedBy(X)</code>, then the definition of «X» must contain an assignment statement, <code>A := value</code>, that sets the value of '''A'''.
  
When a variable, ''A'', has the definition
+
[[ComputedBy]] can only appear at the top level of a Variable's definition.
ComputedBy(X)
 
  
Then the definition of ''X'' must contain an assignment statement, ''A := value'', that sets the value of A.
+
The optional parameter «initial» holds a scalar value (usually a text value) that serves as the initial value if «X» reads its value before setting it, and can also updates when «X» changes its value.
  
ComputedBy can only appear at the top level of a Variable's definition.
+
== Examples ==
 +
[[ComputedBy]] is particularly convenient within an [[Iterate]] function, when you want to update multiple quantities for each iteration. For example:
  
= Referential Transparency =
+
:<code>Variable A ::= ComputedBy(The_iteration)</code>
 +
:<code>Variable B ::= ComputedBy(The_iteration)</code>
 +
:<code>Variable The_iteration ::= Iterate(initial: (A := A0; B := B0),</code>
 +
::<code>expr:(A := F(A, B); B := G(A, B)),</code>
 +
::<code>until: H(A, B),</code>
 +
::<code>maxIter: 100)</code>
  
Analytica's modeling language is [http://en.wikipedia.org/wiki/Referential_transparency referentially transparent], so that side-effects in general are not allowed.  However, in some cases it is natural to set another variable as a side-effect of a computation.  ComputedBy makes this possible without a loss of referential transparency.
+
In other cases, when computing one variable, it is convenient to compute another in the same calculation, for example:
  
= When to Use =
+
:<code>Variable Component_Variance ::= ComputedBy(Principle_Components)</code>
 +
:<code>Variable Principle_Components ::=</code>
 +
::<code>[[Local]] (eigValue, eigVector) := [[EigenDecomp]](X, I, J);</code>
 +
::<code>Component_Variance := eigValue;</code>
 +
::<code>eigVector</code>
  
'''ComputedBy''' can be particularly convenient within an [[Iterate]] function, when multiple quantities need to be updated at each iteration.  Prior to the introduction of '''ComputedBy''', it was necessary to bundle all quantites together, using [[Using References|references]], and then unbundle them. With computed by, this can be accomplished as follows:
+
Note: The above definition of <code>Principle_components</code> can be shortened using a "trick":
 +
:<code>Variable Principle_Components ::=</code>
 +
::<code>( , ComponentVariance ) := [[EigenDecomp]](X, I, J)</code>
 +
Here the first return value (the eigen value) is passed throw whereas the second return value (the eigen vector) is assigned to <code>Component_Variance</code>.
  
Variable A := ComputedBy(The_iteration)
+
The next example uses an «initial» value to hold a default filename, such that if the user ends up selecting a different file name, it saves the new value.
Variable B := ComputedBy(The_iteration)
 
  
Variable The_iteration := Iterate( initial:(A:=A0;B:=B0),
+
:Variable MyDataFilename ::= <code>[[ComputedBy]]( MyData, "MyData.csv" )</code>
                                    expr:(A:=F(A,B);B:=G(A,B)),
+
:Variable MyData ::= <code>( , MyDataFilename ) := [[ReadTextFile]]( MyDataFilename )</code>
                                    until: H(A,B),
 
                                    maxIter:100 )
 
  
In other cases, there are times in which a useful quantity is computed in the course of computing a primary quantity. The secondary quantity can be stored in a variable defined as ComputedBy. The following is an example:
+
In the above, note that [[ReadTextFile]] has two return values, the content of the file, and the actual filename read. The left-hand side of the assignment in <code>MyData</code> assigns the second return value to <code>MyDataFilename</code>, without assigning the first value to anything. Since the first return value is the result of the assignment operator, the final result for <code>MyData</code> is the content of the file. If the file <code>"MyData.csv"</code> exists, then the file is read with no user intervention. However, if it is not found, the user sees a file selector dialog. Suppose the user selects the file <code>"TodaysData.csv"</code>. After evaluation of <code>MyData</code> completes, the definition of <code>MyDataFilename</code> is now:
 +
:<code>[[ComputedBy]]( MyData, "TodaysData.csv" )</code>
 +
If <code>MyData</code> is re-evaluated in the future, perhaps after saving and reloading the model, it will attempt to open <code>"TodaysData.csv"</code>.
  
  Variable Component_Variance := ComputedBy( Principle_Components )
+
==More details==
 +
=== Referential Transparency ===
 +
Analytica's modeling language is [http://en.wikipedia.org/wiki/Referential_transparency referentially transparent], so that side-effects in general are not allowed. However, in some cases it is natural to set another variable as a side-effect of a computation.  [[ComputedBy]] makes this possible without a loss of referential transparency.
  
Variable Principle_Components :=  
+
=== Use in Dynamic ===
      Var eig := EigenDecompose(X,I,J);
 
      Component_Variance := eig[.item='value'];
 
      #eig[.item='vector']
 
  
= Use in [[Dynamic]] =
+
When <code>A := ComputedBy(X)</code>, and «X» is within a [[Dynamic]] loop, then the assignment within «X» sets the value of '''A''' for the current [[Time]].  Thus, '''A''' will also be indexed by [[Time]] when the computation completes.
  
When ''A := ComputedBy(X)'', and ''X'' is within a [[Dynamic]] loop, then the assignment within ''X'' sets the value of ''A'' for the current [[Time]].  Thus, ''A'' will also be indexed by [[Time]] when the computation completes.
+
=== Evaluation Mode ===
 
+
When <code>A := ComputedBy(X)</code>, if the assignment to '''A''' inside of «X»'s definition occurs from within a [[Sample]] evaluation context, then the [[Evaluation Modes|Sample]] value of '''A''' is set.  Likewise, if the assignment occurs from a [[Mid]] context, then the [[Evaluation Modes|Mid]] value of '''A''' is set.
= Evaluation Mode =
 
 
 
When ''A := ComputedBy(X)'', if the assignment to ''A'' inside of ''X'''s definition occurs from within a [[Sample]] evaluation context, then the [[Evaluation Modes|Sample]] value of A is set.  Likewise, if the assignment occurs from a [[Mid]] context, then the [[Evaluation Modes|Mid]] value of A is set.
 
 
 
= See Also =
 
  
 +
== See Also ==
 +
* [[Side effects]]
 
* [[Iterate]]
 
* [[Iterate]]
 
* [[Dynamic]]
 
* [[Dynamic]]
 
* [[Using References]]
 
* [[Using References]]

Latest revision as of 19:30, 8 January 2025


ComputedBy(X, initial)

Used to indicate that the value of a variable is computed as a side effect of a different variable «X».

When a variable A, has the definition ComputedBy(X), then the definition of «X» must contain an assignment statement, A := value, that sets the value of A.

ComputedBy can only appear at the top level of a Variable's definition.

The optional parameter «initial» holds a scalar value (usually a text value) that serves as the initial value if «X» reads its value before setting it, and can also updates when «X» changes its value.

Examples

ComputedBy is particularly convenient within an Iterate function, when you want to update multiple quantities for each iteration. For example:

Variable A ::= ComputedBy(The_iteration)
Variable B ::= ComputedBy(The_iteration)
Variable The_iteration ::= Iterate(initial: (A := A0; B := B0),
expr:(A := F(A, B); B := G(A, B)),
until: H(A, B),
maxIter: 100)

In other cases, when computing one variable, it is convenient to compute another in the same calculation, for example:

Variable Component_Variance ::= ComputedBy(Principle_Components)
Variable Principle_Components ::=
Local (eigValue, eigVector) := EigenDecomp(X, I, J);
Component_Variance := eigValue;
eigVector

Note: The above definition of Principle_components can be shortened using a "trick":

Variable Principle_Components ::=
( , ComponentVariance ) := EigenDecomp(X, I, J)

Here the first return value (the eigen value) is passed throw whereas the second return value (the eigen vector) is assigned to Component_Variance.

The next example uses an «initial» value to hold a default filename, such that if the user ends up selecting a different file name, it saves the new value.

Variable MyDataFilename ::= ComputedBy( MyData, "MyData.csv" )
Variable MyData ::= ( , MyDataFilename ) := ReadTextFile( MyDataFilename )

In the above, note that ReadTextFile has two return values, the content of the file, and the actual filename read. The left-hand side of the assignment in MyData assigns the second return value to MyDataFilename, without assigning the first value to anything. Since the first return value is the result of the assignment operator, the final result for MyData is the content of the file. If the file "MyData.csv" exists, then the file is read with no user intervention. However, if it is not found, the user sees a file selector dialog. Suppose the user selects the file "TodaysData.csv". After evaluation of MyData completes, the definition of MyDataFilename is now:

ComputedBy( MyData, "TodaysData.csv" )

If MyData is re-evaluated in the future, perhaps after saving and reloading the model, it will attempt to open "TodaysData.csv".

More details

Referential Transparency

Analytica's modeling language is referentially transparent, so that side-effects in general are not allowed. However, in some cases it is natural to set another variable as a side-effect of a computation. ComputedBy makes this possible without a loss of referential transparency.

Use in Dynamic

When A := ComputedBy(X), and «X» is within a Dynamic loop, then the assignment within «X» sets the value of A for the current Time. Thus, A will also be indexed by Time when the computation completes.

Evaluation Mode

When A := ComputedBy(X), if the assignment to A inside of «X»'s definition occurs from within a Sample evaluation context, then the Sample value of A is set. Likewise, if the assignment occurs from a Mid context, then the Mid value of A is set.

See Also

Comments


You are not allowed to post comments.