Capucine Example: Subject-Observer PatternA possible implementation of the classic OO Subject-Observer Pattern. |
This is one possible implementation of the Subject-Observer Pattern, which is well-known amongst programmers of object-oriented languages. This example also features an implementation of chained lists. To compile it, go into the capucine directory and type:
ocamlbuild bench/sparse.gwhy
class Node (a) {R} =
unit | (a * Node (a) {R} [R])
end
val nil(): Node (a) {R} [R]
consumes R^e
produces R^c =
let n = new Node (a) {R} in
n := Left ();
n
val cons(x: a, l: Node (a) {R} [R]): unit
consumes R^g
produces R^g =
let n = new Node (a) {R} in
n := !l;
(focus l) := Right (x, n)
class Observer(Subject) = (Subject * int) end
class Subject{Rsub} =
own Rlist, Robs;
(Node(Observer(Subject{Rsub}[Rsub])[Robs]){Rlist}[Rlist] * int)
end
val notify(this: Observer(Subject{Rsub}[Rsub])[Robs], v: int): unit
consumes Robs^g
produces Robs^g =
let o = focus this in
o := (!o.1, v)
val register(
this: Subject{Rsub}[Rsub],
o: Observer(Subject{Rsub}[Rsub])[Ro]): unit
consumes Rsub^c, Ro^c
produces Rsub^c =
let o = adopt o as Rsub.Robs in
cons(o, (!this).1);
notify(o, !this.2)
val foreach_notify(
l: Node(Observer(Subject{Rsub}[Rsub])[Robs]){Rl}[Rl],
n: int): unit
consumes Rl^g
produces Rl^g
(* need pattern matching (not implemented in Capucine yet) *)
val update(this: Subject{Rsub}[Rsub], n: int): unit
consumes Rsub^c
produces Rsub^c =
this := (!this.1, n);
foreach_notify(!this.1, n)