2222 dynamic bool
2323 dynamicBound atomic.Bool
2424
25+ watches IPersistentMap
26+
2527 syncLock sync.Mutex
2628 }
2729
@@ -93,8 +95,9 @@ func InternVarName(nsSym, nameSym *Symbol) *Var {
9395
9496func NewVar (ns * Namespace , sym * Symbol ) * Var {
9597 v := & Var {
96- ns : ns ,
97- sym : sym ,
98+ ns : ns ,
99+ sym : sym ,
100+ watches : emptyMap ,
98101 }
99102 v .root .Store (Box {val : & UnboundVar {v : v }})
100103 v .meta .Store (NewBox (emptyMap ))
@@ -127,7 +130,8 @@ func (v *Var) HasRoot() bool {
127130
128131func (v * Var ) BindRoot (root interface {}) {
129132 // TODO: handle metadata correctly
130- v .root .Store (Box {val : root })
133+ old := v .root .Swap (Box {val : root })
134+ v .notifyWatches (old .(Box ).val , root )
131135}
132136
133137func (v * Var ) IsBound () bool {
@@ -151,7 +155,9 @@ func (v *Var) Set(val interface{}) interface{} {
151155 if b == nil {
152156 panic (fmt .Sprintf ("can't change/establish root binding of: %s" , v ))
153157 }
158+ old := b .val
154159 b .val = val
160+ v .notifyWatches (old , val )
155161 return val
156162}
157163
@@ -230,9 +236,9 @@ func (v *Var) AlterRoot(alter IFn, args ISeq) interface{} {
230236 v .syncLock .Lock ()
231237 defer v .syncLock .Unlock ()
232238
233- newRoot := alter . ApplyTo ( NewCons ( v .Get (), args ) )
234- // TODO: validate, ++rev, notifyWatches
235- // oldRoot := v.Get()
239+ oldRoot := v .Get ()
240+ newRoot := alter . ApplyTo ( NewCons ( oldRoot , args ))
241+ // TODO: validate, ++rev
236242 v .Set (newRoot )
237243 return newRoot
238244}
@@ -246,15 +252,31 @@ func (v *Var) Validator() IFn {
246252}
247253
248254func (v * Var ) Watches () IPersistentMap {
249- panic ( "not implemented" )
255+ return v . watches
250256}
251257
252258func (v * Var ) AddWatch (key interface {}, fn IFn ) IRef {
253- panic ("not implemented" )
259+ v .watches = v .watches .Assoc (key , fn ).(IPersistentMap )
260+ return v
254261}
255262
256263func (v * Var ) RemoveWatch (key interface {}) {
257- panic ("not implemented" )
264+ v .watches = v .watches .Without (key )
265+ }
266+
267+ func (v * Var ) notifyWatches (oldVal , newVal interface {}) {
268+ watches := v .watches
269+ if watches == nil || watches .Count () == 0 {
270+ return
271+ }
272+
273+ for seq := watches .Seq (); seq != nil ; seq = seq .Next () {
274+ entry := seq .First ().(IMapEntry )
275+ key := entry .Key ()
276+ fn := entry .Val ().(IFn )
277+ // Call watch function with key, ref, old-state, new-state
278+ fn .Invoke (key , v , oldVal , newVal )
279+ }
258280}
259281
260282func (v * Var ) Hash () uint32 {
0 commit comments