References


A reference is essentially a persistent array of size 1. Given a viewtype VT, the type for references to values of viewtype VT is ref(VT). The type constructor ref is abstract in ATS, though it can be defined as follows:

typedef ref (a: viewt@ype) = [l:addr] (vbox (a@l) | ptr l)
The interfaces for various functions on references can be found in the file prelude/SATS/reference.sats.

Reference Creation   There is a function template ref_make_elt of the following type:

fun{a:viewt@ype} ref_make_elt : a -<> ref a
Given a value v of some viewtype VT, ref_make_elt<VT> (v) creates a reference of type ref(VT). For instance, the following code creates some references:
val r_int = ref_make_elt<int> (0)
val r_double = ref_make_elt<double> (0.0)
val r_fun = ref_make_elt<int->int> (lam x => x+1)
There is also a function ref_make_view_ptr of the following type for turning pointers into references:
fun ref_make_view_ptr : {a:viewt@ype} {l:addr} (vbox(a @ l) | ptr l) -> ref a
Note that ref_make_view_ptr is a polymorphic function; it is not a function template.

Reference Read and Write   Given a reference r, the syntax for reading from r is !r and the syntax for writing (a value v) to r is !r := v. Note that in both SML and Objective Caml, the syntax for writing (a value v) to a reference r is r := v (instead of !r := v).

There are also two function templates ref_get_elt and ref_set_elt of the following types:

fun{a:t@type} ref_get_elt : ref a -<!ref> a
fun{a:t@type} ref_set_elt : (ref a, a) -<!ref> void
which can used to read from and write to a given reference, respectively. As an example, we give a simple implementation of counters as follows:
// [int64] is the type for 64-bit integers in ATS
typedef counter = '{ // the type for counter objects
  get= () -<cloref1> int64 // get the value of the counter
, set= int64 -<cloref1> void // set the value of the counter
, inc= () -<cloref1> void // increase the value of the counter
, dec= () -<cloref1> void // decrease the value of the counter
}

fn counter_make (): counter = let
  // [int64_of_int] coerce an integer into a 64-bit integer
  val r = ref_make_elt<int64> (int64_of_int 0)
in '{ // record creation
  get= lam () => !r // read from [r]
, set= lam (x) => !r := x // write to [r]
, inc= lam () => !r := succ !r
, dec= lam () => !r := pred !r
} end // end of [counter_make]


The code used for illustration is available here.