These are the built-ins that don't care (much) about the type of their left hand argument.
switch
This built-in exists since FreeMarker 2.3.23.
This is basically the in-line (expression) version of the
switch
-case
-default
directives. Its generic format is like
matchedValue?switch(case1,
result1,
case2,
result2, ...
caseN,
resultN,
defaultResult)
, where
defaultResult
can be
omitted. Example:
<#list ['r', 'w', 'x', 's'] as flag> ${flag?switch('r', 'readable', 'w' 'writable', 'x', 'executable', 'unknown flag: ' + flag)} </#list>
readable writable executable unknown flag: s
That is, switch
will find the first
case
parameter (left
to right) whose value equals to
matchedValue
, then it
returns the value of the
result
parameter
that's directly after that
case
parameter. If it
doesn't find an equal
case
, then it will
return the value of the
defaultResult
, or if
there's no
defaultResult
parameter (i.e., if the number of parameters is even) then it stops
the template processing with error.
Further details:
-
The comparison of
matchedValue
to thecase
parameter value behaves exactly like the==
operator. Hence it only compares scalars and only same-type values. Thus, something likex?switch(1, "r1", "c2", "r2")
doesn't make sense, as ifx
is non-numerical then the first case will cause error, and ifx
is numerical then the second case will cause error (unlessx
is1
, as then we won't do further comparisons after the first one). -
Unlike with normal method calls, only those parameters of
switch(...)
are evaluated that are indeed needed. For example, intwo()?switch(c1(), r1(), c2(), r2(), c3(), r3())
, iftwo()
returns2
,c1()
returns1
, andc2()
returns2
, then only the following functions will be called, and in this order:m()
,c1()
,c2()
,r2()
. (Naturally, arguments that aren't evaluated can refer to missing variables without causing error.) It's guaranteed that thecase
parameter expressions are evaluated left to right, and only until the first match was found. It's also guaranteed that only theresult
expression that belongs to the first matchingcase
will be evaluated. It's also guaranteed that thedefaultResult
expression will only be evaluated if there was no matchingcase
parameter. -
The
case
parameter expressions need not be constant values, they can be arbitrary complex expressions. Of course, the same goes for and theresult
,defaultResult
, andmatchedValue
. -
There's no restriction regarding the type of the
case
parameter values, like they can be strings, or numbers, or dates, etc. However, because of how the==
operator works, it doesn't make sense to usecase
parameters of different types inside the sameswitch
(see earlier why). -
Unlike with the
case
directive, there's no fall-through behavior there, that is, there's no need for an equivalent of thebreak
directive.
If you need to switch by a boolean value, you should use the
then
built-in instead, like
matchedBoolean?then(whenTrue,
whenFalse)
.
If you need to do arbitrary logical tests instead of simple
equality comparisons at the
case
parameters, you
can do something like this (here we tests for ranges):
true?switch(priority <= 1, "low", priority == 2,
"medium", priority >= 3, "high")