RatMinimal web framework

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)]
Result

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)]
Result

'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]
Result

[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)]
Result

[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')]
Result

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