From Textbook: Mutability
Refs
Syntax
1 | ref x |
ref x
: creates a reference using theref
keyword (let x = ref 0
creates a location in memory whose contents are initialized to0
)!x
: dereferencesx
and returns the contents of the memory locationx := e
: is an assignment. It mutates the contentsx
to be1
. Note thatx
itself still points to the same location (i.e., address) in memory. Variables really are immutable in that way. What changes is the contents of that memory location. Memory is mutable; variable bindings are not.
Counter
1 | let next_val = |
Look at how these two functions’ results differ. In the first example, counter
is just a temporary variable later bound to the fun() -> ...
Therefore, counter
will not be initiated every time we call next_val
. It is evaluated only when the first time it is defined.
Sequencing
1 | e1; e2; ... ; en |
The sentence above evaluates each one of ei
in order from left to right, returning only vn
.
If the values
vi
previous expressionei
evaluates to are not of type unit, the compiler will give you a warning because it makes no sense to throw away those values. To get rid of the warning (if you’re sure that’s what you need to do), there’s a functionignore : 'a -> unit
in the standard library. Using it,ignore(2+3); 7
will compile without a warning. Of course, you could code upignore
yourself:let ignore _ = ()
.
This is a syntactic sugar of let _ = e1 in e2
Equality
- Physical Equality (
==,!=
): same address - Structural Equality (
=,<>
): same content
Mutable Fields (in Record)
Syntax
1 | (* declare a record with mutable field *) |
Mutable Stack
Arrays and Loops
Arrays
- Array creation:
[|e0; e1; ...; en|]
- Array indexing:
e1.(e2)
- Array assignment:
e1.(e2) <- e3
Loops
1 | while e1 do e2 done |
while
loops terminate whene1
becomes falsefor
loops execute once for each integer frome1
toe2
for..to
loops evaluate starting ate1
and incrementingx
each iteration;for..downto
loops evaluate starting ate1
and decrementingx
each iteration