Difference between revisions of "Evaluate"

m (Evaluate(t))
m
 
Line 1: Line 1:
 
[[category:Evaluation Functions]]
 
[[category:Evaluation Functions]]
 
[[Category:Doc Status C]] <!-- For Lumina use, do not change -->
 
[[Category:Doc Status C]] <!-- For Lumina use, do not change -->
 
+
Evaluate(t) is a powerful, but rarely needed function. If t is text, it parses it as an Analytica expression and evaluates it. If t is a handle to a variable, it evaluates and returns its value.
 
== Evaluate(t) ==
 
== Evaluate(t) ==
  
[[Evaluate]] is a powerful, but rarely needed function.  If the parameter «t» is a [[Text values|text value]],  [[Evaluate]] expects  «t», tries to evaluate it as though it were an [[expression]] in a [[definition]], and returns the resulting [[value]]. For example:
+
If parameter «t» is a [[Text values|text value]],  [[Evaluate]](«t») tries to parse «t» as an Analytica [[expression]] (as in the [[definition]] of a Variable), evaluates it, and returns the resulting [[value]]. For example:
  
 
:<code>Evaluate('10 * 10') &rarr; 100</code>
 
:<code>Evaluate('10 * 10') &rarr; 100</code>
  
If «t» is a [[Handle]] to a variable, [[Evaluate]] evaluates the variable and returns its value:
+
If parameter «t» is a [[Handle]] to a variable, [[Evaluate]](«t») evaluates the variable and returns its value:
 
:<code>Variable A := 100</code>
 
:<code>Variable A := 100</code>
 
:<code>Evaluate(Handle(A)) &rarr; 100</code>
 
:<code>Evaluate(Handle(A)) &rarr; 100</code>
Line 18: Line 18:
 
