-
Notifications
You must be signed in to change notification settings - Fork 1
/
transactions.jl
45 lines (37 loc) · 1.22 KB
/
transactions.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@use "github.com/jkroso" [
"Prospects.jl" assoc dissoc prepend @struct
"DOM.jl" jsonable]
"""
A `Change` represents a transformation that could be applied to a data structure.
Its like a git diff. A one argument function can serve the same purpose but for now
I'm using a special type since it is simpler to implement methods on.
"""
abstract type Change end
# stops it sending event handlers to the JS runtime
jsonable(::Change) = false
@struct Merge(data) <: Change
Merge(;keys...) = Merge(keys)
@struct Unshift(item) <: Change
@struct Assoc(key, value) <: Change
@struct Swap(value) <: Change
@struct Delete() <: Change
@struct Identity() <: Change
@struct Dissoc(key) <: Change
Merge(;kw...) = Merge(Dict(kw...))
"""
apply a change to `x` if `a` isn't a change then it's assumed to be a literal
value which replaces `b`
"""
apply(a, b) = a
apply(m::Merge, data) =
reduce(pairs(m.data), init=data) do out, (key, value)
assoc(out, key, apply(value, get(data, key)))
end
apply(a::Assoc, data) = begin
value = apply(a.value, get(data, a.key))
assoc(data, a.key, value)
end
apply(u::Unshift, data) = prepend(data, u.item)
apply(s::Swap, data) = s.value
apply(a::Delete, data) = nothing
apply(a::Dissoc, data) = dissoc(data, a.key)