Conversion
Three builtins for moving values between kinds. str renders any value as a string, num parses numeric text, bool applies the truthiness rules. Use them at boundaries — when reading form input, accepting query parameters, or preparing values for an external API — not for normal arithmetic.
str — render anything as a string
Numbers, bools, arrays, objects, null
str(value) calls the type's canonical rendering. Numbers use their natural decimal form; booleans become 'true' / 'false'; arrays and objects use the same compact form interpolation does. null becomes 'null'.
<p> ([str(42)])
<p> ([str(3.14)])
<p> ([str(true)]) str(42) → (42)
str(3.14) → (3.14)
str(true) → (true)
num — parse a string as a number
Float result; non-numeric strings become 0
num(s) parses the string as a decimal number, returning a float. Leading and trailing whitespace is tolerated. A string that doesn't parse cleanly returns 0 — wrap the call in a guard if you need to distinguish "parsed to zero" from "garbage in".
<p> [num('3.14')]
<p> [num('42')] num('3.14') = 3.14
num('42') = 42
bool — truthiness
Same rules as guards: 0 / empty / null are false
bool(value) returns the JavaScript-style truthiness of any value. 0, '', null, empty arrays, and empty objects are all false; everything else is true. The same rules drive guard conditions, so (value) in a guard is equivalent to (bool(value)).
<p> [bool(0)]
<p> [bool('hi')]
<p> [bool(null)]
<p> [bool([])] bool(0) = false
bool('hi') = true
bool(null) = false
bool([]) = false
Form-input coercion
Strings arrive from the wire — coerce before use
Inputs from <input> are always strings, even on type='number'. If you need to do arithmetic on the value, wrap it in num(...) first. Same for query parameters and JSON values whose schema you don't control.
> page
qty: '0'
total >> num(qty) * 9.99
<input value[qty] on_input[qty << event.target.value]>
<p> Total: $[total] Next: Collections — range, sort, filter, map, reduce, and the dozen other array helpers.