Working with immutable state¶
Modifications¶
Because all data in Arza immutable there is special need for support of deeply nested modifications of data structures
Consider Map
let person = {
name = "Bob",
addresses = {
work="Vatutina st. 24/15",
homes=["Gagarina st. 78", "Gorodotskogo st. 15"]
}
}
If we need to create new copy of this map with new home address
and if we have only standart function put
to work with, code might be very verbose
let new_adress = "Zelena st. 20"
let new_person = put(person,
#adresses,
put(person.adresses,
#homes,
cons(new_adress, person.adresses.homes)))
This is hard to read and very error prone. Instead in Arza you can just write
let new_adress = "Zelena st. 20"
let new_person = person.{adresses.homes = cons(new_adress, @)}
// Here @ placeholder means current path inside data structure
// in case of this example it will be person.addresses.homes
Syntax like object.property = value
impossible in Arza.
Instead you can use more powerfull modification syntax where you can add more than one change at once.
With this syntax you can also emulate +=
operator from imperative languages
More complex examples
fun test_map() =
let
d = {
y = 2,
s1 = {
(True) = False,
s2 = {
x = 1,
s3 = {
a = 10
}
}
}
}
d1 = d.{
s1.True = not @,
s1.s2.x = @ + 1,
s1.s2 = @.{
x=42,
z=24
},
s1.s2 = @.{
s3 = @.{
a = @ - 30,
b = 20
}
},
s1.s2.x = @ - 66,
y = (@ +
@/2.0*@ *
seq:reduce([@, @, @], `+`)
) + `*`(@, @)
}
in
affirm:is_equal(d1, {y=18.0, s1={s2={z=24, x=-24, s3={b=20, a=-20}}, (True)=True}})
fun test_list() =
let
d =[
[0,1,2],
3,
4,
[5,6,7, [8, 9, [10]]]]
d1 = d.{
0 = seq:map(@, (x) -> x * x),
1 = @ * @,
2 = @,
(3).(3) = @.{
0 = @ * 8,
1 = @ * 9
},
(3).(3).((fun () = 2)()).0 = ((x) -> @ * x)(4.2)
}
in
affirm:is_equal(d1, [[0, 1, 4], 9, 4, [5, 6, 7, [64, 81, [42.0]]]])
Default values¶
Arza does not support keyword arguments in functions, if you want to receive some kind of arbitrary options you can use maps. However often in such option maps some keys must be set to default values.
Arza support special syntax for updating data structure value if it is absent
let
v = {x=1, y=2}
// right side of or operator will be assigned to x
// only if there are no previous value
v1 = v.{x or 42, z or 42, y = 42}
// the same works with lists, tuples and other data structs
l = [0, 1, 2, 3]
l1 = l.{0 or 5}
in
affirm:is_equal(v1, {y = 42, x = 1, z = 42})
affirm:is_equal(l1, l)