See [[#Using Evaluate on a Function]] below.
 
See [[#Using Evaluate on a Function]] below.
  
== Evaluate a  text value ==
+
== Limitations of Evaluate(t) ==
  
There are several subtleties and limitations to Evaluate(). You should use it with care.
+
There are some subtleties and limitations to Evaluate(«t») when «t» is a text value.
  
 
If text «t» contains a  [[syntax]] error, [[Evaluate]](«t») gives no error message, and returns [[Null]].
 
If text «t» contains a  [[syntax]] error, [[Evaluate]](«t») gives no error message, and returns [[Null]].
  
The context inside the  Evaluate parameter is global, not local. Thus:
+
The context inside the  Evaluate parameter is global, not local. So:
 
:<code>Variable A := 100</code>
 
:<code>Variable A := 100</code>
 
:<code>Variable B := (VAR A := 0; Evaluate('A + 1'))</code>
 
:<code>Variable B := (VAR A := 0; Evaluate('A + 1'))</code>
Line 31: Line 31:
 
The Variable <code>A</code> inside <code>Evaluate('A + 1')</code> refers to the global <code>A</code>, not the local <code>A</code> defined in <code>B</code>. More generally:
 
The Variable <code>A</code> inside <code>Evaluate('A + 1')</code> refers to the global <code>A</code>, not the local <code>A</code> defined in <code>B</code>. More generally:
  
* [[Evaluate]](t) creates its own context for [[Parsed Expressions|parsing]] «t» (at evaluation time), quite different from the context of the expression in which the [[Evaluate]](t) appears  -- e.g., the definition of <code>B</code> above.
+
* [[Evaluate]](t) creates its own context for [[Parsed Expressions|parsing]] «t» (at evaluation time), which is not the context of the expression in which the [[Evaluate]](t) appears  -- e.g., the definition of <code>B</code> above.
* Thus, text «t» cannot refer to [[Local Values|local value]]s, [[index]]es, or [[function parameters]] defined in the context in which the [[Evaluate]](t) function appears.
+
* So, text «t» cannot refer to [[Local Values|local value]]s, [[index]]es, or [[function parameters]] defined in the context in which the [[Evaluate]](t) function appears.
 
* Text «t» may itself define local values and indexes, and refer to them, but these will not be available outside «t».
 
* Text «t» may itself define local values and indexes, and refer to them, but these will not be available outside «t».
 
* If the text value of «t» refers to a global variable —e.g., <code>A</code> in the definition of <code>B</code> above—these do not appear as Inputs of <code>B</code>.  
 
* If the text value of «t» refers to a global variable —e.g., <code>A</code> in the definition of <code>B</code> above—these do not appear as Inputs of <code>B</code>.  
* Analytica will not be able to track the dependency of any variable name that appears inside the text. So, any changes to <code>A</code> will not cause automatic re-evaluation of <code>B</code>. For example:
+
* More generally, Analytica cannot track the dependency of any variable name that appears inside the text. So, for example, any change to <code>A</code> will not cause automatic re-evaluation of <code>B</code>:
 +
:<code>A := 3</code>
 
:<code>B := A + 1</code>
 
:<code>B := A + 1</code>
 
:<code>C := Evaluate('A + 1')</code>
 
:<code>C := Evaluate('A + 1')</code>
 +
:<code>A := 5</code>
  
 
When <code>A</code> changes, Analytica will automatically ensure that <code>B</code> is updated, but it has no way of knowing <code>C</code> should also be recomputed.
 
When <code>A</code> changes, Analytica will automatically ensure that <code>B</code> is updated, but it has no way of knowing <code>C</code> should also be recomputed.
  
Text «t» may itself be an expression that creates a text value to be evaluated by [[Evaluate]]. This text expression appears in the definition of <code>V</code> and is not subject to the above limitations, so, for example:
+
The parameter «t» may itself be an expression that creates a text value to be evaluated by [[Evaluate]]. This text expression appears in the definition of <code>V</code> and is not subject to the above limitations, so, for example:
  
 
:<code>Variable V :=(Var x:= ’10’; Evaluate(x & x))</code>
 
:<code>Variable V :=(Var x:= ’10’; Evaluate(x & x))</code>
Line 49: Line 51:
  
 
The cases in which you should use [[Evaluate]] are rare.  You should be reluctant to use it due to the caveats listed in the previous section. Typical cases when it is useful include:
 
The cases in which you should use [[Evaluate]] are rare.  You should be reluctant to use it due to the caveats listed in the previous section. Typical cases when it is useful include:
* Parsing numbers or simple expressions.
+
* Parsing simple expressions.
 
* (advanced) Use in [[Meta-Inference]] algorithms where you are manipulating handles to objects in your model.
 
* (advanced) Use in [[Meta-Inference]] algorithms where you are manipulating handles to objects in your model.
 
* (rare) Cases where you really do wish to by-pass dependency maintenance.  You want it to compute something the first time the result is requested after the model is first loaded, but not update when parent values are changes.
 
* (rare) Cases where you really do wish to by-pass dependency maintenance.  You want it to compute something the first time the result is requested after the model is first loaded, but not update when parent values are changes.

Latest revision as of 23:17, 12 July 2020

Evaluate(t) is a powerful, but rarely needed function. If t is text, it parses it as an Analytica expression and evaluates it. If t is a handle to a variable, it evaluates and returns its value.

Evaluate(t)

If parameter «t» is a text value, Evaluate(«t») tries to parse «t» as an Analytica expression (as in the definition of a Variable), evaluates it, and returns the resulting value. For example:

Evaluate('10 * 10') → 100

If parameter «t» is a Handle to a variable, Evaluate(«t») evaluates the variable and returns its value:

Variable A := 100
Evaluate(Handle(A)) → 100

You can also use it to evaluate a function passed as an object or handle:

Function Add(a, b)  := a+b
Evaluate(Handle(Add), 2, 10) → 12

This can be useful when you want to define a function that takes a function as a parameter and applies the function in its body. See #Using Evaluate on a Function below.

Limitations of Evaluate(t)

There are some subtleties and limitations to Evaluate(«t») when «t» is a text value.

If text «t» contains a syntax error, Evaluate(«t») gives no error message, and returns Null.

The context inside the Evaluate parameter is global, not local. So:

Variable A := 100
Variable B := (VAR A := 0; Evaluate('A + 1'))
B & rarr; 101

The Variable A inside Evaluate('A + 1') refers to the global A, not the local A defined in B. More generally:

  • Evaluate(t) creates its own context for parsing «t» (at evaluation time), which is not the context of the expression in which the Evaluate(t) appears -- e.g., the definition of B above.
  • So, text «t» cannot refer to local values, indexes, or function parameters defined in the context in which the Evaluate(t) function appears.
  • Text «t» may itself define local values and indexes, and refer to them, but these will not be available outside «t».
  • If the text value of «t» refers to a global variable —e.g., A in the definition of B above—these do not appear as Inputs of B.
  • More generally, Analytica cannot track the dependency of any variable name that appears inside the text. So, for example, any change to A will not cause automatic re-evaluation of B:
A := 3
B := A + 1
C := Evaluate('A + 1')
A := 5

When A changes, Analytica will automatically ensure that B is updated, but it has no way of knowing C should also be recomputed.

The parameter «t» may itself be an expression that creates a text value to be evaluated by Evaluate. This text expression appears in the definition of V and is not subject to the above limitations, so, for example:

Variable V :=(Var x:= ’10’; Evaluate(x & x))
V → 1010

When to Use

The cases in which you should use Evaluate are rare. You should be reluctant to use it due to the caveats listed in the previous section. Typical cases when it is useful include:

  • Parsing simple expressions.
  • (advanced) Use in Meta-Inference algorithms where you are manipulating handles to objects in your model.
  • (rare) Cases where you really do wish to by-pass dependency maintenance. You want it to compute something the first time the result is requested after the model is first loaded, but not update when parent values are changes.

Non-text Parameters

A non-text value can also be passed to Evaluate, which can be of use in some Meta-Inference applications. You need to keep in mind that the parameter to evaluate is evaluated BEFORE the function itself gets it, so evaluating a non-text value is only meaningful when the evaluated parameter is itself something that can still be evaluated. One instance of this that is often useful is the case of a handle an object.

For example, suppose

Variable A := 2 + 3
Variable TheVar := Handle(A)

In the more general case, you might have a Meta-Inference algorithm that identifies a single variable object through some computation. Having identified the object, TheVar now holds a handle to the object. You then may want to access values or properties of the object pointed to by TheVar, rather than just values or properties of TheVar itself. Evaluate serves this purpose:

TheVar → A { A -- i.e., a handle to the object A }
Evaluate(TheVar) → 5 { evaluates A }

It is worth nothing that an alternative method also exists for evaluating a handle. You can declare a LocalAlias set to the handle, and then use its identifier as if it were the identifier of the object.

LocalAlias x := TheVar Do x → 5 { x is an alias for A, so "x" in the body is the value of A }

When accessing attributes of an object in a Meta-Inference algorithm, where your algorithm has a handle to an object (again, say it is in TheVar), you can access the attribute using e.g.,

Description Of Evaluate(TheVar) → "Description of A"
Description Of TheVar → "Description of TheVar"

(the result of using TheVar alone is shown for comparison).

Using Evaluate on a Function

Given a handle to a function object, you can use Evaluate to call the function. If the function expects N parameters, you would provide N+1 parameters to Evaluate -- the first parameter being the handle to the function, and the remaining parameters being the values passed to the function. Example:

MetaVar fn := If opt = 1 then Handle(Max) else if opt = 2 then Handle(Min) else Handle(Sum);
Evaluate(fn, A, I)

Parameters to the function being called are always passed by position, i.e., you cannot use a named-parameter calling syntax as you might if you were calling the function directly.

If the function being called contains repeated (or variable number of) parameters, and you need to include a parameter that follows the repeated parameter, then you must place brackets around the repeated parameters. For example,

Function Fu1(x; y: repeated; z: optional) := ...
 
Evaluate(fn, 1, 2, 3, 4) →
Equivalent to Fu1(1, 2, 3, 4), where [2, 3, 4] are values for y and z is omitted
Evaluate(fn, 1, [2, 3], 4) →
Equivalent to Fu1(1, 2, 3, y: 4), where [2, 3] are values for y, and z is 4.

However, there is a limitation that the first supplied parameter (i.e., the second parameter to Evaluate) cannot be placed inside brackets. Likewise, you cannot pass an literal list by specifying the first parameter as a bracketed list. This is because the repeated-parameter syntax applies equally to Evaluate. If you specify the first parameter to Evaluate in brackets, those become the parameters to the function, i.e.,:

Evaluate(Handle(F), [1, 2, 3, 4]) →
Equivalent to F(1, 2, 3, 4)

Several common built-in functions, including Sum, Max, and Min, allow a variable number of indexes, so that you can use Sum(A, I, J, K) to sum over 3 dimensions in a single call. These functions also have optional parameters, such as «ignoreNonNumbers», so that if you need to specify these optional parameters, you will need to place brackets around the index(es), even if only one (or zero) index is specified. For example, the following examples show how to to specify «ignoreNonNumbers» as true to Sum, when summing over a single index, and when summing over the implicit dimension:

Evaluate(Handle(Sum), A, [I], true)
Var x := [3, 2, 'a', 'b', 6] do Evaluate(Handle(Sum), x, [], true)

Notice that if you don't need to specify the optional «ignoreNonNumbers» parameter (or any parameters that follow the repeated index parameters), then it is more natural to omit the brackets:

Evaluate(Handle(Sum), A, I)
Var x := [3, 2, 5, 3, 6] do Evaluate(Handle(Sum), x)

See Also

Comments


You are not allowed to post comments.