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
endOO-style is used, turning Cell and Exp into classes with
methods. The public API is:
Exp.createcreates an expression from an ordinary value (returnis just too confusing a name).Exp.>=is the monadic bind operator syntax I chose (we cannot overload>>=as in OCaml).Exp.cell_expcreates 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.runruns 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.