Difference between revisions of "Expression Syntax"

m
Line 1: Line 1:
Analytica expressions are the language used for [[Definition]] attributes of a variable or Function. Expressions are also used in the Check, [[OnClick]], and [[OnChange]] Attributes.
+
Analytica expressions are the language used for [[Definition]] attributes of a variable or Function. Expressions are also used in the [[Check]], [[OnClick]], and [[OnChange]] Attributes.
  
 
The obsolete Script attribute uses  [[Scripting|Typescript]], which has a slightly different syntax from Analytica Expressions (see also [[:Category:Typescript_Commands|Typescript Commands]]). The Script attribute was replaced by [[OnClick]] and [[OnChange]] attributes in [[Analytica 4.6]] release, and is retained only for backward compatibility.
 
The obsolete Script attribute uses  [[Scripting|Typescript]], which has a slightly different syntax from Analytica Expressions (see also [[:Category:Typescript_Commands|Typescript Commands]]). The Script attribute was replaced by [[OnClick]] and [[OnChange]] attributes in [[Analytica 4.6]] release, and is retained only for backward compatibility.
Line 7: Line 7:
 
You can call [[Alphabetical_Function_List | built-in functions]] and [[User-Defined Functions]] using standard ''position-based'' syntax, in which you specify the parameters (or arguments) in sequence between parentheses:
 
You can call [[Alphabetical_Function_List | built-in functions]] and [[User-Defined Functions]] using standard ''position-based'' syntax, in which you specify the parameters (or arguments) in sequence between parentheses:
  
Uniform(0, B, True)
+
:<code>Uniform(0, B, True)</code>
  
Each actual parameter, 5, B, and True in this example, may be a number, variable, array, or or other expression, depending on the type of parameter expected. In this case, the function [[Uniform]] expects parameters (min, max, integer).
+
Each actual parameter, <code>5, B</code>, and <code>True</code> in this example, may be a number, variable, array, or or other expression, depending on the type of parameter expected. In this case, the function [[Uniform]] expects parameters («min», «max», «integer»).
  
 
You can also specify some or all parameters using a ''name-based'' syntax, in which you specify a parameter by name, followed by ":" and the value to be called, for example:
 
You can also specify some or all parameters using a ''name-based'' syntax, in which you specify a parameter by name, followed by ":" and the value to be called, for example:
  
Uniform(min: 1, max: 100, integer: True) -- same parameter positions as normal
+
:<code>Uniform(min: 1, max: 100, integer: True)</code> -- same parameter positions as normal
Uniform(integer: True, min: 1, max: 100) -- a different sequence is fine with named parameter
+
:<code>Uniform(integer: True, min: 1, max: 100)</code> -- a different sequence is fine with named parameter
Uniform(1, 100, integer: true) -- mixed syntax: initial parameters are position based, last is by name.
+
:<code>Uniform(1, 100, integer: true)</code> -- mixed syntax: initial parameters are position based, last is by name.
  
 
With names, you can list the parameters in any order, as in the second example.  Using mixed syntax, you can specify initial parameters by position, followed by one or more parameters identified by name. This is especially useful when calling a function with one or a few required initial parameters followed by multiple optional parameters of which you only want to specify a few.
 
With names, you can list the parameters in any order, as in the second example.  Using mixed syntax, you can specify initial parameters by position, followed by one or more parameters identified by name. This is especially useful when calling a function with one or a few required initial parameters followed by multiple optional parameters of which you only want to specify a few.
  
