Type independent built-ins - Apache FreeMarker Manual

Unsupported web browser - Use a modern browser to view this website!

- Home
- Manual
- Java API

- Contribute
- Report a Bug
- Download

Manual
Previous Next

# Type independent built-ins

These are the built-ins that don't care (much) about the type of their left hand argument.

## switch

Note:

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:

Template

    <#list ['r', 'w', 'x', 's'] as flag>
      ${flag?switch('r', 'readable', 'w' 'writable', 'x', 'executable', 'unknown flag: ' + flag)}
    </#list>

Output

      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 the `case` parameter value behaves exactly like the `==` operator. Hence it only compares scalars and only same-type values. Thus, something like `x?switch(1, "r1", "c2", "r2")` doesn't make sense, as if `x` is non-numerical then the first case will cause error, and if `x` is numerical then the second case will cause error (unless `x` is `1`, 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, in `two()?switch(c1(), r1(), c2(), r2(), c3(), r3())`, if `two()` returns `2`, `c1()` returns `1`, and `c2()` returns `2`, 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 the `case` parameter expressions are evaluated left to right, and only until the first match was found. It's also guaranteed that only the `result` expression that belongs to the first matching `case` will be evaluated. It's also guaranteed that the `defaultResult` expression will only be evaluated if there was no matching `case` parameter.

- The `case` parameter expressions need not be constant values, they can be arbitrary complex expressions. Of course, the same goes for and the `result`, `defaultResult`, and `matchedValue`.

- 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 use `case` parameters of different types inside the same `switch` (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 the `break` directive.

Note:

If you need to switch by a boolean value, you should use the `then` built-in instead, like `matchedBoolean?then(whenTrue, whenFalse)`.

Note:

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")`

Previous Next