ddonche/goblin-lang
0.46.24
1
0
docs reference
[[map]]

Map


In Goblin, a map is a collection of key-value pairs. Keys are unique. Values can be anything. Maps are unordered — keys are stored alphabetically internally.


Creating a Map

person | {
    name: "Daniel"
    age: 44
    active: true
}
person | {
    name: "Daniel"
    age: 44
    active: true
}

Keys are bare identifiers. Values are any Goblin expression.

Single-line form using commas:

person | { name: "Daniel", age: 44 }
person | { name: "Daniel", age: 44 }


Map Lookup

Map lookup uses braces:

person{"name"}    /// -> "Daniel"
person{"age"}     /// -> 44
person{"name"}    /// -> "Daniel"
person{"age"}     /// -> 44

This is intentional. Arrays use brackets for positional lookup. Maps use braces for keyed lookup. The syntax tells you what kind of operation you are reading.

routes[0]         /// positional — this is an array
person{"name"}    /// keyed — this is a map
routes[0]         /// positional — this is an array
person{"name"}    /// keyed — this is a map

If you use braces on an array, Goblin errors:

routes{"name"}
/// error: used {} on an array — arrays use positional lookup with []
routes{"name"}
/// error: used {} on an array — arrays use positional lookup with []


Key That Does Not Exist

If the key is missing, Goblin errors:

person{"email"}
/// error: no-such-key: missing key 'email'
person{"email"}
/// error: no-such-key: missing key 'email'

Check first with :has before reading an uncertain key:

if :has(person, "email") => say person{"email"}
if :has(person, "email") => say person{"email"}


Updating an Entry

Use :update! with brace lookup:

:update!(person{"age"}, 45)
:update!(person{"age"}, 45)

Or use :update_at!:

:update_at!(person, "age", 45)
:update_at!(person, "age", 45)

:update_at! errors if the key does not already exist.


Adding an Entry

Use :put_at!:

:put_at!(person, "email", "dan@example.com")
:put_at!(person, "email", "dan@example.com")

:put_at! inserts the key if it does not exist, or overwrites it if it does.


Removing an Entry

Use :delete_at!:

:delete_at!(person, "email")
:delete_at!(person, "email")

Remove all entries matching a predicate on values:

:delete_where!(person, "is_nil")
:delete_where!(person, "is_nil")


Reading a Value by Key

:grab_at returns a value by key without modifying the map:

val | :grab_at(person, "age")    /// -> 44, person unchanged
val | :grab_at(person, "age")    /// -> 44, person unchanged


Remove and Return a Value

:reap_at! removes a key and returns its value:

name | :reap_at!(person, "name")
/// name -> "Daniel"
/// person no longer has "name" key
name | :reap_at!(person, "name")
/// name -> "Daniel"
/// person no longer has "name" key


Checking for a Key

:has(person, "name")    /// -> true
:has(person, "email")   /// -> false
:has(person, "name")    /// -> true
:has(person, "email")   /// -> false


Counting Entries

:count(person)    /// -> 2
:count(person)    /// -> 2


Iterating

Keys only

k_list | :keys(person)
/// -> [age, name]
k_list | :keys(person)
/// -> [age, name]

Values only

v_list | :values(person)
/// -> [44, Daniel]
v_list | :values(person)
/// -> [44, Daniel]

Key-value pairs

:items returns an array of pairs:

:items(person)
/// -> [(age, 44), (name, Daniel)]
:items(person)
/// -> [(age, 44), (name, Daniel)]

To walk keys and values together, use :keys with lookup:

for key in :keys(person)
    val | person{key}
    say key
    say val
xx
for key in :keys(person)
    val | person{key}
    say key
    say val
xx


Type Check

:valtype(person)    /// -> "map"
:valtype(person)    /// -> "map"