[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