Built-ins to handle undefined variables
As we explained in the chapter about expressions, an error will occur and abort the template processing if you try to access a non-existent variable. However four special built-ins can suppress this error, and examine if the variable is present or not. The examined variable can be top-level variable, hash sub-variable, or sequence sub-variable as well. These built-ins can be used with all variable types.
Note
The usage of these built-ins is usually the sign of bad practice. You may revisit you data model so you don't need to use these built-ins.
This built-in allows you to specify a default value for an undefined expression.
Example. Assume no variable called mouse is present:
 |  |  |
 |
${mouse?default("No mouse.")}
<#assign mouse="Jerry">
${mouse?default("No mouse.")} |
|  |
 |  |  |
The output will be:
So, you always use this built-in in a syntactic construct expr?default(default-expr). If expr is defined, it evaluates to expr, otherwise it evaluates to default-expr.
You can use this built-in in two ways with non-top-level variables:
 |  |  |
 |
product.color?default("red") |
|  |
 |  |  |
This examines if the product hash contains a subvariable called color or not, and returns "red" if not. The important point is that product hash itself must exist, otherwise the template processing will die with error.
 |  |  |
 |
(product.color)?default("red") |
|  |
 |  |  |
This examines if product.color exists or not. That is, if product does not exist, 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 usage 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 built-in can be used with sequence sub-variables as well:
 |  |  |
 |
<#assign seq = ['a', 'b']>
${seq[0]?default('-')}
${seq[1]?default('-')}
${seq[2]?default('-')}
${seq[3]?default('-')} |
|  |
 |  |  |
the outpur will be:
A negative sequence index (as seq[-1]?default('-')) will cause an error even with default (and similar) built-ins.
It is true if the variable exists and is not ``empty'', otherwise it is false. The meaning of ``empty'' depends on the concrete case. This follows intuitive common-sense ideas. The following are empty: a string with 0 length, sequence or hash with no subvariables, a collection which has passed the last element. Numbers are never considered empty. Note that when your data model implements multiple template model interfaces you may get unexpected results. However, when in doubt you can use always use expr?if_exists?size > 0 or expr?if_exists?length > 0 instead of expr?has_content.
With non-top-level variables the rules are the same as with default built-in, that is, you can write product.color?has_content and (product.color)?has_content