Some parameters expect an index (or variable), in which case you must provide the identifier of an Index (or other variable).  You can specify an index using the [[Dot_operator::A.I#Dot_Operator:_A.I|dot-operator]] syntax -- e.g. A.I.  In these cases, you may not use arbitrary expressions, including function calls, as the value.   
+
Some parameters expect an index (or variable), in which case you must provide the identifier of an Index (or other variable).  You can specify an index using the [[Dot_operator::A.I#Dot_Operator:_A.I|dot-operator]] syntax -- e.g. <code>A.I</code>.  In these cases, you may not use arbitrary expressions, including function calls, as the value.   
  
 
There are many other expectations or restrictions on parameters and how they get evaluated (or not), specified by [[Function Parameter Qualifiers|parameter qualifiers]] and on the [[Evaluation Modes|evaluation mode]] when the function is evaluated. You can see these qualifiers in the documentation, or in the Object view for each Function. You can also specify them yourself in [[User-defined functions]] that you define yourself.
 
There are many other expectations or restrictions on parameters and how they get evaluated (or not), specified by [[Function Parameter Qualifiers|parameter qualifiers]] and on the [[Evaluation Modes|evaluation mode]] when the function is evaluated. You can see these qualifiers in the documentation, or in the Object view for each Function. You can also specify them yourself in [[User-defined functions]] that you define yourself.
Line 25: Line 25:
 
== Array subscripting ==
 
== Array subscripting ==
  
To obtain a single cell, slice, or subarray from an array, you identify the relevant indexes by name. For example, suppose array '''Population''' is indexed by '''Year''' and '''State''', you can get the population of New York in 2010 as::
+
To obtain a single cell, slice, or subarray from an array, you identify the relevant indexes by name. For example, suppose array '''Population''' is indexed by '''Year''' and '''State''', you can get the population of New York in 2010 as:
Population[Year = 2010, State = "New York"]
+
:<code>Population[Year = 2010, State = "New York"]</code>
 +
 
 
or equivalently:
 
or equivalently:
Population[State = "New York", Year = 2010]
+
:<code>Population[State = "New York", Year = 2010]</code>
 +
 
 
Analytica's '''Named Index subscripting''' has some important advantages over positional indexing for multidimensional arrays, which is what most other computer languages use. First, you don't have to remember which is the "inner" or "outer" index. In fact, those concepts are usually irrelevant in Analytica.  A second advantage is that you can slice out a subarray, e.g.
 
Analytica's '''Named Index subscripting''' has some important advantages over positional indexing for multidimensional arrays, which is what most other computer languages use. First, you don't have to remember which is the "inner" or "outer" index. In fact, those concepts are usually irrelevant in Analytica.  A second advantage is that you can slice out a subarray, e.g.
Population[State = "New York"]
+
:<code>Population[State = "New York"]</code>
gives the population of New York for every value of Year. OrL
+
 
Population[Year = 2010]
+
gives the population of New York for every value of Year. Or:
 +
:<code>Population[Year = 2010]</code>
 +
 
 
gives the population of all states for 2010.  
 
gives the population of all states for 2010.  
  
 
The number of dimensions in an array variable may change as you develop a model, or even by run of a model, for example when using parametric analysis. Accessing Indexes by name is much more robust, since it won't break if an array gets an extra dimension, as would standard positional indexing.
 
The number of dimensions in an array variable may change as you develop a model, or even by run of a model, for example when using parametric analysis. Accessing Indexes by name is much more robust, since it won't break if an array gets an extra dimension, as would standard positional indexing.
  
If you subscript an array by an index that it doesn't contain, it will ignore that subscripting -- e.g.
+
If you subscript an array by an index that it doesn't contain, it will ignore that [[subscript]]ing -- e.g.
Population[State = "New York", Year = 2010, Month = "February"]
+
:<code>Population[State = "New York", Year = 2010, Month = "February"]</code>
 +
 
 
it will just return the population for New York in 2010, assuming it is the same for all months of that year. This is the Principle of being '''Constant over Irrelevant Indexes'''.
 
it will just return the population for New York in 2010, assuming it is the same for all months of that year. This is the Principle of being '''Constant over Irrelevant Indexes'''.
  
If you subscript an array using a value that's not in that Index, it will usually flag an error and return NULL:
+
If you subscript an array using a value that's not in that Index, it will usually flag an error and return [[Null]]:
Population[State = "Quebec"]  @rarr NULL
+
:<code>Population[State = "Quebec"]  &rarr; NULL</code>
  
 
You can specify an alternative value to return for an invalid index value:
 
You can specify an alternative value to return for an invalid index value:
Population[State = "Quebec", defValue: 0]  @rarr 0
+
:<code>Population[State = "Quebec", defValue: 0]  &rarr; 0</code>
  
 
== Operator Precedence ==
 
== Operator Precedence ==
  
 
Analytica uses a fairly standard precedence for arithmetic and logical operators. Exponentiation (^) binds more tightly than multiplication (*) and division (/), which binds more tightly than addition (+) and subtraction (-).  Thus, this expression
 
Analytica uses a fairly standard precedence for arithmetic and logical operators. Exponentiation (^) binds more tightly than multiplication (*) and division (/), which binds more tightly than addition (+) and subtraction (-).  Thus, this expression
1 / 2 * 3 - 4 / 5 ^ 6 + 7
+
:<code>1/2*3 - 4/5^6 + 7</code>
 +
 
 
would parse as
 
would parse as
( ( 1 / 2 ) * 3 ) - ( 4 / ( 5 ^ 6 ) ) + 7
+
:<code>((1/2)*3) - (4/(5^6)) + 7</code>
  
 
This list shows the binding precedence of Analytica operators, with the highest precedence operators first.  Operators in the same bullet have the same level of precedence:
 
This list shows the binding precedence of Analytica operators, with the highest precedence operators first.  Operators in the same bullet have the same level of precedence:
Line 69: Line 75:
 
* +, - (binary minus)
 
* +, - (binary minus)
 
* [[Sequence Operator|m..n]]
 
* [[Sequence Operator|m..n]]
* =, <=, >=, <, >, <>
+
* [[Comparison Operators|=, <=, >=, <, >, <>]]
 
* [[Logical Operators#And|And]]
 
* [[Logical Operators#And|And]]
 
* [[Logical Operators#Or|Or]]
 
* [[Logical Operators#Or|Or]]
:''Note: [[Logical Operators#And|And]],[[Logical Operators#Or|Or]] have equal precedence in Analytica 4.2 and earlier''
+
:''Note: [[Logical Operators#And|And]] and [[Logical Operators#Or|Or]] have equal precedence in Analytica 4.2 and earlier''
 
* [[Text_Concatenation_Operator:_%26 | &]]
 
* [[Text_Concatenation_Operator:_%26 | &]]
 
* [[Assignment_Operator::_::%3D | :=]]
 
* [[Assignment_Operator::_::%3D | :=]]
Line 82: Line 88:
 
Comments can be embedded anywhere whitespace would be allowed within an expression.  There are two ways to specify comments:
 
Comments can be embedded anywhere whitespace would be allowed within an expression.  There are two ways to specify comments:
  
{ This is a comment }
+
:<code>{ This is a comment }</code>
/* This is a comment */  
+
:<code>/* This is a comment */</code>
  
If you start a comment with "{", your comment cannot contain the "}" character.  Similarly, if you start a comment with "/*", it musn't contain the two character sequence "*/".  If you need to embed a comment within a comment (often useful when temporarily commenting out a block of expression code that already contains comments), ensure that if the inner comment uses {...}, that the outer comment uses /*...*/, or vice versa.  
+
If you start a comment with "{", your comment cannot contain the "}" character.  Similarly, if you start a comment with "/*", it musn't contain the two character sequence "*/".  If you need to embed a comment within a comment (often useful when temporarily commenting out a block of expression code that already contains comments), ensure that if the inner comment uses <code>{...}</code>, that the outer comment uses <code>/*...*/</code>, or vice versa.  
  
 
=== Version Gated Comments ===
 
=== Version Gated Comments ===
Line 92: Line 98:
  
 
Consider these equivalent forms of version gated comments:
 
Consider these equivalent forms of version gated comments:
{!40000|''expression''}
+
:<code>{!40000|''expression''}</code>
{!40000-|''expression''}}
+
:<code>{!40000-|''expression''}</code>
  
 
Analytica release 4.00.00 or after will interpret the expression, but prior release will ignore it as a comment.   
 
Analytica release 4.00.00 or after will interpret the expression, but prior release will ignore it as a comment.   
  
 
This gated comment executes the expression in releases 4.00.00 through 4.01.00, but releases before and after will treat it as a comment:
 
This gated comment executes the expression in releases 4.00.00 through 4.01.00, but releases before and after will treat it as a comment:
{!40000-40100|''expression''}
+
:<code>{!40000-40100|''expression''}</code>
  
 
This version interprets the expression in any release from 4.0 up to 4.02.00, but any release thereafter treats it as a comment:   
 
This version interprets the expression in any release from 4.0 up to 4.02.00, but any release thereafter treats it as a comment:   
{!-40200|''expression''}
+
:<code>{!-40200|''expression''}</code>
  
'''''Important:''''' All version-gated comments are treated as comment in Analytica release 3.1 and earlier, regardless of what the version number indicates, since the version-gated comment feature was not introduced until Analyica 4.0.
+
<tip title="Important"> All version-gated comments are treated as comment in Analytica release 3.1 and earlier, regardless of what the version number indicates, since the version-gated comment feature was not introduced until Analyica 4.0.
 +
</tip>

Revision as of 00:51, 12 January 2016

Analytica expressions are the language used for Definition attributes of a variable or Function. Expressions are also used in the Check, OnClick, and OnChange Attributes.

The obsolete Script attribute uses Typescript, which has a slightly different syntax from Analytica Expressions (see also Typescript Commands). The Script attribute was replaced by OnClick and OnChange attributes in Analytica 4.6 release, and is retained only for backward compatibility.

Function Calls

You can call built-in functions and User-Defined Functions using standard position-based syntax, in which you specify the parameters (or arguments) in sequence between parentheses:

Uniform(0, B, True)

Each actual parameter, 5, B, and True in this example, may be a number, variable, array, or or other expression, depending on the type of parameter expected. In this case, the function Uniform expects parameters («min», «max», «integer»).

You can also specify some or all parameters using a name-based syntax, in which you specify a parameter by name, followed by ":" and the value to be called, for example:

Uniform(min: 1, max: 100, integer: True) -- same parameter positions as normal
Uniform(integer: True, min: 1, max: 100) -- a different sequence is fine with named parameter
Uniform(1, 100, integer: true) -- mixed syntax: initial parameters are position based, last is by name.

With names, you can list the parameters in any order, as in the second example. Using mixed syntax, you can specify initial parameters by position, followed by one or more parameters identified by name. This is especially useful when calling a function with one or a few required initial parameters followed by multiple optional parameters of which you only want to specify a few.

Some parameters expect an index (or variable), in which case you must provide the identifier of an Index (or other variable). You can specify an index using the dot-operator syntax -- e.g. A.I. In these cases, you may not use arbitrary expressions, including function calls, as the value.

There are many other expectations or restrictions on parameters and how they get evaluated (or not), specified by parameter qualifiers and on the evaluation mode when the function is evaluated. You can see these qualifiers in the documentation, or in the Object view for each Function. You can also specify them yourself in User-defined functions that you define yourself.

Array subscripting

To obtain a single cell, slice, or subarray from an array, you identify the relevant indexes by name. For example, suppose array Population is indexed by Year and State, you can get the population of New York in 2010 as:

Population[Year = 2010, State = "New York"]

or equivalently:

Population[State = "New York", Year = 2010]

Analytica's Named Index subscripting has some important advantages over positional indexing for multidimensional arrays, which is what most other computer languages use. First, you don't have to remember which is the "inner" or "outer" index. In fact, those concepts are usually irrelevant in Analytica. A second advantage is that you can slice out a subarray, e.g.

Population[State = "New York"]

gives the population of New York for every value of Year. Or:

Population[Year = 2010]

gives the population of all states for 2010.

The number of dimensions in an array variable may change as you develop a model, or even by run of a model, for example when using parametric analysis. Accessing Indexes by name is much more robust, since it won't break if an array gets an extra dimension, as would standard positional indexing.

If you subscript an array by an index that it doesn't contain, it will ignore that subscripting -- e.g.

Population[State = "New York", Year = 2010, Month = "February"]

it will just return the population for New York in 2010, assuming it is the same for all months of that year. This is the Principle of being Constant over Irrelevant Indexes.

If you subscript an array using a value that's not in that Index, it will usually flag an error and return Null:

Population[State = "Quebec"] → NULL

You can specify an alternative value to return for an invalid index value:

Population[State = "Quebec", defValue: 0] → 0

Operator Precedence

Analytica uses a fairly standard precedence for arithmetic and logical operators. Exponentiation (^) binds more tightly than multiplication (*) and division (/), which binds more tightly than addition (+) and subtraction (-). Thus, this expression

1/2*3 - 4/5^6 + 7

would parse as

((1/2)*3) - (4/(5^6)) + 7

This list shows the binding precedence of Analytica operators, with the highest precedence operators first. Operators in the same bullet have the same level of precedence:

Note: And and Or have equal precedence in Analytica 4.2 and earlier

Comments

Comments can be embedded anywhere whitespace would be allowed within an expression. There are two ways to specify comments:

{ This is a comment }
/* This is a comment */

If you start a comment with "{", your comment cannot contain the "}" character. Similarly, if you start a comment with "/*", it musn't contain the two character sequence "*/". If you need to embed a comment within a comment (often useful when temporarily commenting out a block of expression code that already contains comments), ensure that if the inner comment uses {...}, that the outer comment uses /*...*/, or vice versa.

Version Gated Comments

A version-gated comment is a portion of an expression that Analytica ignores as a comment in some releases of Analytica, but treats as a meaningful expression in other releases For example, suppose you have an algorithm that uses features new in Analytica 4.0, but you still want it to work with Analytica 3.1, perhaps falling back to a less efficient algorithm or to reduced functionality. A version-gated comment lets you do this without risk of parse errors in the version that might not recognize the newer features.

Consider these equivalent forms of version gated comments:

{!40000|expression}
{!40000-|expression}

Analytica release 4.00.00 or after will interpret the expression, but prior release will ignore it as a comment.

This gated comment executes the expression in releases 4.00.00 through 4.01.00, but releases before and after will treat it as a comment:

{!40000-40100|expression}

This version interprets the expression in any release from 4.0 up to 4.02.00, but any release thereafter treats it as a comment:

{!-40200|expression}
Important
All version-gated comments are treated as comment in Analytica release 3.1 and earlier, regardless of what the version number indicates, since the version-gated comment feature was not introduced until Analyica 4.0.
Comments


You are not allowed to post comments.