Operators and Expressions
Expressions are the logic building blocks, they allow you to express a value. From the basic constants to binary and ternary operations, expressions give the power to specify a value.
Identifiers
Identifiers are one of the simplest expressions. They represent variables, properties, method and function names. Identifiers can only contain alphanumeric (Latin) characters, underscores, digits, however they cannot start with digits.
Keywords
Template Engine has a set of reserved keywords used for building complex constructs as part of tags and other expressions. Although they are valid identifiers, they can't be used as identifiers.
Here is the list of the reserved keywords:
set | in |
|---|---|
global | as |
if | do |
elseif | verbatim |
else | filter |
endif | endfilter |
for | null |
endfor | is |
true | not |
false | with |
empty | require |
return | returning |
include | macro |
Access Expressions
List or Map Values
In order to access either a list element or map value, Template Engine comes with the value access expression where you use a list element index or map key, defined in square braces []. Note that list elements index always starting at zero.
{{ list[0] }}
{{ map["key1"] }}
WARNING
List or Map Values Access expressions in combination with binary operators are very sensitive to parentheses.
This is a technical limitation of the template engine parser architecture, you can find more details about it here.
Properties and Methods
In order to access an object property or invoke its method, the selection operator . (dot) is used. You can find available properties and methods in the Data Types and Variables articles.
{{ guild.name }}
{{ guild.getMember(247734710682255361) }}
Selection operator can also be used for maps as well to get the value represented by key, if this key is valid identifier:
{{ map.key1 }}
Complex Expressions
Constants, variables and other expressions can be combined into more complex expressions by using operators. Operator precedence determine the order in which the operations in an expression are performed.
These operators include the following groups:
Order of Evaluation
In an expression with multiple operators, the operators with higher precedence are evaluated before the operators with lower precedence. Operators of the same precedence are evaluated in lexical order.
You can use parentheses to change the order of evaluation imposed by operator precedence.
If you want to know more about expressions precedences, check Expressions Precedence article.
TIP
The lower the number, the higher the precedence and the earlier it is evaluated.
Unary Operators
Unary operators by definition only need one argument, Template Engine comes with only two built in unary operators, they are not and -.
| Symbol | Description | Precedence | Example |
|---|---|---|---|
- | Switches the signal | 95 | -(-1) outputs 1 |
not | Negates the input | 100 | not false outputs true;not true outputs false |
Binary Operators
Template Engine comes with several built-in binary operators:
TIP
The lower the number, the higher the precedence and the earlier it is evaluated.
| Symbol | Precedence | Description | Пример |
|---|---|---|---|
. | 101 | Access inner properties of objects | member.id outputs member id |
^ | 103 | Takes base number to to the power of exponent | 2 ^ 3 outputs 8 |
* | 105 | Multiplies two values | 2.2 * 2.2 outputs 4.84 |
** | 105 | Multiplies the integer part of two values | 2.2 ** 2.2 outputs 4 |
/ | 105 | Divides two values | 5.0 / 2.0 outputs 2.5 |
// | 105 | Divides the integer part of two values | 5.0 // 2.0 outputs 3 |
% | 105 | Gets the integer division remainder | 5 % 2 outputs 1 |
+ | 110 | Sums two values | 5 + 2 outputs 7 |
- | 110 | Subtracts two values | 5 - 2 outputs 3 |
~ | 112 | Concatenates two strings | "5" ~ "2" outputs "52" |
< | 115 | Compares two values, checking whether the first is lower than the second | 1 < 2 outputs true 1 < 1 outputs false |
<= | 115 | Compares two values, checking whether the first is lower or equal than the second | 2 <= 2 outputs true 2 < 1 outputs false |
> | 115 | Compares two values, checking whether the first is higher than the second | 2 > 1 outputs true 2 > 2 outputs false |
>= | 115 | Compares two values, checking whether the first is higher or equal than the second | 2 >= 2 outputs true 2 >= 3 outputs false |
in | 115 | Checks whether the second value contains the first one | 5 in [2] outputs false |
== | 120 | Compares two values, checking whether they are equal or not | true == false outputs false false == false outputs true |
!= | 120 | Compares two values, checking whether they are different or not | true != false outputs true false != false outputs false |
and | 125 | Conjunction boolean operator | true and false outputs false true and true outputs true |
or | 125 | Disjunction boolean operator | true or false outputs true false or false outputs false |
| | 130 | Uses the first argument as parameter for the second argument. Note that, composition forces the second argument to be a function | -5 | abs outputs 5 |
:= | 140 | Calculates and returns second value, assigning it to the variable in the first operand. More details. | result := 1 + 2 outputs 3, assigning it as result variable |
Assignment Operator
Assignment Operator (affectionately known as "the walrus operator" :=) is a binary operator that lets you assign value to variable and return it at the same time.
{{ <variable> := <expression> }}
The walrus calculates the value of the expression, assigns it to the specified variable and returns the same value.
{{ result := 1 + 2 }}
{{ result }}
Previous example will return "3" twice. First one is the result of expression calculation and second one is the value of result variable that has been updated by this assignment expression.
This operator is very useful to make your code look better and shorter. For example, let's take a simple template using set tag to assign a value to variable:
{% set amount = 5 %}
{% if amount > 0 %}
Daniel has {{ amount }} apples!
{% endif %}
This template can be simplified:
{% if (amount := 5) > 0 %}
Daniel has {{ amount }} apples!
{% endif %}
Assignment Precedence
As you can see on the table above, the Assignment Operator has the lowest precedence along other binary operators and this must be taken into account.
If previous example would have an expression written like amount := 5 > 0, the amount value would be true, not 5, because comparing operator has the higher precedence so it calculates first. This is why we must use parentheses to isolate assignment operator.
Assignment Operator itself can't make a global variables, but if specified variable does already exist and is global, the assignment operator will update its value and keep it global.
Ternary Operator
Template Engine only contains one ternary operator. It allows to fork the logic based on a boolean expression, as exemplified below:
{{ expr ? 1 : 2 }}
Such expression will output 1 if the variable expr is true, or 2 if the variable is false.
Elvis Operator
Template Engine supports Elvis operator that returns its first operand if that operand evaluates to a true value according Type Convert, and otherwise evaluates and returns its second operand.
{{ <expression A> ?: <expression B> }}
This operator is very useful to return a "default" value for expressions.
TIP
By its nature, the Elvis Operator should be binary, but from the perspective of the template engine's rules, it is placed in a separate group, which precedence is even lower than the entire group of binary expressions, but higher than the Ternary Operator.
Test Expressions
Test expressions are a complex predicate construct, they return a boolean value as result.
| Name | Description | Example |
|---|---|---|
| Null | Checks whether a value is null or not | 1 is null outputs false |
| Divisible | Checks if a value is divisible by another | 2 is divisible by 1 outputs true |
| Same As | Checks whether two objects are strictly equal by their reference | 1 is same as (2) outputs false |
| Function based | This checks the function result by invoking it with the value as argument. | 4 is defined outputs true;'test' is number outputs false. |
| Is Not | All test constructs listed before can be negated with the is not constructor. | 4 is not defined outputs false |
"Same As" Test Expression
This expression tests for the same object by reference, not just their value. For example:
{{ 1 is same as (1) }}
This will print false. Yes, they are both number 1, but they are different instances of same number having different reference internally. Now check this:
{% set value = 1 %}
{% set other = value %}
{{ value is same as (other) }}
This will print true because those both value and other variables have the same reference to the same number.
It works for null though:
{{ null is same as (null) }}
This will print true because null reference is always the same.