This is a Ruby translation of a highly imperative dataflow system given in "How to implement a spreadsheet".
$ bundle install
$ rake
Ruby does not have types or module signatures (interfaces), so there is no equivalent to the OCaml explicit module signature
module type CELL = sig
type 'a cell
type 'a exp
val return : 'a -> 'a exp
val (>>=) : 'a exp -> ('a -> 'b exp) -> 'b exp
val cell : 'a exp -> 'a cell exp
val get : 'a cell -> 'a exp
val set : 'a cell -> 'a exp -> unit
val run : 'a exp -> 'a
end
OO-style is used, turning Cell
and Exp
into classes with
methods. The public API is:
Exp.create
creates an expression from an ordinary value (return
is just too confusing a name).Exp.>=
is the monadic bind operator syntax I chose (we cannot overload>>=
as in OCaml).Exp.cell_exp
creates a cell expression from an expression.Cell.exp
(corresponding toget
) creates an expression from a cell.Cell.exp=
(corresponding toset
) is Ruby syntactic sugar for setting a cell to a new expression.Exp.run
runs an expression.
A globally unique dummy Unevaluated
value is used to simulate the
OCaml option
type (nil
is a bad choice because a cell could
legitimately evaluate to nil
).
Instead of manually creating a unique ID for each cell for comparing
object identity, we just use Ruby's built-in equal?
method.
For keeping track of observers and reads, OCaml used an existential type. There is no such thing in Ruby and we just duck-type instead.