@@ -25,7 +25,10 @@ function observe(::S) where {S<:AbstractObservable}
25
25
end
26
26
27
27
"""
28
- Like a `Ref` but updates can be watched by adding a handler using `on`.
28
+ obs = Observable(val)
29
+ obs = Observable{T}(val)
30
+
31
+ Like a `Ref`, but updates can be watched by adding a handler using [`on`](@ref) or [`map`](@ref).
29
32
"""
30
33
mutable struct Observable{T} <: AbstractObservable{T}
31
34
listeners:: Vector{Any}
@@ -162,16 +165,33 @@ end
162
165
on(f, observable::AbstractObservable; weak = false)
163
166
164
167
Adds function `f` as listener to `observable`. Whenever `observable`'s value
165
- is set via `observable[] = val` `f` is called with `val`.
168
+ is set via `observable[] = val`, `f` is called with `val`.
166
169
167
- Returns an `ObserverFunction` that wraps `f` and `observable` and allows to
170
+ Returns an [ `ObserverFunction`](@ref) that wraps `f` and `observable` and allows to
168
171
disconnect easily by calling `off(observerfunction)` instead of `off(f, observable)`.
172
+ If instead you want to compute a new `Observable` from an old one, use [`map(f, ::Observable)`](@ref).
169
173
170
174
If `weak = true` is set, the new connection will be removed as soon as the returned `ObserverFunction`
171
175
is not referenced anywhere and is garbage collected. This is useful if some parent object
172
176
makes connections to outside observables and stores the resulting `ObserverFunction` instances.
173
177
Then, once that parent object is garbage collected, the weak
174
178
observable connections are removed automatically.
179
+
180
+ # Example
181
+
182
+ ```jldoctest; setup=:(using Observables)
183
+ julia> obs = Observable(0)
184
+ Observable{$Int } with 0 listeners. Value:
185
+ 0
186
+
187
+ julia> on(obs) do val
188
+ println("current value is ", val)
189
+ end
190
+ (::Observables.ObserverFunction) (generic function with 0 methods)
191
+
192
+ julia> obs[] = 5;
193
+ current value is 5
194
+ ```
175
195
"""
176
196
function on (@nospecialize (f), observable:: AbstractObservable ; weak:: Bool = false )
177
197
push! (listeners (observable), f)
@@ -305,7 +325,7 @@ to_value(x) = isa(x, AbstractObservable) ? x[] : x # noninferrable dispatch is
305
325
"""
306
326
obsid(observable::Observable)
307
327
308
- Gets a unique id for an observable!
328
+ Gets a unique id for an observable.
309
329
"""
310
330
obsid (observable:: Observable ) = string (objectid (observable))
311
331
obsid (observable:: AbstractObservable ) = obsid (observe (observable))
@@ -327,6 +347,8 @@ Calls `f` on updates to any observable refs in `args`.
327
347
`args` may contain any number of `Observable` objects.
328
348
`f` will be passed the values contained in the refs as the respective argument.
329
349
All other objects in `args` are passed as-is.
350
+
351
+ See also: [`on`](@ref).
330
352
"""
331
353
function onany (f:: F , args... ; weak:: Bool = false ) where F
332
354
callback = OnUpdate (f, args)
@@ -366,6 +388,35 @@ Updates `observable` with the result of calling `f` with values extracted from a
366
388
All other objects in `args` are passed as-is.
367
389
368
390
By default `observable` gets updated immediately, but this can be suppressed by specifying `update=false`.
391
+
392
+ # Example
393
+
394
+ We'll create an observable that can hold an arbitrary number:
395
+
396
+ ```jldoctest map!; setup=:(using Observables)
397
+ julia> obs = Observable{Number}(3)
398
+ Observable{Number} with 0 listeners. Value:
399
+ 3
400
+ ```
401
+
402
+ Now,
403
+
404
+ ```jldoctest map!
405
+ julia> obsrt1 = map(sqrt, obs)
406
+ Observable{Float64} with 0 listeners. Value:
407
+ 1.7320508075688772
408
+ ```
409
+
410
+ creates an `Observable{Float64}`, which will fail to update if we set `obs[] = 3+4im`.
411
+ However,
412
+
413
+ ```jldoctest map!
414
+ julia> obsrt2 = map!(sqrt, Observable{Number}(), obs)
415
+ Observable{Number} with 0 listeners. Value:
416
+ 1.7320508075688772
417
+ ```
418
+
419
+ can handle any number type for which `sqrt` is defined.
369
420
"""
370
421
@inline function Base. map! (f:: F , observable:: AbstractObservable , os... ; update:: Bool = true ) where F
371
422
# note: the @inline prevents de-specialization due to the splatting
@@ -396,15 +447,28 @@ See also [`Observables.ObservablePair`](@ref).
396
447
connect! (o1:: AbstractObservable , o2:: AbstractObservable ) = map! (identity, o1, o2)
397
448
398
449
"""
399
- map(f, observable ::AbstractObservable, args...)
450
+ obs = map(f, arg1 ::AbstractObservable, args...)
400
451
401
- Creates a new observable ref which contains the result of `f` applied to
402
- values extracted from args. The second argument `observable` must be an observable ref for
403
- dispatch reasons. `args` may contain any number of `Observable` objects.
452
+ Creates a new observable ref `obs` which contains the result of `f` applied to values
453
+ extracted from `arg1` and `args` (i.e., `f(arg1[], ...)`.
454
+ `arg1` must be an observable ref for dispatch reasons. `args` may contain any number of `Observable` objects.
404
455
`f` will be passed the values contained in the refs as the respective argument.
405
456
All other objects in `args` are passed as-is.
457
+
458
+ If you don't need the value of `obs`, and just want to run `f` whenever the
459
+ arguments update, use [`on`](@ref) or [`onany`](@ref) instead.
460
+
461
+ # Example
462
+
463
+ ```jldoctest; setup=:(using Observables)
464
+ julia> obs = Observable([1,2,3]);
465
+
466
+ julia> map(length, obs)
467
+ Observable{$Int } with 0 listeners. Value:
468
+ 3
469
+ ```
406
470
"""
407
- @inline function Base. map (f:: F , observable :: AbstractObservable , os ... ; kwargs... ) where F
471
+ @inline function Base. map (f:: F , arg1 :: AbstractObservable , args ... ; kwargs... ) where F
408
472
# note: the @inline prevents de-specialization due to the splatting
409
473
if haskey (kwargs, :init )
410
474
Base. depwarn ("""
@@ -415,23 +479,9 @@ All other objects in `args` are passed as-is.
415
479
`map!(f, Observable{T}(), args...)`.
416
480
""" , :map )
417
481
dest = Observable {Any} (kwargs[:init ])
418
- return map! (f, dest, observable, os ... ; update= false )
482
+ return map! (f, dest, arg1, args ... ; update= false )
419
483
end
420
- map! (f, Observable (f (observable[], map (to_value, os)... )), observable, os... ; update= false )
421
- end
422
-
423
- """
424
- map(f, Observable{T}, args...)
425
-
426
- Creates an `Observable{T}` containing the result of calling `f` with values extracted from args.
427
- `args` may contain any number of `Observable` objects.
428
- `f` will be passed the values contained in the refs as the respective argument.
429
- All other objects in `args` are passed as-is.
430
- """
431
- @inline function Base. map (f:: F , :: Type{Observable{T}} , os... ) where {F, T}
432
- # note: the @inline prevents de-specialization due to the splatting
433
- dest = Observable {T} (f (map (to_value, os)... ))
434
- map! (f, dest, os... ; update= false )
484
+ map! (f, Observable (f (arg1[], map (to_value, args)... )), arg1, args... ; update= false )
435
485
end
436
486
437
487
"""
0 commit comments