Tinderbox v9 Icon

eval([item], expressionStr)

Operator Type: 

Operator Scope of Action: 

Operator Purpose: 

Operator First Added: 

Operator Last Altered: 

Operator Has Optional Arguments: 

 Function  [other Function type actions]

 Item  [operators of similar scope]

 Data manipulation  [other Data manipulation operators]


 As at baseline

 [More on optional operator arguments]

eval([item,] expressionStr)

The item argument must be quoted unless an attribute reference. Ways to define item.

The eval() function takes two quoted evaluated (as string) arguments. The first argument, item, is optional. The second argument , expressionStr, holds string holding an action code expression to be evaluated. Thus, in basic form:

if($MyBool){$AttribX = "$Name(parent)+' XYZ'";}else{$AttribX = "$Name(grandparent) + 'ABC'";}; $AttribY = eval($AttribX); 

will set AttribY to the name of the current note's parent's title plus string "XYZ" or that of its grandparent plus string "ABC", depending on the value of attribute MyBool by evaluating attribute AttribX. Thus eval() gives the action code result of an attribute rather than its literal value. As such eval is normally applied to string-based attributes.

If trying to construct an attribute reference from "$" and a literal string or variable, use action() instead.

Further examples

The eval() function can be useful for inserting a local attribute value in an expression that will be evaluated in a different context. Consider this find() in an a rule:

$ArtistCount = find($ArtistName==$Name & !$IsAlias).size; 

For each note evaluated, the note's $Name is compared to ArtistName. However, what if the intent was to use this in a note with an artist's name where it is necessary to come the calling note's $Name, not that of the in-scope note. There is no designator for that relationship, but eval() offers a way around:

$ArtistCount = eval('(find($ArtistName=="'+$Name+'" & !$IsAlias).size)'); 

This first of all makes a string using the correct find code but also inserting the value of the calling note's $Name, and then the whole is evaluated as if it were the original verbatim find() call above.

The process can be made clearer by splitting it into two steps by first using a placeholder $TempString attribute:

$TempString = '(find($ArtistName=="'+$Name+'" & !$IsAlias).size)'; 

The outer parentheses are simply to ensure the .size() call chained on the end of the find is evaluated with the find(). For a note called "Jacques Brel", $TempString would be the string: (find($ArtistName=="Jacques Brel" & !$IsAlias).size). Now, to use eval():

$ArtistCount = eval($TempString); 

Side note: the actual scenario above can also be solved using the 'that' designator, although the example holds true as an exploration of how eval() works.

A more complex example, using nested eval() calls is described under 'using long sections of code'.

Macros: eval() can be combined with do(macro). As macros take input arguments, an evaluated macro can work a bit like a code function, taking inputs and returning output that once passed through eval() gives an evaluated result. See the do() operator.

The eval() operator also allows access to two Tinderbox properties that are not available via action syntax or attribute value. There are the current TBX document's filename (sans extension) and the app version of the currently used Tinderbox on the user's Mac:

eval(^docTitle^) gives a value of "aTbRef-95" (note no '.tbx' extension)

eval(^version^) gives "9.7.3" (note that you might want to prefix the return string with 'v' or 'v.' thus: "v.9.7.3").

In full syntax form, an additional first argument is added that is an expression string evaluating as a note name, path or note name. Where specified, this indicates the note from which attribute values in the second argument should be drawn.

To create an attribute reference ($-prefixed as in '$Name' not 'Name') use action() instead of eval().

Example using both inputs

A different example, using the optional path argument. Take two root-level notes, AA and BB.

$Text("AA") is: 1+1

$Text("BB") is: ""(i.e. nothing)

$Rule("BB") is: $Text=eval("AA",$Text) 

…after a brief delay, the text of note BB becomes 2, i.e. the sum of the expression stored in aa's text. The item argument "AA" simply indicates that the source of the expressionStr is the note AA.

Now change AA's text:

$Text("AA") is: if(1){42}else{1000}

…after a brief delay, the text of note BB becomes 42. How? Any if(condition) is a Boolean test trying to get a true/false result. If the condition does not result in an actual Boolean value (e.g. testing the value of a Boolean attribute) a Boolean is coerced from the result. Thus an empty string or set or the number zero equate to false, all other values to true. Thus in AA's text above, the condition (1) equates to true so the result is 42.

Again, replace the $Text of note 'AA' with

$Text("AA"): $Color=="red"

This is less obvious. When the expression is evaluated, the result will be true if AA is red, and false otherwise. So, $Text("BB") will be empty unless AA is red; if AA's $Color is red,

$Text("BB"): true