Sequencing of Effects
The semicolon operator is used to sequence effects, such as mutating refs. We've seen semicolon occur previously with printing. Now that we're studying mutability, it's time to treat it formally.
Syntax:
e1; e2
Dynamic semantics: To evaluate
e1; e2
,First evaluate
e1
to a valuev1
.Then evaluate
e2
to a valuev2
.Return
v2
. (v1
is not used at all.)If there are multiple expressions in a sequence, e.g.,
e1; e2; ...; en
, then evaluate each one in order from left to right, returning onlyvn
. Another way to think about this is that semicolon is right associative—for examplee1; e2; e3
is the same ase1; (e2; e3))
.
Static semantics:
e1; e2 : t
ife1 : unit
ande2 : t
. Similarly,e1; e2; ...; en : t
ife1 : unit
,e2 : unit
, ... (i.e., all expressions excepten
have typeunit
), anden : t
.
The typing rule for semicolon is designed to prevent programmer mistakes. For
example, a programmer who writes 2+3; 7
probably didn't mean to: there's
no reason to evaluate 2+3
then throw away the result and instead return 7
.
The compiler will give you a warning if you violate this particular typing rule.
To get rid of the warning (if you're sure that's what you need to do),
there's a function ignore : 'a -> unit
in the standard library.
Using it, ignore(2+3); 7
will compile without a warning. Of course,
you could code up ignore
yourself: let ignore _ = ()
.