An expression is made of one or more literal values, operators, functions, and variables. Below is an example expression with its various parts labeled.
New Ticket
and by
are text literals and return in the expression output as written.&
operator represents text concatenation and combines text with data.pv!ticketId
variable returns the Ticket ID value, and the pp!initiator
variable returns the user who started the process.userDisplayName
rule takes a user as a parameter and returns the user's first and last name.The above expression could result in the following output: New Ticket AN-9867 by John Smith
You can use Appian functions, custom function plug-ins, and rules in expressions to perform operations using arguments you pass to them. The expression then returns a result based on your arguments.
You can use data types in expressions to construct a complex data type value by creating a type constructor.
Arguments or fields within a type constructor that contain data queries may be evaluated in parallel to reduce the overall evaluation time.
See also: Appian Functions, Expression Rules, Data Types
A literal is a static value stated in the expression, such as 2, 3.14, or "hello".
The following types of literals are supported:
Expresses a series of text characters. It is stated as text entered between double quotation marks.
"Hello World"
An integer number is any whole number.
82
or -82
A decimal number possesses a decimal point and can express fractional numbers.
1.234
Certain built-in expression values exist in order to concisely express concepts or conditions. Supported special literals include:
true
for the Boolean value true.
false
for the Boolean value false.
null
for an empty (null) value that has no specific data type.
Special literals can be used within any variable as a default value and can be cast to any data type.
An array is an ordered list of data items that can be selected by indices computed at run-time. Arrays can be empty or constructed with literal values, variables, or functions.
{{1, 2}, {3, 4}} = {1, 2, 3, 4}
When entering an array as part of an expression, you must use braces ({}) to enclose it and separate items using commas (,) unless you are referencing a variable.
{2, 3, 9, 1}
To add text in an array, enclose each item in quotation marks ("").
{"a", "b", "c", "d"}
Items in a list that contain data queries may be evaluated in parallel to reduce the overall evaluation time.
In order to select one or more values from an array, use the index operator [] or index().
For example, with an index operator and an array of pv!multiple = {10, 20, 30}
:
pv!Multiple[2]
yields 20
pv!Multiple[{2, 3, 2}]
yields {20, 30, 20}
Example with index() and array of {10, 20, 30}
:
index({10, 20, 30}, 2, 1)
yields 20
See also: Array Functions
A map is an ad-hoc data structure created inline in an expression using the a!map() function. In contrast, a custom data type is a reusable data structure with a specific name and predefined fields.
For example, to create a map with two fields called label
and value
, enter the following:
1
a!map(label: "Item", value: "Entry")
To create an array of maps, enter the following:
1
{a!map(label: "Item one", value: "Entry one"), a!map(label: "Item two", value: "Entry two")}
Fields within a map that contain data queries may be evaluated in parallel to reduce the overall evaluation time.
A dictionary is very similar to a map; it is an ad-hoc data structure mapping fields to values. However, values indexed out of a dictionary often need to be cast to their respective type before use. For this reason, maps should generally be used instead of dictionaries.
To create a dictionary with two fields called label
and value
, enter the following:
1
{label: "Item", value: "Entry"}
Data types Date, Time, and Date and Time are stored as numbers.
For date and time values, the local value (based on the designer time zone) is not stored. Instead, it is stored in Greenwich Mean Time (GMT) and then converted to the user's time zone when displayed on the screen.
To advance either Date or Date and Time by a day, add 1 to the value.
To advance Time by a minute, add 60*1000
to the value. Adding 1 to Time only advances it by a millisecond.
Example Input | Yields |
---|---|
date(2012, 4, 30) - date(2012, 4, 25) |
5 days |
datetime(2012, 4, 25, 12) - datetime(2012, 4, 25, 10) |
0.0833 days -or- 2.0 hours |
date(2012, 4, 25) + 5 |
4/30/2012 |
There are many operators that can be used in expressions to perform data manipulation. The operators provided are divided into two different categories.
To Perform... | Use | Example |
---|---|---|
Addition | + | 10+8 yields 18 |
Subtraction/Negation | - | 10-8 yields 2 - OR - if value is 97 , then -value is -97 |
Multiplication | * | 2*5 yields 10 |
Division | / | 10/5 yields 2 |
Exponentiation | ^ | 2^8 yields 256 |
Percentage (divide by 100) | % | 97% yields 0.97 |
Example Input | Yields |
---|---|
{1, 2, 3} * 10 |
{10, 20, 30} |
{1, 2, 3} + {1, 2, 3} + {1, 2, 3} |
{3, 6, 9} |
{1, 1, 1, 1, 1} + {1, 2} |
{2, 3, 2, 3, 2} |
tointeger({}) + 1 |
1 |
Tip: Apply arithmetic to lists directly, rather than through multi-node instances, to make your process model look cleaner and work faster.
Note: If operating on two arrays that are not the same length, the shorter list will be repeatedly extended until it is the same length as the longer list. This applies to Date and Date/Time values as well: pv!list_of_dates+1
returns the next day for the entire list.
To Perform... | Use | Example |
---|---|---|
Less than | < | 10<2 yields false |
Greater Than | > | 10>2 yields true |
Less Than or Equal | <= | 10<=2 yields false |
Greater Than or Equal | >= | 10>=2 yields true |
Not Equal to | <> | 10<>2 yields true |
Equal to | = | 10=2 yields false |
exact()
function rather than the =
operator to improve performance.Example Input | Yields |
---|---|
1={1, 2, 3} |
{true, false, false} |
{1, 2, 3}<>{4, 2, 6} |
{true,false,true} |
exact({1, 2, 3},{1, 2, 3}) |
true |
1=tointeger({}) |
false |
0=tointeger({}) |
true |
"Hello"="HELLO" |
true (case-insensitive) |
exact("Hello","HELLO") |
false (case-sensitive) |
{1,2} = {1,2,1,2} |
{true, true, true, true} |
{"a","b"} = {"a","a","b","b"} |
{true, false, false, true} |
Note: In the case of comparing an array of text values to a scalar text value, the array elements will not be compared item by item with the scalar text value. In order to compare item by item, you must wrap the scalar value in a list. For example, use {"a", "b", "c"} = {"c"}
instead of {"a", "b", "c"} = "c"
to compare each element of the array to the value "c"
. This only applies to the text data type.
The precedence of operators evaluated in an expression follows the standard Order of Operations:
So, if an expression includes two or more operators, the operator higher on the list is applied first, then the second highest, and so on. In order to ensure an operation occurs before another, enclose it within parentheses.
A variable identifies the data to use when evaluating an expression. It uses syntax similar to Microsoft Excel sheet and cell syntax, where the Appian data domain is the sheet and a named variable is the cell syntax. Appian variables are always of a specific data type.
The variables you can use in an expression depend on the context in which the expression is designed and evaluated. They are listed in the Data tab of the Expression Editor and include Appian variables and user-defined process variables.
For a full listing or variables delivered with Appian, see Process and Report Data.
In the following example, the expression returns the value of a process variable:
'pv!variable.a-name'
.Variables of complex and custom data types use the dot operator to access field values. You can also use the index()
function.
Let's say you have a custom data type "Person" with the following structure:
1
2
3
4
5
Person
|- firstName (Text)
|- lastName (Text)
|- homeAddress (Address)
|- city (Text)
You create a variable (process variable, node input, or local variable) called "personA" of type Person. To access the "firstName" value of the variable, enter any of the following:
index(pv!personA, "firstName", "")
pv!personA["firstName"]
pv!personA.firstName
Note: Appian recommends using index()
to access the index value of a CDT in cases where the variable may have a null value, or the field name is not available. The index()
function allows you to assign a default value through its default value parameter. See also: index() function.
The dot notation is useful when accessing nested fields of custom data type, provided that the nested field is not null.
To access the "city" value of the "personA" variable, enter either of the following:
index(pv!personA, "homeAddress", "city", "")
pv!personA.homeAddress.city
Local variables differ in that they are defined and set within the expression and are only available inside the function that defines them.
The a!localVariables() function defines a local variable and immediately assigns it a value. For example, in the following expression, local!username
is set to the current user's username and then used several times in the rest of the expression:
1
2
3
4
5
6
7
8
a!localVariables(
local!username: loggedInUser(),
if(
len(local!username) > 10,
local!username & " is a long username!",
local!username & " seems like a fairly short username!"
)
)
Using local variables can avoid duplicating logic, make expressions easier to read, and avoid needlessly evaluating a part of the expression multiple times. They can also be used to store a user's input as they interact with the interface.
Local variable definitions that contain data queries may be evaluated in parallel to reduce the overall evaluation time.
Some functions allow variables to be used in one or more of their inputs. These variables are in the fv!
domain and are only available when configuring that function's input. They are auto-suggested in the Expression Editor and listed in the documentation for relevant functions.
For example, the a!foreach() looping function has several variables available in its expression parameter, such as fv!item
:
1
=a!forEach(items: { 1, 2, 3 }, expression: fv!item + 1)
Because it is a function variable provided by the a!foreach()
function, fv!item
cannot be used outside of a!foreach()
. In this case, it is only provided for the expression parameter, so it cannot be used in the items parameter either. As a!forEach()
iterates through the items parameter, it evaluates the expression multiple times, each time providing the current item value to fv!item
.
When writing an expression that includes text and data, use an ampersand (&
) to string (or concatenate) the information together.
For example, use the following expression to display a salutation when using process variables for the title and name data:
1
="Dear " & pv!title & " " & pv!name & ","
To return the following value:
1
Dear Mr. John Smith,
Comments are a way for designers to leave notes in the expression to explain what the expression does.
You start a comment with /*
and end it with */
. Any content between these two symbols is ignored when the expression evaluates.
For example:
1
"Dear "& pv!title /* pv!title should contain either "Mr" or "Mrs" */ & pv!name &","
Includes a comment but still evaluates to the following:
1
"Dear "& pv!title & pv!name &","
Parts of an Expression