Observables.jlまったくわからん.jl

juliaのパッケージObservables.jl
について理解するためのメモ。
プロットパッケージのMakie.jl
について理解するのに、Observables.jl
も知っておいた方が良さそうだな、ということで勉強する。

公式ドキュメントによると、ObservablesはRef
に似ているものらしい。正直juliaのRef
をあまりよく理解していないので、まずはRef
について確認する。

ヘルプを読んだ感じ、Ref
はポインタを表現する型らしい。ただし、ヌルポにならないことが保障されているのかな?Ptr
より少し安全装置があるような記述をしている。
Ref(x)
でx
への参照ができる。[]
で参照先の値にアクセスできる。

Observable
がRef
と似ているのは、それ自体はRef
のように値への参照なのだろう。[]
で参照先の値を得られるのも同じ。ただ、Ref
と違って、Observable
は参照先の値の変更をlistenしている。
つまり、参照先の値が変更されるたびに関数を実行できるっぽい。

on(f, o::Observable)
で、関数f
をo
の参照先が変更されるたびに実行されるように登録することができるみたい。
off(o::Observable, f)
で、on
によって登録された関数f
を外すことができる。
on(o::Observable) do ... end
の書き方をすることが多そう?

やってみた
using Pkg
p = mktempdir()
Pkg.activate(p)
Pkg.add("Observables")
using Observables
x = 3
o = Observable(x)
on(o) do x
println("x is updated!: ", x)
end
o
の参照先であるx
の値を直接書き換えても意味はなさそう
julia> x = 4
4
o[]
に値を入れると関数が実行される。
julia> o[] = 5;
x is updated!: 5
ちなみにこのときx
は変更されないっぽい
julia> x === o[]
false
julia> @show x
x = 4

Reactive.jl
と似ているらしいけれど、Observables.jl
は同期的で、Reactive.jl
は非同期的らしい?
ひとまずは今はこの辺の話は無視。

他のAPI
onany(f, args...)
args
は全部Observable
で、args
のどれか一つが更新されるたびにf
を実行するように登録する
map!(f, o::Observable, args...)
args
は全部Observable
で、args
のどれか一つが更新されるたびに、f(args)
の実行結果でo
を更新する。
ソースはこんな感じ
function map!(f, o::Observable, os...)
onany(os...) do val...
o[] = f(val...)
end
return o
end
connect!(o1::Observable, o2::Observable)
o1
が更新されるたびに、o2
をo1
と同じ値で更新する。
ソースはこんな感じ
connect!(o1::Observable, o2::Observable) = map!(identity, o2, o1)