Expressions

MWorks’ expression language should feel familiar to anyone who has used programming or scripting languages before. The following sections describe it in detail.

Literals

The expression parser recognizes literal values for a variety of data types.

Data Type

Examples

Notes

Boolean

true
false
YES
NO

Not case-sensitive

Integer

1
+123
-4567

Floating point

1.0
1.
.1
-0.1
+0.1
1.2e10

String

''
"foo"
'bar'
"Hello, world!"

Supports variable and expression interpolation and some C/C++ escape sequences

List

[]
[1.5]
[1, 2.5, 'foo']
[1:10]
[1,2,3:6,7,8:10]

Can include range expressions

Dictionary

{}
{'foo': 1.5}
{'a': 1, true: 2.5, 3.5: 'foo'}

Operators

The expression parser supports a number of mathematical, logical, comparison, and other operators.

Description

Operator

Alternative Form(s)

Example

Precedence

Unit operators (postfix)

Microseconds

us

2000us

1

Milliseconds

ms

100ms

1

Seconds

s

1.5s

1

Element access operators

Subscript

[]

{1:'a'}[1]

2

Unary operators (prefix)

Positive

+

+3

3

Negative

-

-1.7

3

Logical “not”

!

not

!true

3

Type conversion operators (prefix)

Boolean

(bool)

(bool)3

4

Integer

(int)

(integer)

(int)2.7

4

Floating point

(float)

(double)

(float)5

4

String

(string)

(string)4

4

Binary operators

Multiplication

*

1 * 2

5

Division

/

1 / 2

5

Modulus (remainder)

%

1 % 2

5

Addition

+

1 + 2

6

Subtraction

-

1 - 2

6

Equality

==

=

1 == 2

7

Inequality

!=

1 != 2

7

Less than

<

#LT

1 < 2

7

Less than or equal

<=

=< #LE

1 <= 2

7

Greater than

>

#GT

1 > 2

7

Greater than or equal

>=

=> #GE

1 >= 2

7

Logical “and”

&&

and #AND

1 && 2

8

Logical “or”

||

or #OR

1 || 2

9

Note that the unit operators and the plain-English logical operators (not, and, and or) are not case-sensitive. However, the type-conversion operators and all operators that begin with # (#LT, #AND, etc.) are case-sensitive.

Also, be aware that the division operator (/) always produces a floating-point result, even if both of its operands are integers. For example, 1/2 evaluates to 0.5, not 0 (as it does in some programming languages).

Units

Since MWorks does not provide true support for quantities with associated units, the unit operators are simply shorthand for multiplication operations. In the case of time units (us, ms, and s), the operators multiply by a factor suitable for converting to microseconds (1, 1000, and 1000000, respectively).

Subscripting

If the expression exp evaluates to a list, then exp[n] returns the element at index n. If n is out of bounds, the expression evaluates to zero, and the parser issues an error message. (Note that the first element of a list is at index 0, not 1.)

If the expression exp evaluates to a dictionary, then exp[k] returns the value associated with key k in the dictionary. If the dictionary has no matching key, the expression evaluates to zero, and the parser issues an error message.

Precedence

The above table lists the operators from highest precedence (1) to lowest precedence (9). Operator precedence determines the order of operations in expressions, as higher-precedence operations are evaluated before lower-precedence ones.

The order of operations can be altered by wrapping sub-expressions in parentheses, which have higher precedence than all other operators. For example, * has higher precedence than +, so 1+2*3 evaluates to 7, but (1+2)*3 evaluates to 9.

Ranges

A range expression is a compact representation of an evenly-spaced, ordered sequence of integers.

The general form of a range expression is start:stop:step, where start, stop, and step are expressions that evaluate to integers. step is optional. If provided, it must evaluate to a positive integer; if omitted, it defaults to 1. If start is less than stop, the sequence will be increasing; otherwise, it will be decreasing. start is always included in the sequence. If start and stop are separated by a multiple of step, stop will be included as well.

List literals, function calls, and selection variable value lists can all incorporate range expressions. In all cases, range expressions can be mixed with other expressions, so long as all items are separated by commas.

The following table shows some examples of range expression usage, with equivalent, range-expression-free versions shown alongside.

Expression

Equivalent

[1:5]

[1,2,3,4,5]

f(2:-1)

f(2,1,0,-1)

3:10:2

3,5,7,9

[9:0:3]

[9,6,3,0]

f(3:3)

f(3)

7,2:4,-5,9:5:2,1

7,2,3,4,-5,9,7,5,1

Variables

MWorks variables can be incorporated into expressions by referencing each variable by its name. For example, if your experiment defines two variables, x and y, which hold the values 1 and 2, respectively, then the expression 3*x+y will evaluate to 5.

