-
-
Notifications
You must be signed in to change notification settings - Fork 313
ArgumentsObservable
jkrumbiegel edited this page Nov 18, 2020
·
1 revision
struct Arguments
args::Tuple
kwargs::NamedTuple
end
function Arguments(args...; kwargs...)
Arguments(Tuple(args), NamedTuple(kwargs))
end
function Base.getindex(a::Arguments, i::Int)
a.args[i]
end
function Base.getindex(a::Arguments, s::Symbol)
a.kwargs[s]
end
mutable struct ArgumentsObservable
arguments::Arguments
listeners::Vector{Pair{Tuple, Any}}
end
function validate(ao, pairs)
for (id, _) in pairs
ao.arguments[id]
end
nothing
end
function update_arguments!(ao, pairs)
dict = Dict(pairs)
newargs = Tuple(get(dict, i, ao.arguments[i]) for i in eachindex(ao.arguments.args))
newkwargs = NamedTuple(kw => get(dict, kw, ao.arguments[kw]) for kw in keys(ao.arguments.kwargs))
newarguments = Arguments(newargs, newkwargs)
ao.arguments = newarguments
nothing
end
function update!(ao::ArgumentsObservable, pairs::AbstractVector{<:Pair})
validate(ao, pairs)
update_arguments!(ao, pairs)
updated_identifiers = Set(first.(pairs))
for (used_identifiers, listener) in ao.listeners
if !isempty(intersect(Set(used_identifiers), updated_identifiers))
listener(updated_identifiers, (ao.arguments[i] for i in used_identifiers)...)
end
end
end
ao = ArgumentsObservable(Arguments(randn(100), randn(100), color = randn(100)), [])
function on(f, ao::ArgumentsObservable, args::Union{Int, Symbol}...)
push!(ao.listeners, Tuple(args) => f)
f
end
on(ao, 1, :color) do changed, x, color
println("What changed?")
println(changed)
if 1 in changed
println("New x length: $(length(x))")
end
if :color in changed
println("New color length: $(length(color))")
end
end
# no reaction
update!(ao, [2 => randn(100)])
# reaction
update!(ao, [1 => randn(200), :color => randn(200)])