2
votes

I've been trying to figure out how to resize an already initialized array in OCaml. However, it seems that while you can write a function that will create a brand new array with the elements of the old one copied over (and extra slots), that function's output cannot be assigned to existing array. How would one do this? Is there an easy way in which to use references to make this happen if not without?

Here's a tiny example:

let rec function_that_adds_to_array storage args ... =
   (* let's say the function has a set of if-else constructs that controls what it does, and let's further say that one of the cases leads to: *)
   let new_array = Array.make (Array.length storage) ("Null", ("Null", -2)) in
   Array.blit collection 0 new_array 0 index; (* index is controlled by the function's recursion *)
   Array.set new_array index (obj_name, obj_expr);
   new_array) (* insert the macro at tail *)
...
;;


### main method ###
let storage = Array.make 10 ((x : string), (a, b)) in
...
while true do
...
storage = function_that_adds_to_array storage args....;
...

A print statement at the end of the function_that_adds_to_array(...) confirms that a new array is returned, containing the old elements of the initial array, however, in the main method, storage remains identical. Is this because of the immutability of OCaml's elements? I thought Arrays were mutable. I've looked around, and some mention writing hacks to getting OCaml to act like Perl, however, using one individual's resize hack function proved futile. Any way I can get storage to become a new array? It needs to be an update-able collection of tuples (i.e. (string, (x, y)) )?

1
If you aren't doing this for educational purposes i'd suggest to look into batteries's dynarray - rgrinberg
I like this library, however, it does not appear to be included in the standard OCaml distribution (I put the appropriate open and include calls, but it tells me its an unbound module). Can you provide me a good link for getting and installing the most recent version of BatDynArray and its needed libraries? - 9codeMan9
Install OPAM. Then do opam install batteries. #require "batteries;;" followed by open Batteries;; - rgrinberg
Any suggestions for getting OPAM for Cygwin? I've searched and it doesn't seem as easy to get it to wrok for Cygwin as it is for a Linux-based system... - 9codeMan9

1 Answers

4
votes

In OCaml you can't assign to variables, period. There's no special limitation for arrays. However, you can have a variable that is bound to a reference, which can hold different values of the same type. This structure is what is usually called a "variable" in imperative languages. To have different sized arrays in a variable x you could write code as follows:

# let x = ref [| 0 |];;
val x : int array ref = {contents = [|0|]}
# Array.length x;;
Error: This expression has type int array ref
   but an expression was expected of type 'a array
# Array.length !x;;
- : int = 1
# x := [| 2; 3 |];;
- : unit = ()
# Array.length !x;;
- : int = 2

The ! operator dereferences a reference, and the := operator assigns a new value.

If you're new to OCaml I'll include my standard advice that you should investigate the use of immutable data before deciding to recreate the patterns of imperative languages that you already know. If you're not new to OCaml, I apologize for my impertinence!