Variable names are case-sensitive, so myvar, MYVAR, and MyVar all refer to different variables.

Selection

When used in an expression, a selection variable evaluates to the currently-selected value. If no selections have been made on the variable, the first one is made automatically, and its value is returned.

Timer

MWorks timers are implemented as variables. When used in an expression, the name of a timer evaluates to true if the timer has expired, false otherwise.

Note: timer_expired (see Time-Related functions below) actually just passes its input value unchanged. However, using it may help to clarify the intent of an expression.

Variable and Expression Interpolation

A string literal can incorporate the value of one or more variables via variable interpolation. When a string literal containing placeholder text of the form $var or ${var} is evaluated, the placeholder is replaced with the current value of variable var (converted to a string). For example:

var greeting = 'Hello'
var subject = 'World'

var message = '$greeting, ${subject}!'  // message contains "Hello, World!"

To inhibit variable interpolation, preface the dollar sign with a backslash:

var text = '123\$abc'  // text contains "123$abc"

A string literal may also incorporate the value of one or more expressions via expression interpolation. When a string literal containing placeholder text of the form $(expr) is evaluated, the placeholder is replaced with the result of evaluating the expression, converted to a string. For example:

message = '1 + 2 = $(1 + 2)'  // message contains "1 + 2 = 3"
text = '$(round(pi())) is a magic number'  // text contains "3 is a magic number"

As with variable interpolation, expression interpolation can be inhibited by prefacing the dollar sign with a backslash:

text = '123\$abc\$(whee!)'  // text contains "123$abc$(whee!)"

Functions

The expression parser recognizes a number of pre-defined functions, many of which are found in other programming or scripting languages. Note that function names are not case sensitive, so now(), NOW(), and Now() are all equivalent.

Mathematical

abs(x)

Absolute value of x

ceil(x)

Nearest integer not less than x

cos(x)

Cosine of x (measured in radians)

exp(x)

Euler’s number (e) raised to the power x

floor(x)

Nearest integer not greater than x

fmod(x,y)

Floating-point remainder of x/y

logn(x)

Natural logarithm of x

max(x,y)

Larger of x and y

min(x,y)

Smaller of x and y

pi()

The constant 𝜋

pow(x,y)

x raised to the power y

round(x)

Nearest integer to x. Number is rounded away from zero in halfway cases.

sin(x)

Sine of x (measured in radians)

sqrt(x)

Square root of x

tan(x)

Tangent of x (measured in radians)

Random Number Generators

rand()

Random floating-point value uniformly distributed in the range [0..1)

rand(min,max)

Random floating-point value uniformly distributed in the range [min..max)

disc_rand(min,max)

Random integer value uniformly distributed in the set of integer numbers {min, min+1, min+2, …, max}

geom_rand(prob,max)

Discrete random number sampled in the interval [0, max] from a geometric distribution with constant Bernoulli probability prob

exp_rand(beta,min,max)

Random number from exponential distribution with mean beta+min, optionally truncated at max. min and max are both optional and default to zero and positive infinity, respectively.

Other

date(fmt)

Returns the current date/time as a string, formatted according to format string fmt. The format string can contain any of the conversion specifiers supported by strftime, as well as arbitrary text.

display_bounds()

Returns a dictionary containing the bounds (in degrees) of the main display. The keys in the dictionary are the strings “left”, “right”, “bottom”, and “top”.

display_bounds(edge)

Given one of the strings “left”, “right”, “bottom”, or “top”, returns the corresponding boundary (in degrees) of the main display

filenames(glob_expr)

Given glob_expr, a string containing a shell-style file name pattern, returns a list of strings containing the names of all matching files (or any empty list, if no files match)

format(fmt,...)

printf-style string formatting. fmt is the format string, and any subsequent arguments are items to be formatted.

num_accepted('sel')

Takes the name of a selectable object (as a string) and returns the number of accepted selections that have been made on it

osname()

Name of the current operating system as a string (e.g. “macos”, “ios”)

py_call(expr,...)

Evaluates expr as a Python expression, calls the resulting Python object with the remaining arguments, and returns the result. If a Python error occurs, logs the error message and returns 0.

py_eval(expr)

Evaluates expr as a Python expression and returns the result. If a Python error occurs, logs the error message and returns 0.

selection('sel',n)

Takes the name of a selection variable (as a string) and an integer n and returns the n-th tentative (i.e. non-accepted) selection on the variable

size(x)

Size of x: number of characters in a string, number of elements in a list or dictionary, 0 otherwise

type(x)

Data type of x as a string (“boolean”, “integer”, “float”, “string”, “list”, or “dictionary”)