Vascula v0.1.5

Values and truthiness

#Kinds of values

KindWritten asNotes
String"text" or 'text'A backslash takes the next character literally: "say \"hi\"". There are no escape sequences such as \n.
Integer42, -7Exact 64-bit integers.
Decimal3.14, -0.564-bit floating point. Exponent notation is not accepted.
Booleantrue, false
Nothingnil or nullPrints nothing.
Emptyempty or blankOnly for comparisons; see Empty.
Range(1..5)A list of integers; see Loops.
Array, mapfrom data onlyThere are no array or map literals.
Template
{{ "double" }} {{ 'single' }} {{ "say \"hi\"" }} {{ 42 }} {{ -0.5 }} {{ true }} [{{ nil }}]
Output
double single say "hi" 42 -0.5 true []

#Integers stay exact

A number without a decimal point is an exact integer, and arithmetic between two integers stays exact. This matters for large identifiers.

Template
{{ 9007199254740993 | plus: 1 }} {{ 10 | divided_by: 4 }} {{ 10 | divided_by: 5 }}
Output
9007199254740994 2.5 2

Division keeps a fractional result. A calculation that overflows 64 bits falls back to floating point. Data from the application keeps its own type: numbers decoded from JSON are floating point.

#Truthiness

Conditions such as {% if %} test whether a value is truthy.

ValueIn a condition
falsefalse
nil, a missing fieldfalse
truetrue
0, 0.0true
"" (empty string)true
[], {} (empty array or map)true
any other valuetrue

Only false and nothing are false. To ask "is there anything here?", compare with blank, or check .size.

Template
{% if settings.zero %}0 is true{% endif %}, {% if settings.text %}"" is true{% endif %}, {% if settings.missing %}{% else %}missing is false{% endif %}
Data
{"settings": {"zero": 0, "text": ""}}
Output
0 is true, "" is true, missing is false

#Empty and blank

empty and blank are the same marker. A value equals it when the value is nothing, an empty string, or a collection with no entries. A string of spaces is not blank.

Template
{% if settings.title == blank %}No title{% endif %} / {% if settings.tags == empty %}No tags{% endif %} / {% if settings.space == blank %}blank{% else %}not blank{% endif %}
Data
{"settings": {"title": "", "tags": [], "space": " "}}
Output
No title / No tags / not blank

#Comparing values

OperatorMeaning
==, !=Equal, not equal.
<, >, <=, >=Order. Both sides must be numbers, or both strings.
containsSubstring of a string, or member of an array.

Equality is forgiving: numbers compare as numbers, and a string that is a number equals that number. Anything else compares by its printed text.

Template
{{ 1 == 1.0 }} {{ "5" == 5 }} {{ "a" == "a" }} {{ nil == nil }} {{ "1" != 2 }}
Output
true true true true true

Ordering is strict. Comparing a number with a string, or anything that is not a number or string, is an error, never a silent false.

Template
{{ 2 > 1 }} {{ "b" > "a" }} {{ 10 >= 10 }}
Output
true true true
Template
{% if settings.count > "3" %}more{% endif %}
Data
{"settings": {"count": 5}}
Error
cannot compare number and string with ">"

contains looks for a substring in a string, or an equal member in an array. It is always false for maps and other values.

Template
{{ "teapot" contains "tea" }} {{ settings.tags contains "new" }} {{ settings.tags contains "old" }}
Data
{"settings": {"tags": ["new", "sale"]}}
Output
true true false

#How values print

ValuePrints as
Stringitself, HTML-escaped
Integerdigits: 42
Decimalshortest exact form: 2.5, 3 for 3.0
Booleantrue or false
nilnothing
Arrayits items printed one after another, with no separator; use join
Mapa debugging form; print its fields instead
Template
{{ settings.list }} | {{ settings.list | join: ", " }} | {{ 3.0 }}
Data
{"settings": {"list": ["a", "b", "c"]}}
Output
abc | a, b, c | 3

Next: Variables, data and scope.