Ink code scratch book
Observer/Observable pattern
Here is how to observe an object
# We define the `observed' aspect, that can be bound
# to mutable slots
Aspect Observed s:
@doc Observes changes made to the given slot.
@pre s as mutable Slot
directive install:
this.observers := create List
relation mutate! newValue:
this.observers : invoke s,this.s,newValue
relation e observes m, s:
@doc (Observes a slot of the given object. The slot is
designated by the given symbol in the given object )
@pre e is evaluable, m is mutable, s as Symbol
aspect := m.[s] weave Observed
aspect.observers append! e
return aspect
# We create a point (with x and y slots)
p := Point create
# We define an anonymous function that takes old value
# new one. First argument can be anything.
f := fun _,old,new: print ( old, "has changed to", new )
f observes (p, `p.x)
- We need to select on events, not on type....
Noticable idioms
Evaluation order enforcement with templated expressions
aspect := m.[s] weave Observed
allow to escape the default evaluation mechanism: m.s would be evaluated as m slot s and not, to m attribute value_of_s.
In fact @[s]@ means that the @s@ expression is evaluated before the whole expression (which means that m.[s] is a templated-expression)
Symbol quoting
It is sometimes useful to pass a symbol without evaluating it (ie. accessing its value). To do this, the ` (backquote) indicates that the following expression should not be evaluated.
f observes (p, `p.x)
Note that this can also work with coumpound expressions
x = 1 a = `( x = x + 2 , x = x * x ) x --> 1 `a --> ( x = x + 2 , x = x * x ) [unevaluated] x --> 1 a --> ( x = x + 2 , x = x * x ) x --> 9
