7.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 eachei
to a valuevi
, create a new array of lengthn+1
, and store each value in the array at its index.To evaluate
e1.(e2)
, evaluatee1
to an array valuev1
, ande2
to an integerv2
. Ifv2
is not within the bounds of the array (i.e.,0
ton-1
, wheren
is the length of the array), raiseInvalid_argument
. Otherwise, index intov1
to get the valuev
at indexv2
, and returnv
.To evaluate
e1.(e2) <- e3
, evaluate each expressionei
to a valuevi
. Check thatv2
is within bounds, as in the semantics of indexing. Mutate the element ofv1
at indexv2
to bev3
.
Static semantics.
[|e0; e1; ...; en|] : t array
ifei : t
for all theei
.e1.(e2) : t
ife1 : t array
ande2 : int
.e1.(e2) <- e3 : unit
ife1 : t array
ande2 : int
ande3 : 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.