[MLton] MLton.Vector.create
Stephen Weeks
MLton@mlton.org
Tue, 28 Mar 2006 13:36:18 -0800
> You can't quite always do what you want before calling the create
> without using a ref cell and perhaps an extra option. If I need to
> use some function closed over sub or update, and that is what the
> tabulator is going to use, then I would have to use a ref cell
> carrying an option type and fill it in the first time that the
> tabulator was called.
Good point.
> Funny, I think that you convinced me that the currying in the
> tabulator should stay. The computation being staged could be
> useful, and also implies that the sub and update functions don't
> vary between different invocations of the tabulator.
Well, they sort-of don't vary. There is a ref cell for the limit
under the hood that does get mutated, and this affects the meaning of
sub and update.
> Ah yes, I was just thinking of the second version, where you pass
> sub/update once and get back a tuple of the tabulator and a whacker.
> I definitely like this one much more. It makes it clear that there
> is only one sub/update, it being the same for all invocations of the
> tabulator and the whacker. It lets you stage things in a perhaps
> useful way (building closures and data structures once that are used
> both by the tabulator and the whacker).
All true. I now agree that this version seems best. Here's the
signature and implementation that I have committed.
val create:
int * ({sub: int -> 'a, update: int * 'a -> unit}
-> (int -> 'a) * (unit -> unit))
-> 'a vector
fun create (n, f) =
let
val a = Primitive.Array.array n
val subLim = ref 0
fun sub i =
if Primitive.safe andalso Primitive.Int.geu (i, !subLim) then
raise Subscript
else
Primitive.Array.sub (a, i)
val updateLim = ref 0
fun update (i, x) =
if Primitive.safe andalso Primitive.Int.geu (i, !updateLim) then
raise Subscript
else
Primitive.Array.update (a, i, x)
val (tab, finish) = f {sub = sub, update = update}
val () =
Util.naturalForeach
(n, fn i =>
(Primitive.Array.update (a, i, tab i);
subLim := i + 1;
updateLim := i + 1))
val () = finish ()
val () = updateLim := 0
in
fromArray a
end