# Expr Advanced Reference - Operators

Operators allow writing formulas in a convenient way using traditional logical and arithmetic operations. Each operator has one (unary operators) or two operands. Each operand could be a variable, a number, or just any expression, which sometimes will need to be in parentheses.

The operators translate into calling the corresponding functions on operands as arguments. If an operand expression evaluates to an error, then the operator's result will also be an error.

Available operators are:

Operator(s) | Symbol(s) | Priority | Type of Operands | Result Type | Corresponding Function(s) |
---|---|---|---|---|---|

Logical negation | `NOT` | 7 | Any | Number (Boolean) | `NOT` |

Unary sign | `+ -` | 7 | Convert to Number | Number | `SUM, MINUS` |

Multiplication and division | `* /` | 6 | Convert to Number | Number | `MUL, DIV` |

Addition and subtraction | `+ -` | 5 | Convert to Number | Number | `SUM, MINUS` |

Concatenation | `CONCAT` | 4 | Convert to Text/Joined | Text | `CONCAT` |

Equality/Inequality check | `= != ` | 3 | Any | Number (Boolean) | `EQ, NE` |

Numeric Comparison | `< > <= >=` | 3 | Number | Number (Boolean) | `LT, GT, LE, GE` |

Logical AND | `AND` | 2 | Any | Any(*) | `AND` |

Logical OR | `OR` | 1 (lowest) | Any | Any(*) | `OR` |

The operators are listed in their priority order. The priority is important when an expression could allow different interpretations about which operators are applied first.

For example, in an expression ** progress + parent.progress * weight < threshold AND priority != "Blocker"**, the multiplication is executed first, then the addition, then the comparisons, and then the logical AND. If you'd like to alter the order of operator application, use the parentheses.

### Logical Negation (NOT)

To negate a logical value or expression, use the

operator. Instead of **NOT**** NOT**, an exclamation mark (

**) can also be used.**

`!`

The operator produces ** 0** if the operand is a truthy value, and

**otherwise. Therefore, it may be applied to any value.**

`1`

If the value negated is an expression with other operators, it should be contained in parentheses.

Examples:

`NOT resolved`

`NOT (storyPoints > 0 AND storyPoints < parent.maxStoryPoints)`

### Unary Sign (+ -)

The operator first attempts to convert the value of an expression to a number. If conversion succeeds, `+`

produces this number, and `-`

produces the negated number.

If the conversion to a number fails, and the value of the expression is falsy, the negation produces `undefined`

. Otherwise, it produces an error.

### Arithmetic operators (* / + -)

Arithmetic operators are: addition (`+`

), subtraction (-), multiplication (`*`

) and division (/).

Multiplication and division have precedence over addition and subtraction.

These operators convert their arguments to numbers. A non-empty, non-number argument would produce an error. Falsy non-number values are treated as zero.

Examples:

`"" + 1 → 1`

`"foo" + 1 → error`

`"" * 1 → 0`

`"foo" * 1 → error`

`"" - 1 → -1`

`1/0 → error`

If any subexpression produces an error, the operator produces the same error.

### Concatenation (CONCAT)

The concatenation operator converts each operand to a text value (Text/Joined, to be precise) and creates a new text by joining them together. It is identical to calling the CONCAT function on its operands:

`value1 CONCAT value2 CONCAT value3 = CONCAT(value1, value2, value3)`

The operator can be used to increase the readability of a formula.

Note that CONCAT is applied after all the arithmetic operators but before comparisons and logical operators.

### Equality check (= !=)

The "equals" operator (=) checks that both arguments are "essentially the same value". The "not equals" operator (** !=** or

**) produces the inverse value.**

`<>`

The comparison rules are based on the type of the values compared.

Equality operator will return true (1) if any of the following conditions hold:

Both values are

**Undefined.**One value is a

**Number**, and the second value is the same number, or can be converted to the same number.- One value is a
**Text**, and the second value can be converted to Text (using Text/Joined), and both values are "essentially the same".- The differences in letter forms and leading and trailing whitespace are ignored (thus
).`" cote " = "côte"`

- The differences in letter forms and leading and trailing whitespace are ignored (thus
One value is an

**Item**, and the other value is the same item. (Note that if the other value is a Text, both values can be compared as text values.)- One value is a
**Key-Value Map**, and the other value is also a key-value map with the same contents (these equality rules applied to all elements). - One value is a
**User Function**, and the other value is exactly the same user function (not just having the same logic). One value is an

**Array**, and either of the following is true:The other value is also an

**array**, has the same number of elements and the elements are respectively equal.The other value is

**undefined**and the array does not contain any non-undefined elements.This array contains only

**one element**and this element is equal to the other non-array value we are comparing the array with.

In all other cases, the equality returns false (

.**0**)

Note that you can compare an item to a text, for example,

`IF project = "My Project" : ...`

The item will get converted to a text using value conversion rules described earlier.

If one value is a number and the other value can be converted to a number, both values are treated as numbers. However, if both values are text, they will be treated as text, even if both can be converted to a number. You can use the NUMBER function to force a value to be numeric.

`3.4 = 3.40 → 1`

`3.4 = "3.40" → 1`

`"3.4" = "3.40" → 0`

`NUMBER("3.4") = "3.40" → 1`

### Numeric Comparison (< > <= >=)

The ordering / comparison operators work on numbers only:

(less than)`<`

(greater than)`>`

(less than or equal)`<=`

(greater than or equal)`>=`

If either of the values is text, the operator attempts to convert it to a number. If the conversion fails, the result is an error.

If any value is undefined, strict operators (** <**,

**) produce**

`>`

`0.`

Non-strict (**,**

`<=`

**) produce**

`>=`

`0`

, unless *both*values are undefined (because they are equal).

### Logical operators (AND OR)

The logical operators are used to combine other logical conditions, or to pick an alternative or a conditional value.

also can be written as "`OR`

" or "`||`

"`|`

also can be written as "`AND`

" or "`&&`

"`&`

When both operands are Number(Boolean), then the operators perform the corresponding boolean operation.

However, you can use these operators with non-boolean operands in a "short circuit" way, based on whether the operands are "truthy" (see above).

– if "a" is truthy, "b" is not evaluated and the result of the operation is "a"; otherwise the result of the operation is "b".`a OR b`

– if "a" is falsy, "b" is not evaluated and the result of the operation is "a"; otherwise the result of the operation is "b".`a AND b`

Note that "b" is not evaluated in case the result of the operation is equal to "a". This might be important in case calculating "b" could result in an error.

Examples:

– This will produce either the issue's assignee user key or (if the issue is unassigned) the text value "`assignee OR "UNASSIGNED"`

**UNDEFINED**".– This will produce`!assignee AND status = "OPEN"`

if the issue is unassigned and in status`1`

, and`OPEN`

otherwise.`0`

– This will produce some average number (total / count), unless count is 0 – in this case the result will be 0. Note that there will be no division by zero error.`count AND total / count`