Inspection
Five builtins for inspecting values. len counts, type labels, keys and values unpack objects, and has checks membership. They work the same way on strings, arrays, and objects: the same call gives the right answer regardless of shape.
len: count the elements
Strings, arrays, objects all work
len(value) returns the size: byte length for strings, element count for arrays, key count for objects. Calling it on a number, bool, or null is an error, so use those values directly.
<p> [len('abc')]
<p> [len(items)]
<p> [len(person)] string: 3
array: 3
object: 2
type: the runtime kind
One of: null, bool, int, float, string, array, object, function
type(value) returns the kind as a string. Use it to branch on shape in a function that accepts a few possibilities. int and float are distinct: the server tier keeps them apart even though both are number in the browser.
<p> [type('hi')]
<p> [type(42)]
<p> [type(3.14)]
<p> [type(true)]
<p> [type(items)]
<p> [type(person)]
<p> [type(null)] 'hi' → string
42 → int
3.14 → float
true → bool
items → array
person → object
null → null
keys: list the field names
Insertion order, as written in the source
keys(obj) returns the field names in the order they were declared. Pair with in keys(obj) to iterate. Calling it on an array returns the integer indices as strings.
<p> [keys(person)]
<ul>
[k] in keys(person)
<li> [k] [first, last]
- first
- last
values: list the field values
Same order as keys; pairs by index
values(obj) returns the values in the same order keys would. Zip them together when you need [k, v] pairs.
<p> [values(person)] [Grace, Hopper]
has: membership test
true / false; works on objects, arrays, strings
has(obj, name) returns whether the key exists on the object. On arrays it tests element membership; on strings, substring presence. contains is its alias for arrays and strings. Use whichever reads better in context.
<p> [has(person, 'first')]
<p> [has(person, 'age')]
<p> [has(items, 'pears')]
<p> [has('hello world', 'lo wo')] person.first exists? true
person.age exists? false
items has 'pears'? false
'hello world' has 'lo wo'? false
Putting them together
Dispatch on type
Combine type with a guard chain to render different markup per kind. The same approach sanitises user input or normalises mixed data into a uniform shape before storage.
> render_value[v]
(type(v) == 'array')
<ul>
[x] in v
<li> [x]
(type(v) == 'object')
<dl>
[k] in keys(v)
<dt> [k]
<dd> [v[k]]
(else)
<p> [v] See also Collections · Guards and loops · Logging