When you supply values for interpolations or directive
        parameters you can use variables or more complex expressions. For
        example, if x is the number 8 and y is 5, the value of (x +
        y)/2 resolves to the numerical value 6.5.
Before we go into details, let's see some concrete examples:
- 
            
When you supply value for interpolations: The usage of interpolations is
${expression}where expression gives the value you want to insert into the output as text. So${(5 + 8)/2}prints "6.5" to the output (or possibly "6,5" if the language of your output is not US English). - 
            
When you supply a value for the directive parameter: You have already seen the
ifdirective in the Getting Started section. The syntax of this directive is:<#if expression>...</#if>. The expression here must evaluate to a boolean value. For example in<#if 2 < 3>the2 < 3(2 is less than 3) is an expression which evaluates totrue. 
Quick overview (cheat sheet)
This is a reminder for those of you who already know FreeMarker or are just experienced programmers:
- Specify values directly
 - 
              Retrieving
              variables
              
- 
                  Top-level
                  variables: 
user - 
                  Retrieving
                  data from a hash: 
user.name,user["name"] - 
                  Retrieving data
                  from a sequence:
                  
products[5] - 
                  Special
                  variable: 
.main 
 - 
                  Top-level
                  variables: 
 - 
              String
              operations
              
- 
                  Interpolation
                  and concatenation:
                  
"Hello ${user}!"(or"Hello " + user + "!") - 
                  Getting a
                  character: 
name[0] - 
                  String
                  slice: Inclusive end: 
name[0..4], Exclusive end:name[0..<5], Length-based (lenient):name[0..*5], Remove starting:name[5..] 
 - 
                  Interpolation
                  and concatenation:
                  
 - 
              Sequence
              operations
              
- 
                  Concatenation:
                  
users + ["guest"] - 
                  Sequence
                  slice: Inclusive end:
                  
products[20..29], Exclusive end:products[20..<30], Length-based (lenient):products[20..*10], Remove starting:products[20..] 
 - 
                  Concatenation:
                  
 - 
              Hash
              operations
              
- 
                  Concatenation:
                  
passwords + { "joe": "secret42" } 
 - 
                  Concatenation:
                  
 - 
              Arithmetical
              calculations: 
(x * 1.5 + 10) / 2 - y % 100 - 
              Comparison:
              
x == y,x != y,x < y,x > y,x >= y,x <= y,x lt y,x lte y,x gt y,x gte y, ...etc. - 
              Logical
              operations: 
!registered && (firstVisit || fromEurope) - 
              Built-ins:
              
name?upper_case,path?ensure_starts_with('/') - 
              Method
              call: 
repeat("What", 3) - 
              Missing value
              handler operators:
              
- 
                  Default
                  value: 
name!"unknown"or(user.name)!"unknown"orname!or(user.name)! - 
                  Missing
                  value test: 
name??or(user.name)?? 
 - 
                  Default
                  value: 
 - 
              Assignment
              operators: 
=,+=,-=,*=,/=,%=,++,-- - 
              Local
              lambdas: 
