All expressions, when evaluated, produce either a value or an error. All values are immutable – if you need to change a value, you derive another value from it.

Each value belongs to a certain type. There are simple and complex types.

Simple types represent just one value and allow you to write literal values (constants). Simple types are:

  • Undefined
  • Text 
  • Number

Complex types represent a value that has some internal structure. Complex types are:

  • Item

  • Array
  • User Function
  • Key-Value Map

Errors are special values, but they usually cause the whole expression to return an error.

A library function may expects certain types as parameters and will produce a particular type as the result. Expr will also try to convert one type to another as needed.

Undefined

Undefined is a special value, which represents "no value" or a missing value. For example, variable Assignee will have undefined value if the issue is unassigned. 

Undefined value can be used instead of a value of any other type. 

To use the undefined value in a formula explicitly, you can write undefined.

Functions can return undefined when the result of the function is not specified. For example, the function IF(N = 0; "No apples"; N = 1; "One apple") only has a specified value when N is equal to 0 or 1. If N is equal to anything else, it returns undefined.

Text

A text value consists of 0 or more Unicode symbols. Its literal representation consists of the value enclosed in single quotes (') or double quotes ("). Example: "Major" represents text value Major. Similarly, 'Major' represents the same text value.

If the text value itself contains quotes, you'll need to insert a backslash (\) before them. Example: "Charlie \"Bird\" Parker" represents the text value Charlie "Bird" Parker. Alternatively, you can use another kind of quotes to enclose the literal representation: 'Charlie "Bird" Parker'.

If you need to use the backslash at the end of text value, you will need to insert another backslash before it. Example: "C:\Users\John\\" represents text value C:\Users\John\.

Text Snippets (""")

Sometimes you need a long text value that contains some words and symbols, but also the value of a certain expression or a variable. One way to create it is to use the CONCAT function and join all the pieces of text together. A more convenient way could be writing a text snippet.

A text snippet starts with triple double quotes (""") and continues until the next triple double quotes. It includes ends of line, so you can create multiline text values with a text snippet.

Text snippets may contain special sequences that get replaced with a calculated value:

  • A dollar sign followed by a variable name is replaced by that variable's value. For example, """Assigned to: $assignee""".
  • A dollar sign followed by an Expr expression in curly braces is replaced by the value of that expression. For example, """Total score: ${ score + subtasks.score.SUM() }""".

Number

A number represents a single numerical value. Aside from representing some quantity, a number value can also represent a point in time or a duration of time. In this case, you can use Format settings in the Formula column to properly display the results as dates or durations.

There are two forms of literal representations of numbers:

  • a whole number: 42 
  • a fractional number: 0.239

Note that only dot (.) can be used as a decimal separator. Comma (,) is used to delimit function arguments. Thus, MAX(X, 0,618) will be understood as the maximum of three values: X, 0, and 618.

Group separators are not supported, so 100 000 is not a literal representation of number 100000. However, you can write a string value and explicitly call the conversion function – NUMBER("100 000")

Technical note: internally, numbers are represented as decimal floating-point numbers with 16 digits of precision and half-even rounding. Most of the operations are carried out in this form; however, some of the more sophisticated functions, such as SQRT, might first convert the numbers into binary floating-point, calculate the result and then convert it back into decimal floating-point.

Date and Date/Time

A Date/Time value is represented as an integer number of milliseconds since Unix epoch (1970-01-01 00:00:00 GMT). Date functions will help you convert those numbers to readable Text values.

A Date value (without the time component) is represented in the same way as the date/time value, calculated for the midnight of the specified day – in the user's current time zone. (warning) This means that expressions involving Date values (for example, using Jira's Due Date field) may produce different results for different users if they are in different time zones.

Duration

A Duration value is represented as an integer number of milliseconds. Duration functions help transform duration values into readable Text values.

Boolean

A boolean value, such as returned from comparison functions, is represented by a number 1 if true, or 0 if false. 

Additionally, all values can be converted to a boolean value based on whether they are "truthy". (See Value Conversions.)

Item

An item value represents an object that you can potentially have as a row in a structure – a Jira issue, project, sprint, version, user, status, priority and others. It can also represent purely Structure-owned objects like folders.

Items have properties that you can access by writing item.propertyName, or (item-resulting expression).propertyName. The types of items, their properties and their type is listed in Item Property Reference.

Special conversion of Item values

Item values always can be used as Text. Each item will then be represented by a text – an issue by issue key, a project by its name, etc.

Also, items may be compared using UMAX and UMIN functions, which will respect the "natural" order for the items. Most items will be compared alphabetically, but some will have a predefined order, like Priority items. 

Special treatment of Item values by generators

Similar to max/min operations, if a formula column produces Item values, then you can sort by that column (or use Attribute Sorter) to reorder the structure according to the natural order of the resulting items.

If an Attribute Grouper is configured with a formula that produces Item values, the groups will become those items.

Array

An array value is a list of other values. Each value in an array is called an element of the array.

Each value in an array may be of any type – you can have an array of texts, array of items, array of arrays, and so on. An array can contain different types of values in each element – the first one could be a number, the second one an item, and the third one an array of some other elements.

The values in an array may be accessed by their index. The first value has index 0, the second value has index 1, and so on.

There's a number of array functions that allow you to write formulas that deal with multiple values – see Array Functions

Creating an array

You can create an array by calling the ARRAY function: ARRAY(element1, element2, element3, ...)

When you need to change an array, you apply some transformations to an existing array – most frequent being FILTER and MAP. This effectively creates a new array.

Accessing array elements

You can access an element of an array by its index, using the GET function: array.GET(index)

However, it's typically not needed, as the calculations with arrays are done mostly with FILTERMAP and REDUCE.

Special treatment of Array values by the Attribute Grouper generator

When an array value is returned by a formula to the Attribute Grouper generator, it will create multiple groups – one for each non-empty, distinct value returned by the formula.

User Function

A user function value (sometimes called a "lambda value") represents a piece of Expr code that defines a function – see User Functions below.

Typically, you create a user function value to apply it to an array via one of the system functions, such as FILTER or MAP.

For example, consider the following code:

worklogs.FILTER($.author = ME()).MAP(w -> w.timeSpent).REDUCE((a, b) -> a + b)

There are three user functions here, $.author = ME() , w -> w.timeSpent , and (a, b) -> a + b . The first defines the condition for filtering work logs, the second defines how to transform each work log into a number, and the third one defines how to aggregate multiple numbers into one.

Each of these three pieces of Expr are evaluated and are represented by a value of the "User Function" type, and passed to FILTER, MAP, and similar functions.

As with any other value, a User Function value can be assigned to a variable. A more traditional function definition form could be used for that. The following two definitions are identical:

WITH square = x -> x * x :
...
WITH square(x) = x * x :
...

Key-Value Map

A key-value map is produced by some of the Expr functions, and is a collection of pairs, where "key" is the property name and "value" is the property value.

Currently, only GROUP function creates a key-value map, with key group mapping to the value the array is grouped by, and key elements mapping to an array of the matching elements.

To access the value, you need to write kvm.keyName, where kvm is a local variable or an expression that represents the key-value map. 

Keys are supposed to be well-known; there's no way to iterate over all keys.

There's no way for the user to create an arbitrary Key-Value Map; this type is intended only for some system functions.

Errors

Errors are special values, which indicate that the calculation of some part or the whole of the expression encountered a problem.

The list of possible errors is available at Expr Error Codes.

Normally if an error occurs somewhere in the formula, the result of the whole calculation is an error as well. But, if receiving an error from a part of the expression is legitimate, you can use the IFERR and ISERR functions to handle it.