The let
keyword creates a name binding, which means "this name means this value" (or this function). It is immutable: in the code you wrote, the name z
in the split
function will always refer to the value abs(x / 10)
, and cannot be changed. The let z = z + 1
expression in your if modz > 5 = ...
block is not reassigning the value of the outer z
. Instead, it's creating a new definition of z
, local to the block that it's in. What the code you've written is saying is "within the true part of this if
expression, I want a name called z
whose value is the value of z
that I currently know about, plus 1. Oh, and hide the "outer" z
from me: inside this block, I want to use my definition of z
." But outside the block, the "outer" z
is unchanged. This allows you to redefine names at will, without accidentally causing bugs in other code, and it's usually a good thing.
What you're trying to do is create a mutable variable, and that's done by adding the mutable
keyword to let
. The syntax for assigning a new value to a mutable variable is also different: it doesn't use let
at all. What you wanted is to write:
let mutable z = abs(x / 10)
// Later on...
z <- z + 1
The left-facing arrow operator <-
means "change the value of this mutable variable". If you write z = z + 1
, which is a common newbie mistake, the compiler will give you a warning that this is a Boolean value that is ignored -- because when it's not part of a let
binding, the =
operator is comparison. The expression z = z + 1
is asking "is z
equal to z + 1
?" And that will always be false (unless you've created a really weird numeric type).
I don't really recommend using mutable
as a general rule. Try re-writing your logic to avoid it. For example, you could write your function like so:
let split x =
let z = abs(x / 10)
let modz = abs(x % 10)
let increment = if modz > 5 then 1 else 0
let y = if modz > 5 then abs(5 - modz) else modz
(y, z + increment)
That would be more functional, and avoid the use of mutable
.