Skip to content

Commit 0f94e69

Browse files
authored
Update on value change (#68)
1 parent 2fe0cf8 commit 0f94e69

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

src/Observables.jl

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module Observables
22

3-
export Observable, on, off, onany, connect!, obsid, async_latest, throttle
3+
export Observable, on, off, onany, connect!, obsid, observe_changes, async_latest, throttle
44

55
import Base.Iterators.filter
66

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

480+
"""
481+
obs = observe_changes(arg::AbstractObservable, eq=(==))
482+
483+
Returns an `Observable` which updates with the value of `arg` whenever the new value
484+
differs from the current value of `obs` according to the equality operator `eq`.
485+
486+
# Example:
487+
```
488+
julia> obs = Observable(0);
489+
490+
julia> obs_change = observe_changes(obs);
491+
492+
julia> on(obs) do o
493+
println("obs[] == \$o")
494+
end;
495+
496+
julia> on(obs_change) do o
497+
println("obs_change[] == \$o")
498+
end;
499+
500+
julia> obs[] = 0;
501+
obs[] == 0
502+
503+
julia> obs[] = 1;
504+
obs_change[] == 1
505+
obs[] == 1
506+
507+
julia> obs[] = 1;
508+
obs[] == 1
509+
```
510+
"""
511+
function observe_changes(obs::AbstractObservable{T}, eq=(==)) where T
512+
out = Observable{T}(obs[])
513+
on(obs) do val
514+
if !eq(val, out[])
515+
out[] = val
516+
end
517+
end
518+
out
519+
end
520+
480521
"""
481522
async_latest(observable::AbstractObservable, n=1)
482523

test/runtests.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,29 @@ end
185185
@test c[] == 103
186186
end
187187

188+
@testset "observe_changes" begin
189+
o = Observable(0)
190+
changes = observe_changes(o)
191+
changes_approx = observe_changes(o, (x,y) -> abs(x-y) < 2)
192+
@test eltype(changes) == eltype(changes_approx) == Int
193+
@test changes[] == changes_approx[] == 0
194+
195+
values = Int[]
196+
values_approx = Int[]
197+
on(changes) do v
198+
push!(values, v)
199+
end
200+
on(changes_approx) do v
201+
push!(values_approx, v)
202+
end
203+
204+
for i in 1:100
205+
o[] = floor(Int, i/10)
206+
end
207+
@test values == 1:10
208+
@test values_approx == 2:2:10
209+
end
210+
188211
@testset "async_latest" begin
189212
o = Observable(0)
190213
cnt = Ref(0)

0 commit comments

Comments
 (0)