julia> x = Node(1)
Observable{Int64} with 0 listeners. Value:
1
julia> obsfunc = on(x) do x
@show x
end
(::Observables.ObserverFunction) (generic function with 0 methods)
julia> x[] = 3
x = 3
3
julia> off(obsfunc)
true
julia> x[] = 4
4
julia> y = lift(x) do x
println("y is still there")
3 * x
end
y is still there
y is still there
Observable{Int64} with 0 listeners. Value:
12
julia> x[] = 5
y is still there
5
julia> y = lift(x) do x
println("new y")
4 * x
end
new y
new y
Observable{Int64} with 0 listeners. Value:
20
julia> x[] = 6
y is still there
new y
6
julia> deleteat!(x.listeners, 1)
1-element Vector{Any}:
(::Observables.OnUpdate{Observables.MapUpdater{var"#307#308", Int64}, Tuple{Observable{Int64}}}) (generic function with 1 method)
julia> x[] = 7
new y
7
julia> empty!(x.listeners)
Any[]
julia> x[] = 8
8
So, if I correctly understand, I have to manually remove the concrete function from the list of listeners of all input observables/nodes that I used during the lift call?
I’ll rephrase it once more. Do I correctly understand that if I want to remove a lifted observable, there is no function that would traverse the “parents” of my observable and deregister?
Is it feasible to write such a function? Or, would it require a bi-directional reference list (of “lifts”) as part of Observable structure, so we know on which objects to deregister?
Yeah this problem with missing links is one of my gripes with Observables. Before I added the observerfunc thing, you couldn’t even remove those with a single off call, you always had to keep the exact function and observable together to unlink them again.
The connections are made via closures though, so in principle it could be possible to scan those for observables and disconnect. Might be hard to implement correctly.
It appears that for the specific case of lift, a specific listener object is created where you can access the targeted observable. But there could always be side effects in the listener functions etc.
julia> x = Node(1)
Observable{Int64} with 0 listeners. Value:
1
julia> y = @lift($x * 3)
Observable{Int64} with 0 listeners. Value:
3
julia> x.listeners[1].f.observable
Observable{Int64} with 0 listeners. Value:
3
julia> x.listeners[1].f.observable === y
true
x = something
function a_function()
do_something_with(x)
end
If you only have x, I have no idea how to find out it’s referenced in a_function in Julia. Probably need internals that traverse memory structures, something like this would be needed for garbage collection anyway.