6.3. Arrays and Loops#
Arrays are fixed-length mutable sequences with constant-time access and update. So they are similar in various ways to refs, lists, and tuples. Like refs, they are mutable. Like lists, they are (finite) sequences. Like tuples, their length is fixed in advance and cannot be resized.
The syntax for arrays is similar to lists:
let v = [|0.; 1.|]
val v : float array = [|0.; 1.|]
That code creates an array whose length is fixed to be 2 and whose contents are
initialized to 0. and 1.. The keyword array is a type constructor, much
like list.
Later those contents can be changed using the <- operator:
v.(0) <- 5.
- : unit = ()
v
- : float array = [|5.; 1.|]
As you can see in that example, indexing into an array uses the syntax
array.(index), where the parentheses are mandatory.
The Array module has many useful functions on arrays.
Syntax.
Array creation:
[|e0; e1; ...; en|]Array indexing:
e1.(e2)Array assignment:
e1.(e2) <- e3
Dynamic semantics.
To evaluate
[|e0; e1; ...; en|], evaluate eacheito a valuevi, create a new array of lengthn+1, and store each value in the array at its index.To evaluate
e1.(e2), evaluatee1to an array valuev1, ande2to an integerv2. Ifv2is not within the bounds of the array (i.e.,0ton-1, wherenis the length of the array), raiseInvalid_argument. Otherwise, index intov1to get the valuevat indexv2, and returnv.To evaluate
e1.(e2) <- e3, evaluate each expressioneito a valuevi. Check thatv2is within bounds, as in the semantics of indexing. Mutate the element ofv1at indexv2to bev3.
Static semantics.
[|e0; e1; ...; en|] : t arrayifei : tfor all theei.e1.(e2) : tife1 : t arrayande2 : int.e1.(e2) <- e3 : unitife1 : t arrayande2 : intande3 : t.
Loops.
OCaml has while loops and for loops. Their syntax is as follows:
while e1 do e2 done
for x=e1 to e2 do e3 done
for x=e1 downto e2 do e3 done
Each of these three expressions evaluates the expression between do and done
for each iteration of the loop; while loops terminate when e1 becomes false;
for loops execute once for each integer from e1 to e2; for..to loops
evaluate starting at e1 and incrementing x each iteration; for..downto
loops evaluate starting at e1 and decrementing x each iteration. All three
expressions evaluate to () after the termination of the loop. Because they
always evaluate to (), they are less general than folds, maps, or recursive
functions.
Loops are themselves not inherently mutable, but they are most often used in
conjunction with mutable features like arrays—typically, the body of the
loop causes side effects. We can also use functions like Array.iter,
Array.map, and Array.fold_left instead of loops.