Skip to content

Commit

Permalink
Update on value change (#68)
Browse files Browse the repository at this point in the history
  • Loading branch information
yha committed Feb 22, 2021
1 parent 2fe0cf8 commit 0f94e69
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 1 deletion.
43 changes: 42 additions & 1 deletion src/Observables.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Observables

export Observable, on, off, onany, connect!, obsid, async_latest, throttle
export Observable, on, off, onany, connect!, obsid, observe_changes, async_latest, throttle

import Base.Iterators.filter

Expand Down Expand Up @@ -477,6 +477,47 @@ Observable{$Int} with 0 listeners. Value:
map!(f, Observable(f(arg1[], map(to_value, args)...)), arg1, args...; update=false)
end

"""
obs = observe_changes(arg::AbstractObservable, eq=(==))
Returns an `Observable` which updates with the value of `arg` whenever the new value
differs from the current value of `obs` according to the equality operator `eq`.
# Example:
```
julia> obs = Observable(0);
julia> obs_change = observe_changes(obs);
julia> on(obs) do o
println("obs[] == \$o")
end;
julia> on(obs_change) do o
println("obs_change[] == \$o")
end;
julia> obs[] = 0;
obs[] == 0
julia> obs[] = 1;
obs_change[] == 1
obs[] == 1
julia> obs[] = 1;
obs[] == 1
```
"""
function observe_changes(obs::AbstractObservable{T}, eq=(==)) where T
out = Observable{T}(obs[])
on(obs) do val
if !eq(val, out[])
out[] = val
end
end
out
end

"""
async_latest(observable::AbstractObservable, n=1)
Expand Down
23 changes: 23 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,29 @@ end
@test c[] == 103
end

@testset "observe_changes" begin
o = Observable(0)
changes = observe_changes(o)
changes_approx = observe_changes(o, (x,y) -> abs(x-y) < 2)
@test eltype(changes) == eltype(changes_approx) == Int
@test changes[] == changes_approx[] == 0

values = Int[]
values_approx = Int[]
on(changes) do v
push!(values, v)
end
on(changes_approx) do v
push!(values_approx, v)
end

for i in 1:100
o[] = floor(Int, i/10)
end
@test values == 1:10
@test values_approx == 2:2:10
end

@testset "async_latest" begin
o = Observable(0)
cnt = Ref(0)
Expand Down

2 comments on commit 0f94e69

@timholy
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/30595

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.4.0 -m "<description of version>" 0f94e69cabddd87fcf057fb95ed5dc64be9661de
git push origin v0.4.0

Please sign in to comment.