The feature of call-by-reference in ATS is similar to the corresponding one in C++. What is special in ATS is the way in which this feature is handled by the type system. In general, if f is given a type of the following form for some viewtypes VT1 and VT2:
(..., &VT1 >> VT2, ...) -> ...then a function call f(..., x, ...) on some variable x of the viewtype VT1 is to change the viewtype of x into VT2 upon its return. In the case where VT1 and VT2 are the same, &VT1 >> VT2 can simply be written as &VT1. Note that the variable x may be replaced with other forms of left-values.
As an example, an implementation of the factorial function is given as follows that makes use of call-by-reference:
fun fact (x: int): int = let fun loop {l:addr} (x: int, res: &int): void = if x > 0 then (res := res * x; loop (x-1, res)) else () var res: int = 1 in loop (x, res); res end // end of [fact]Note that if the line for introducing the variable res in the implementation is replaced with the following one:
val res: int = 1 // [res] is now a value, not a variable!then a type error should occur as res is no longer a left-value when it is passed as an argument to loop.
The code used for illustration is available here.