[MLton] MLton.Vector.create
Stephen Weeks
MLton@mlton.org
Tue, 28 Mar 2006 10:47:41 -0800
> I would make it so that calling sub after create returns also raises
> Fail.
I think that is unnecessarily limiting. Suppose one wants to create a
vector of promises, where some promises refer to other ones in the
same vector. Those will need to use the supplied "sub" after the
vector has been returned.
> Also, I wonder if it is worth while having something just like
> create that takes a tabulate function instead of a single element
> for the initial value of the array/vector.
That seems like a better interface. In fact, I don't see any reason
not to give the tabulate function access to "sub" and "update" on
earlier elements in the vector. How about the following interface?
val create:
int * ({sub: int -> 'a, update: int * 'a -> unit} -> int -> 'a)
-> 'a vector
Here's a proposed implementation. I eliminated the "frozen" stuff and
simply have sub and update return "Subscript" if the index is invalid.
fun create (n, f) =
let
val a = Primitive.Array.array n
val subMax = ref 0
fun sub i =
if Primitive.safe andalso Primitive.Int.geu (i, !subMax) then
raise Subscript
else
Primitive.Array.sub (a, i)
val updateMax = ref 0
fun update (i, x) =
if Primitive.safe andalso Primitive.Int.geu (i, !updateMax) then
raise Subscript
else
Primitive.Array.update (a, i, x)
val f = f {sub = sub, update = update}
val () =
Util.naturalForeach
(n, fn i =>
(subMax := i;
updateMax := i;
Primitive.Array.update (a, i, f i)))
val () = subMax := n
val () = updateMax := 0
in
fromArray a
end