x -> x + 1,(x, y) -> x + y 
See also: Operator precedence
Specify values directly
Often you want to specify a value directly and not as a result of some calculations.
Strings
To specify a string value directly you give the text in
            quotation marks, e.g.: "some text" or in
            apostrophe-quote, e.g. 'some text'. The two
            forms are equivalent. If the text itself contains the character
            used for the quoting (either " or
            ') or backslashes, you have to precede them
            with a backslash; this is called escaping. You can type any other
            character, including line
            breaks, in the text directly. Example:
${"It's \"quoted\" and
this is a backslash: \\"}
${'It\'s "quoted" and
this is a backslash: \\'}    will print:
It's "quoted" and this is a backslash: \ It's "quoted" and this is a backslash: \
Of course, you could simply type the above text into the
              template, without using
              ${...}. But we do
              it here just for the sake of example, to demonstrate
              expressions.
This is the list of all supported escape sequences. All other usage of backlash in string literals is an error and any attempt to use the template will fail.
| Escape sequence | Meaning | 
|---|---|
\" | 
                  Quotation mark (u0022) | 
\' | 
                  Apostrophe (a.k.a. apostrophe-quote) (u0027) | 
\{ | 
                  Opening curly brace: { | 
                
\= | 
                  Equals character: = (Supported since
                  FreeMarker 2.3.28.) | 
                
\\ | 
                  Back slash (u005C) | 
\n | 
                  Line feed (u000A) | 
\r | 
                  Carriage return (u000D) | 
\t | 
                  Horizontal tabulation (a.k.a. tab) (u0009) | 
\b | 
                  Backspace (u0008) | 
\f | 
                  Form feed (u000C) | 
\l | 
                  Less-than sign: < | 
                
\g | 
                  Greater-than sign: > | 
                
\a | 
                  Ampersand: & | 
                
\xCode | 
                  Character given with its hexadecimal Unicode code (UCS code) | 
The Code after
            the \x is 1 to 4 hexadecimal digits. For
            example this all put a copyright sign into the string:
            "\xA9 1999-2001",
            "\x0A9 1999-2001",
            "\x00A9 1999-2001". When the character directly
            after the last hexadecimal digit can be interpreted as hexadecimal
            digit, you must use all 4 digits or else FreeMarker will
            misunderstand you.
Note that the character sequence ${ and
            #{ (and rarely [= instead,
            depending on the
            configured syntax) has special meaning. They are used to
            insert the value of expressions (typically: the value of
            variables, as in "Hello ${user}!"). This will
            be explained later.
            If you want to print ${ or
            #{ (or [=), you should
            either use raw string literals as explained below, or escape the
            { like in "foo $\{bar}" (or
            the = like in "foo
            [\=bar]").
A special kind of string literals is the raw string
            literals. In raw string literals, backslash and
            ${ have no special meaning, they are considered
            as plain characters. To indicate that a string literal is a raw
            string literal, you have to put an r directly
            before the opening quotation mark or apostrophe-quote.
            Example:
${r"${foo}"}
${r"C:\foo\bar"}    will print:
${foo}
C:\foo\bar    Numbers
To specify a numerical value directly you type the number
            without quotation marks. You have to use the dot as your decimal
            separator and must not use any grouping separator symbols. You can
            use - or + to indicate the
            sign (+ is redundant). Scientific notation is
            not yet supported (so 1E3 is wrong). Also, you
            cannot omit the 0 before the decimal separator (so
            .5 is wrong).
Examples of valid number literals: 0.08,
            -5.013, 8,
            008, 11,
            +11
Note that numerical literals like 08,
            +8, 8.00 and
            8 are totally equivalent as they all symbolize
            the number eight. Thus, ${08},
            ${+8}, ${8.00} and
            ${8} will all print exactly same.
Booleans
To specify a boolean value you write true
            or false. Don't use quotation marks.
Sequences
To specify a literal sequence, you list the sub variables separated by commas, and put the whole list into square brackets. For example:
<#list ["foo", "bar", "baz"] as x>
${x}
</#list>    will print:
foo bar baz
The items in the list are expressions, so you can do this
            for example: [2 + 2, [1, 2, 3, 4], "foo"]. Here
            the first subvariable will be the number 4, the second will be
            another sequence, and the third subvariable will be the string
            "foo".
Ranges
Ranges are just sequences, but they are created by
            specifying what range of whole numbers they contain, instead of
            specifying their items one by one. For example,
            0..<m, assuming the m
            variable stores 5, will give a sequence that contains [0,
            1, 2, 3, 4]. Ranges are primarily used for iterating
            over a range of numbers with <#list
            ...> and for slicing
            sequences and slicing
            strings.
The generic forms of range expressions are (where
            start and
            end can be any
            expression that evaluates to a number):
- 
                
start..end: Range with inclusive end. For example,1..4gives[1, 2, 3, 4], and4..1gives[4, 3, 2, 1]. Beware, ranges with inclusive end never give an empty sequence, so0..length-1is WRONG, because when length is0it gives[0, -1]. - 
                
start..<endorstart..!end: Range with exclusive end. For example,1..<4gives[1, 2, 3],4..<1gives[4, 3, 2], and1..<1gives[]. Note the last example; the result can be an empty sequence. There's no difference between..<and..!; the last form is used in applications where using the<character causes problems (for HTML editors and such). - 
                
start..*length: Length limited range. For example,10..*4gives[10, 11, 12, 13],10..*-4gives[10, 9, 8, 7], and10..*0gives[]. When these kind of ranges are used for slicing, the slice will end without error if the end of the sliced sequence or string is reached before the specified range length was reached; see slicing sequences for more.Note:Length limited ranges were introduced in FreeMarker 2.3.21.
 - 
                
start..: Right-unbounded range. This are like length limited ranges with infinite length. For example1..gives[1, 2, 3, 4, 5, 6, ... ], up to infinity. Be careful when processing (like listing) such ranges, as processing all items of it it would take forever or until the application runs out of memory and crashes. Just like with length limited ranges, when these kind of ranges are used for slicing, the slice will end when the end of the sliced sequence or string is reached.Warning!Right-unbounded ranges before FreeMarker 2.3.21 were only used for slicing, and behaved like an empty sequence for other purposes. To activate the new behavior, it's not enough to use FreeMarker 2.3.21, the programmer also have to set the
incompatible_improvementsconfiguration setting to at least 2.3.21. 
Further notes on ranges:
- 
                
Range expressions themselves don't have square brackets, for example, you write
<#assign myRange = 0..<x, NOT<#assign myRange = [0..<x]>. The last would create a sequence that contains an item that's a range. The square brackets are part of the slicing syntax, likeseq[myRange]. - 
                
You can write arithmetical expression on the sides of the
..without parenthesis, liken + 1 ..< m / 2 - 1. - 
                
..,..<,..!and..*are operators, so you can't have space inside them. Liken .. <mis WRONG, butn ..< mis good. - 
                
The reported size of right-unbounded ranges is 2147483647 (or 0 if
incompatible_improvementsis less than 2.3.21) due to a technical limitation (32 bits). However, when listing them, their actual size is infinite. - 
                
Ranges don't really store the numbers they consist of, thus for example
0..1and0..100000000is equally fast to create and takes the same amount of memory. 
Hashes
To specify a hash in a template, you list the key/value
            pairs separated by commas, and put the list into curly brackets.
            The key and value within a key/value pair are separated with a
            colon. Here is an example: { "name": "green mouse",
            "price": 150 }. Note that both the names and the values
            are expressions. The keys must be strings. The values can be if
            any type.
Retrieving variables
Top-level variables
To access a top-level variable, you simply use the variable
            name. For example, the expression user will
            evaluate to the value of variable stored with name
            "user" in the root. So this will print what you store
            there:
${user}    If there is no such top-level variable, then an error will result when FreeMarker tries to evaluate the expression, and it aborts template processing (unless programmers has configured FreeMarker differently).
In this kind of expression, the variable name can only
            contain letters (including non-Latin letters), digits (including
            non-Latin digits), underline (_), dollar
            ($), at sign (@).
            Furthermore, the first character can't be an ASCII digit
            (0-9). Since FreeMarker
            2.3.22 the variable name can also contain minus
            (-), dot (.), and colon
            (:) at any position, but these must be escaped
            with a preceding backslash (\), otherwise they
            are interpreted as operators. For example, to read the variable
            whose name is "data-id", the expression is
            data\-id, as data-id would
            be interpreted as "data minus id". (Note that these
            escapes only work in identifiers, not in string literals.)
            Furthermore, since FreeMarker 2.3.31, hash mark
            (#) can also be used, but must be escaped with
            a preceding backslash (\).
Retrieving data from a hash
If we already have a hash as a result of an expression, then we can get its subvariable with a dot and the name of the subvariable. Assume that we have this data-model:
(root) | +- book | | | +- title = "Breeding green mouses" | | | +- author | | | +- name = "Julia Smith" | | | +- info = "Biologist, 1923-1985, Canada" | +- test = "title"
Now we can read the title with
            book.title, since the book expression will
            return a hash (as explained in the last chapter). Applying this
            logic further, we can read the name of the author with this
            expression: book.author.name.
There is an alternative syntax if we want to specify the
            subvariable name with an expression:
            book["title"]. In the square brackets you can
            give any expression as long as it evaluates to a string. So with
            this data-model you can also read the title with
            book[test]. More examples; these are all
            equivalent: book.author.name,
            book["author"].name,
            book.author["name"],
            book["author"]["name"].
When you use the dot syntax, the same restrictions apply
            regarding the variable name as with top-level variables (name can
            contain only letters, digits, _,
            $, @ but can't start with
            0-9, also starting from
            2.3.22 you can also use \-,
            \. and \:). There are no
            such restrictions when you use the square bracket syntax, since
            the name is the result of an arbitrary expression. (Note, that to
            help the FreeMarker XML support, if the subvariable name is
            * (asterisk) or **, then you
            do not have to use square bracket syntax.)
As with the top-level variables, trying to access a non-existent subvariable causes an error and aborts the processing of the template (unless programmers has configured FreeMarker differently).
Retrieving data from a sequence
This is the same as for hashes, but you can use the square
            bracket syntax only, and the expression in the brackets must
            evaluate to a number, not a string. For example to get the name of
            the first animal of the example data-model (remember
            that the number of the first item is 0, not 1):
            animals[0].name
Special variables
Special variables are variables defined by the FreeMarker
            engine itself. To access them, you use the
            .variable_name
            syntax.
Normally you don't need to use special variables. They are for expert users. The complete list of special variables can be found in the reference.
String operations
Interpolation and concatenation
If you want to insert the value of an expression into a
            string, you can use
            ${...} (and the
            deprecated #{...})
            in string literals.
            ${...} in string
            literals behaves
            similarly as in text
            sections (so it goes through the same locale
            sensitive number and date/time formatting).
It's possible to configure FreeMarker's interpolation
              syntax to use
              [=...] instead;
              see
              here.
Example (assume that user is "Big Joe"):
<#assign s = "Hello ${user}!">
${s} <#-- Just to see what the value of s is -->    This will print:
Hello Big Joe!
A frequent mistake of users is the usage of interpolations
              in places where they needn't/shouldn't/can't be used.
              Interpolations work only in text sections (e.g.
              <h1>Hello ${name}!</h1>) and in
              string literals (e.g. <#include
              "/footer/${company}.html">). A typical
              WRONG usage is <#if
              ${big}>...</#if>, which will cause a
              syntactical error. You should simply write <#if
              big>...</#if>. Also, <#if
              "${big}">...</#if> is
              WRONG, since it converts the parameter
              value to string and the if directive wants a
              boolean value, so it will cause a runtime error.
Alternatively,
            you can use the + operator to achieve similar
            result:
<#assign s = "Hello " + user + "!">
This gives the same result as the earlier example with the
            ${...}.
Because + follows similar rules as
              ${...}, the
              appended string is influenced by the locale,
              number_format,
              date_format, time_format,
              datetime_format and
              boolean_format, etc. settings, and thus the
              result targets humans and isn't in generally machine parseable.
              This mostly leads to problems with numbers, as many locales use
              grouping (thousands separators) by default, and so
              "someUrl?id=" + id becomes to something like
              "someUrl?id=1 234". To prevent this, use the
              ?c (for Computer audience) built-in, like in
              "someUrl?id=" + id?c or
              "someUrl?id=${id?c}", which will evaluate to
              something like "someUrl?id=1234", regardless
              of locale and format settings.
As when ${...}
            is used inside string expressions it's just a
            shorthand of using the + operator, auto-escaping is not
            applied on it.
Getting a character
You can get a single character of a string at a given index
            similarly as you can read the subvariable of a
            sequence, e.g. user[0]. The result will
            be a string whose length is 1; FTL doesn't have a separate
            character type. As with sequence sub variables, the index must be
            a number that is at least 0 and less than the length of the
            string, or else an error will abort the template
            processing.
Since the sequence subvariable syntax and the character
            getter syntax clashes, you can use the character getter syntax
            only if the variable is not a sequence as well (which is possible
            because FTL supports multi-typed values), since in that case the
            sequence behavior prevails. (To work this around, you can use
            the
            string built-in, e.g.
            user?string[0]. Don't worry if you don't
            understand this yet; built-ins will be discussed later.)
Example (assume that user is "Big Joe"):
${user[0]}
${user[4]}    will print (note that the index of the first character is 0):
B J
String slicing (substrings)
You can slice a string in the same way as you slice a sequence (see there), only here instead of sequence items you work with characters. Some differences are:
- 
                
Decreasing ranges aren't allowed for string slicing. (That's because unlike sequences, you seldom if ever want to show a string reversed, so if that happens, that's almost always the result of an oversight.)
 - 
                
If a value is both a string and a sequence (a multi-typed value), then slicing will slice the sequence instead of the string. When you are processing XML, such values are common. In such cases you can use
someXMLnode?string[range]to fore string slicing. - 
                
There's a legacy bug where a range with inclusive end that's one less than the starting index and is non-negative (like in
"abc"[1..0]) will give an empty string instead of an error. (It should be an error as it's a decreasing range.) Currently this bug is emulated for backward compatibility, but you shouldn't utilize it, as in the future it will be certainly an error. 
Example:
<#assign s = "ABCDEF">
${s[2..3]}
${s[2..<4]}
${s[2..*3]}
${s[2..*100]}
${s[2..]}    will print:
CD CD CDE CDEF CDEF
Some of the typical use-cases of string slicing is covered
              by convenient built-ins: remove_beginning,
              remove_ending,
              keep_before,
              keep_after,
              keep_before_last,
              keep_after_last
Sequence operations
Concatenation
You can concatenate sequences in the same way as strings,
            with +. Example:
<#list ["Joe", "Fred"] + ["Julia", "Kate"] as user>
- ${user}
</#list>    will print:
- Joe - Fred - Julia - Kate
Note that sequence concatenation is not to be used for many
            repeated concatenations, like for appending items to a sequence
            inside a loop. It's just for things like <#list users
            + admins as person>. Although concatenating sequences
            is fast and is constant time (it's speed is independently of the
            size of the concatenated sequences), the resulting sequence will
            be always a little bit slower to read than the original two
            sequences were. Thus, after tens or hundreds of repeated
            concatenations the result can be impractically slow to
            reader.
Sequence slicing
With
            seq[range],
            were range is a
            range value as
            described here, you can take a slice of the sequence. The
            resulting sequence will contain the items from the original
            sequence (seq) whose
            indexes are in the range. For example:
<#assign seq = ["A", "B", "C", "D", "E"]>
<#list seq[1..3] as i>${i}</#list>    will print
BCD
Furthermore, the items in the slice will be in the same
            order as in the range. Thus for example the above example with the
            3..1 range would print
            DCB.
The numbers in the range must be valid indexes in the
            sequence, or else the processing of the template will be aborted
            with error. Like in the last example,
            seq[-1..0] would be an error as
            seq[-1] is invalid, also
            seq[1..5] would be because
            seq[5] is invalid. (Note that
            seq[100..<100] or
            seq[100..*0] would be valid despite that 100 is
            out of bounds, because those ranges are empty.)
Length limited ranges
            (start..*length)
            and right-unbounded ranges
            (start..) adapt to
            the length of the sliced sequence. They will slice out at most as
            many items as there is available:
<#assign seq = ["A", "B", "C"]>
Slicing with length limited ranges:
- <#list seq[0..*2] as i>${i}</#list>
- <#list seq[1..*2] as i>${i}</#list>
- <#list seq[2..*2] as i>${i}</#list> <#-- Not an error -->
- <#list seq[3..*2] as i>${i}</#list> <#-- Not an error -->
Slicing with right-unlimited ranges:
- <#list seq[0..] as i>${i}</#list>
- <#list seq[1..] as i>${i}</#list>
- <#list seq[2..] as i>${i}</#list>
- <#list seq[3..] as i>${i}</#list>    This will print:
Slicing with length limited ranges: - AB - BC - C - Slicing with right-unlimited ranges: - ABC - BC - C -
Note above that slicing with length limited and right unbounded ranges allow the starting index to be past the last item by one (but no more).
To split a sequence to slices of a given size, you should
              use the chunk
              built-in.
Hash operations
Concatenation
You can concatenate hashes in the same way as strings, with
            +. If both hashes contain the same key, the
            hash on the right-hand side of the + takes
            precedence. Example:
<#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}>
- Joe is ${ages.Joe}
- Fred is ${ages.Fred}
- Julia is ${ages.Julia}    will print:
- Joe is 30 - Fred is 25 - Julia is 18
Note that hash concatenation is not to be used for many repeated concatenations, like for adding items to a hash inside a loop. While adding together hashes is fast and is constant time (independent of the size of the hashes added), the resulting hash is a bit slower to read than the hashes added together. Thus after tens or hundreds of additions the result can be impractically slow to read.
Arithmetical calculations
This is the basic 4-function calculator arithmetic plus the modulus operator. So the operators are:
- 
              Addition: 
+ - 
              Subtraction: 
- - 
              Multiplication: 
* - 
              Division: 
/ - 
              Modulus (remainder) of integer operands:
              
% 
Example:
${100 - x * x}
${x / 2}
${12 % 10}    Assuming that x is 5, it will print:
75 2.5 2
Both operands must be expressions which evaluate to a
          numerical value. So the example below will cause an error when
          FreeMarker tries to evaluate it, since "5" is a
          string and not the number 5:
${3 * "5"} <#-- WRONG! -->    There is an exception to the above rule. The
          + operator, is used to concatenate
          strings as well. If on one side of + is a
          string and on the other side of + is a numerical
          value, then it will convert the numerical value to string (using the
          format appropriate for language of the page) and then use the
          + as string concatenation operator.
          Example:
${3 + "5"}    35
Generally, FreeMarker never converts a string to a number automatically, but it may convert a number to a string automatically.
 People often want only the integer part of the result
          of a division (or of other calculations). This is possible with the
          int built-in. (Built-ins are explained later):
${(x/2)?int}
${1.1?int}
${1.999?int}
${-1.1?int}
${-1.999?int}    Assuming that x is 5, it will print:
2 1 1 -1 -1
Due to historical reasons, the % operator
          works by first truncating the operands to an integer number, and
          then returning the remainder of the division:
${12 % 5}   <#-- Prints 2 -->
${12.9 % 5} <#-- Prints 2 -->
${12.1 % 5} <#-- Prints 2 -->
${12 % 6}   <#-- Prints 0 -->
${12 % 6.9} <#-- Prints 0 -->    The sign of the result of % is the same as
          the sign of the left hand operand, and its absolute value is the
          same as if both operands where positive:
${-12 % -5} <#-- Prints -2 -->
${-12 % 5} <#-- Prints -2 -->
${12 % -5} <#-- Prints 2 -->    About the precision of the operations:
          By default FreeMarker uses BigDecimal-s for all
          arithmetical calculations, to avoid rounding and overflow/underflow
          artifacts, and also keeps the result as
          BigDecimal-s. So + (addition),
          - (subtraction) and *
          (multiplication) are "lossless". Again by default,
          / (division) results are calculated to 12
          decimals with half-up rounding (unless some operands have even more
          decimals, in which case it's calculated with that much decimals).
          All this behavior depends on the
          arithmetic_engine configuration setting
          (Configurable.setArithmericEngine(ArithmericEngine))
          though, and some application might use a different value than the
          default, although that's highly uncommon.
Comparison
Sometimes you want to know if two values are equal or not, or which value is the greater.
To show concrete examples I will use the if
          directive here. The usage of if directive is:
          <#if
          expression>...</#if>,
          where expression must evaluate to a boolean value or else an error
          will abort the processing of the template. If the value of
          expression is true then the things between the
          begin and end-tag will be processed, otherwise they will be
          skipped.
To test two values for equality you use ==
          (or = as a deprecated
          alternative) To test two values for inequality you use
          !=. For example, assume that
          user is "Big Joe":
<#if user == "Big Joe"> It is Big Joe </#if> <#if user != "Big Joe"> It is not Big Joe </#if>
The user == "Big Joe" expression in the
          <#if ...> will evaluate to the boolean
          true, so the above will say "It is Big
          Joe".
The expressions on both sides of the == or
          != must evaluate to a scalar (not a sequence or
          hash). Furthermore, the two scalars must have the same type (i.e.
          strings can only be compared to strings and numbers can only be
          compared to numbers, etc.) or else an error will abort template
          processing. For example <#if 1 == "1"> will
          cause an error. Note that FreeMarker does exact comparison, so
          string comparisons are case and white-space sensitive:
          "x" and "x " and
          "X" are not equal values.
For numerical and date, time and date-time values you can also
          use <, <=,
          >= and >. You can't use
          them for strings! Example:
<#if x <= 12> x is less or equivalent with 12 </#if>
There's a problem with >= and
          >. FreeMarker interprets the
          > character as the closing character of the
          FTL tag. To prevent this, you can use lt instead
          of <, lte instead of
          <=, gt instead of
          > and gte instead of
          >=, like in <#if x gt
          y>. Another trick it to put the expression into parentheses like in
          <#if (x > y)>, although it's considered
          to be less elegant.
FreeMarker supports some more syntactical alternatives:
- 
              
>and<can also be used, like in:<#if x > y>or<#if x >= y>. This isn't meant to be entered manually; it's to work around cases where the template gets XML/HTML escaped and the user can't easily prevent that happening. Note that in general FTL does not support entity references (the&...;things) in FTL tags; it's just an exception with these operators. - 
              
Deprecated forms:
\lt,\lte,\gtand\gte. These are the same as the ones without the backslash. 
Logical operations
Just the usual logical operators:
- 
              Logical or: 
|| - 
              Logical and: 
&& - 
              Logical not: 
! 
The operators will work with boolean values only. Otherwise an error will abort the template processing.
Example:
<#if x < 12 && color == "green"> We have less than 12 things, and they are green. </#if> <#if !hot> <#-- here hot must be a boolean --> It's not hot. </#if>
FreeMarker supports some more syntactical alternatives:
- 
              
\and(since FreeMarker 2.3.27): In some applications using&&causes problems as it's not valid in XML or HTML. While FreeMarker templates was never intended to be valid XML/HTML, only their output should be that, in reality there are some applications that expect the template itself to be valid XML/HTML regardless. This syntax is a workaround for such cases. Also note that unlike with the comparison operators,andwithout\is not supported due to backward compatibility restrictions. - 
              
&&(since FreeMarker 2.3.27): This isn't meant to be entered manually; it's to work around cases where the template gets XML/HTML escaped and the user can't easily prevent that happening. Note that in general FTL does not support entity references (the&...;things) in FTL tags; it's just an exception with these operators. - 
              
Deprecated forms:
&and|. Don't use them anymore. 
Built-ins
Built-ins are like methods that are added to the objects by
          FreeMarker. To prevent name clashes with actual methods and other
          sub-variables, instead of dot (.), you separate
          them from the parent object with question mark
          (?). For example, if you want to ensure that
          path has an initial / then you
          could write path?ensure_starts_with('/'). The
          Java object behind path (a
          String most certainly) doesn't have such method,
          FreeMarker adds it. For brevity, if the method has no parameters,
          you must omit the (), like,
          to get the length of path, you have to write
          path?length, not
          path?length().
The other reason why built-ins are crucial is that normally
          (though it depends on configuration settings), FreeMarker doesn't
          expose the Java API of the objects. So despite that Java's
          String has a length() method,
          it's hidden from the template, you have to use
          path?length instead. The advantage of that is
          that thus the template doesn't depend on the exactly type of the
          underlying Java objects. (Like path is maybe a
          java.nio.Path behind the scenes, but if the
          programmers has configure FreeMarker to expose
          Path objects as FTL strings, the template won't
          be aware of that, and ?length will work, despite
          that java.nio.Path has no similar method.)
You can find some of the most commonly used built-ins mentioned here, and the complete list of built-ins in the Reference. For now, just a few of the more important ones:
Example:
${testString?upper_case}
${testString?html}
${testString?upper_case?html}
${testSequence?size}
${testSequence?join(", ")}    Assuming that testString stores the string
          "Tom & Jerry", and testSequnce stores the strings
          "foo", "bar" and "baz", the
          output will be:
TOM & JERRY Tom & Jerry TOM & JERRY 3 foo, bar, baz
Note the test?upper_case?html above. Since
          the result of test?upper_case is a string, you
          can apply the html built-in on it.
Naturally, the left side of the built-in can be arbitrary expression, not just a variable name:
${testSeqence[1]?cap_first}
${"horse"?cap_first}
${(testString + " & Duck")?html}    Bar Horse Tom & Jerry & Duck
Method call
If you have a method then you can use the method call operation on it. The method call operation is a comma-separated list of expressions in parentheses. These values are called parameters. The method call operation passes these values to the method which will in turn return a result. This result will be the value of the whole method call expression.
For example, assume the programmers have made available a
          method variable called repeat. You give a string
          as the first parameter, and a number as the second parameter, and it
          returns a string which repeats the first parameter the number of
          times specified by the second parameter.
${repeat("Foo", 3)}    will print:
FooFooFoo
Here repeat was evaluated to the method
          variable (according to how you access top-level
          variables) and then ("What", 3) invoked
          that method.
I would like to emphasize that method calls are just plain expressions, like everything else. So this:
${repeat(repeat("x", 2), 3) + repeat("Foo", 4)?upper_case}    will print this:
xxxxxxFOOFOOFOOFOO
Handling missing values
These operators exist since FreeMarker 2.3.7 (replacing the
            default, exists and
            if_exists built-ins).
As we explained earlier, an error will occur and abort the
          template processing if you try to access a missing variable. However
          two special operators can suppress this error, and handle the
          problematic situation. The handled variable can be top-level
          variable, hash subvariable, or sequence subvariable as well.
          Furthermore these operators handle the situation when a method call
          doesn't return a value (from the
          viewpoint of Java programmers: it returns null or
          it's return type is void), so it's more
          correct to say that these operators handle missing values in
          general, rather than just missing variables.
For those who know what's Java
          null, FreeMarker 2.3.x
          treats them as missing values. Simply, the template language doesn't
          know the concept of null. For example, if you
          have a bean that has a maidenName property, and
          the value of that property is null, then that's
          the same as if there were no such property at all, as far as the
          template is concerned (assuming you didn't configured FreeMarker to
          use some extreme object wrapper, that is). The result of a method
          call that returns null is also treated as a
          missing variable (again, assuming that you use some usual object
          wrapper). See more in the
          FAQ.
If you wonder why is FreeMarker so picky about missing variables, read this FAQ entry.
Default value operator
Synopsis:
            unsafe_expr!default_expr
            or unsafe_expr! or
            (unsafe_expr)!default_expr
            or
            (unsafe_expr)!
This operator allows you to specify a default value for the case when the value is missing.
Example. Assume no variable called mouse
            is present:
${mouse!"No mouse."}
<#assign mouse="Jerry">
${mouse!"No mouse."}    The output will be:
No mouse. Jerry
The default value can be any kind of expression, so it
            doesn't have to be a string. For example you can write
            hits!0 or colors!["red", "green",
            "blue"]. There is no restriction regarding the
            complexity of the expression that specifies the default value, for
            example you can write: cargo.weight!(item.weight *
            itemCount + 10).
If you have a composite expression after the
              !, like 1 + x,
              always use parentheses, like
              ${x!(1 + y)} or ${(x!1) +
              y)}, depending on which interpretation you meant.
              That's needed because due to a programming mistake in FreeMarker
              2.3.x, the precedence of ! (when it's used as
              default value operator) is very low at its right side. This
              means that, for example, ${x!1 + y} is
              misinterpreted by FreeMarker as ${x!(1 + y)}
              while it should mean ${(x!1) + y}. This
              programming error will be fixed in FreeMarker 2.4, so you should
              not utilize this wrong behavior, or else your templates will
              break with FreeMarker 2.4!
If the default value is omitted, then it will be empty
            string and empty sequence and empty hash at the same time. (This
            is possible because FreeMarker allows multi-type values.) Note the
            consequence that you can't omit the default value if you want it
            to be 0 or false.
            Example:
(${mouse!})
<#assign mouse = "Jerry">
(${mouse!})    The output will be:
() (Jerry)
Due to syntactical ambiguities <@something
              a=x! b=y /> will be interpreted as
              <@something a=x!(b=y) />, that is, the
              b=y will be interpreted as a comparison that
              gives the default value for x, rather than
              the specification of the b parameter. To
              prevent this, write: <@something a=(x!) b=y
              />
You can use this operator in two ways with non-top-level variables:
product.color!"red"
This will handle if color is missing
            inside product (and returns
            "red" if so), but will not handle if
            product is missing. That is, the
            product variable itself must exist, otherwise
            the template processing will die with error.
(product.color)!"red"
This will handle if product.color is
            missing. That is, if product is missing, or
            product exists but it does not contain
            color, the result will be
            "red", and no error will occur. The important
            difference between this and the previous example is that when
            surrounded with parentheses, it is allowed for any component of
            the expression to be undefined, while without parentheses only the
            last component of the expression is allowed to be
            undefined.
Of course, the default value operator can be used with sequence sub variables as well:
<#assign seq = ['a', 'b']>
${seq[0]!'-'}
${seq[1]!'-'}
${seq[2]!'-'}
${seq[3]!'-'}    the outpur will be:
a b - -
A negative sequence index (as
            seq[-1]!'-') will always cause an error, you
            can't suppress that with this or any other operator.
Missing value test operator
Synopsis:
            unsafe_expr?? or
            (unsafe_expr)??
This operator tells if a value is missing or not. Depending
            on that, the result is either true or
            false.
Example. Assume no variable called mouse
            is present:
<#if mouse??> Mouse found <#else> No mouse found </#if> Creating mouse... <#assign mouse = "Jerry"> <#if mouse??> Mouse found <#else> No mouse found </#if>
The output will be:
No mouse found Creating mouse... Mouse found
With non-top-level variables the rules are the same as with
            the default value operator, that is, you can write
            product.color?? and
            (product.color)??.
Assignment Operators
These are actually not expressions, but parts of the syntax of
          the assignment directives, such as assign,
          local
          and global. As
          such, they can't be used anywhere else.
<#assign x += y> is shorthand for
          <#assign x = x + y>, <#assign x
          *= y> is shorthand for <#assign x = x *
          y>, and so on.
<#assign x++> differs from
          <#assign x += 1> (or <#assign x
          = x + 1>) in that it always does arithmetical addition
          (and fails if the variable is not a number), while the others are
          overloaded to do string and sequence concatenation and hash
          addition. <#assign x--> is shorthand for
          <#assign x -= 1>.
The shorthand operators (like +=,
            ++, etc.) are only supported since FreeMarker
            2.3.23. Before that, you could only use = in
            itself, as in <#assign x = x + 1>.
Local lambdas
FreeMarker doesn't support general purpose lambdas (unlike
          Java). The usage of lambdas is restricted to the parameters of
          certain built-ins,
          like: filter, map, take_while,
          drop_while.
The reason of this restriction is that FreeMarker doesn't implement binding/capturing variables that are referred from the lambda, instead it ensures that the evaluation of the lambda happens before the enclosing variable scope is ended. Hence, and to differentiate them from "real" lambdas, these are called local lambdas.
The syntax of lambdas is like
          (name1,
          name2, ...,
          nameN) ->
          expression. If there's only a
          single argument, the parentheses can be omitted:
          name1 ->
          expression.
As the right side of the -> is just a
          single expression, if you need complex logic there, you probably
          want to move that into a function, as the you can use
          directives like if, list, etc.
          In that case though, you don't need a lambda expression, as all
          built-ins that support a lambda parameter, also support passing in a
          function directly. For example, instead of seq?map(it ->
          myMapper(it)) you should just write
          seq?map(myMapper).
The argument specified in a lambda expression can hold the
          missing (Java null) value. Reading a lambda
          argument never falls back to higher scope, so a variable with
          identical name will not interfere when accessing the lambda
          parameter. Therefore something like seq?filter(it ->
          it??), which filters out missing element from the
          sequence, will work reliably.
Parentheses
Parentheses can be used to group any expressions. Some examples:
                               <#-- Output will be: -->
${3 * 2 + 2}                   <#-- 8 -->
${3 * (2 + 2)}                 <#-- 12 -->
${3 * ((2 + 2) * (1 / 2))}     <#-- 6 -->
${"green " + "mouse"?upper_case}    <#-- green MOUSE -->
${("green " + "mouse")?upper_case}  <#-- GREEN MOUSE -->
<#if !(color == "red" || color == "green")>
  The color is nor red nor green
</#if>    Note that the parentheses of a method call expressions have nothing to do with the parentheses used for grouping.
White-space in expressions
FTL ignores superfluous white-space in expressions. So these are totally equivalent:
${x + ":" + book.title?upper_case}    and
${x+":"+book.title?upper_case}    and
${
   x
 + ":"   +  book   .   title
   ?   upper_case
      }    Comments in expressions
Expression may contain comments anywhere where they can
          contain ignored white-space (see above). Comments
          look like <#-- ... --> or as [#--
          ... --]. Example:
<#assign x <#-- A comment --> = 123 <#-- A comment -->>
<#function f(x <#-- A comment -->, y <#-- A comment -->)>
  <#return <#-- A comment --> 1 <#-- A comment -->>
</#function>
<#assign someHash = {
    "foo": 123, <#-- A comment -->
    "bar": x <#-- A comment --> + 1,
    <#-- A comment -->
    "baaz": f(1 <#-- A comment -->, 2 <#-- A comment -->)
} <#-- A comment -->>    Operator precedence
The following table shows the precedence assigned to the
          operators. The operators in this table are listed in precedence
          order: the higher in the table an operator appears, the higher its
          precedence. Operators with higher precedence are evaluated before
          operators with a relatively lower precedence. Operators on the same
          line have equal precedence. When binary operators (operators with
          two "parameters", as + and
          -) of equal precedence appear next to each other,
          they are evaluated in left-to-right order.
| Operator group | Operators | 
|---|---|
| highest precedence operators | [subvarName]
                [subStringRange] . ?
                (methodParams)
                expr!
                expr?? | 
              
| unary prefix operators | +expr
                -expr !expr | 
              
| multiplicative operators | * / % | 
              
| additive operators | + - | 
              
| numerical ranges | .. ..<
                ..! ..* | 
              
| relational operators | < > <= >= (and equivalents:
                gt, lt, etc.) | 
              
| equality operators | == != (and equivalents:
                =) | 
              
| logical "and" operator | && | 
              
| logical "or" operator | || | 
              
| local lambda | -> | 
              
For those of you who know C, Java language or JavaScript, note that the precedence rules are the same as in those languages, except that FTL has some operators that do not exist in those languages.
The default value operator
          (exp!exp)
          is not yet in the table because of a programming mistake, which will
          be only fixed in FreeMarker 2.4 due to backward compatibility
          constraints. It meant to be a "highest precedence operator", but in
          FreeMarker 2.3.x the precedence on its right side is very low by
          accident. So if you have a composite expression on the right side,
          always use paranthesses, etiher like x!(y + 1) or
          like (x!y) + 1. Never write just x!y +
          1.
