6

I'm new to functional programming, and I don't understand the concept of immutability; e.g. an immutable variable.

For example, in Standard ML (SML):

val a = 3
val a = a + 1

The second line does not "change" the value of variable a; however, afterwards, a equals 4. Can someone please explain this?

Also, what is the benefit of "no mutation" (immutability)?

5
  • 2
    The second a is a new variable which happens to be called the same as the previous one and therefore masks it in a nested context. Compiler will rewrite this code anyway as something like let a000 = 3 in let a001 = a000+1 in ... Commented Mar 27, 2013 at 8:51
  • so it means that they refer to different memory locations? Am i able to find the first "a000" back? Commented Mar 27, 2013 at 9:38
  • 1
    You should not even think of such variables in terms of "memory locations" (and they're constants anyway, so likely will be folded). Since the name is masked, you won't be able to get the original a back, unless you quit the masking definition context, e.g. let a = 1 in let b = (let a = a+1 in a /* a is 2 */) in a /* b is forgotten, returning the original a */ Commented Mar 27, 2013 at 9:49
  • 1
    so every variable binding creates a new enviroment, and every operation will look up the currrent enviroment to get the value? Commented Mar 27, 2013 at 11:04
  • 1
    Every binding just gives a name to a value. It's better to think of a binding as a syntax sugar expanding into a lambda application, e.g. let x = a in ... is expanded into ((fun x -> ...) a), i.e., x is a function argument name here. Commented Mar 27, 2013 at 11:43

1 Answer 1

8

When we say a variable is immutable, we mean that its own value cannot be changed. What you're showing there with

val a = 3
val a = a+1

is: the new value of a is simply "shadowing" the old value of a. a is just a name that is bound to 3, and in the second line, it's bound to 4. The old value of a still exists, it's just inaccessible.

This can be seen more apparently if you're using some sort of data structures. There's no mutator methods like you see in many other languages. For example, if you have a list val L = [1,2,3], then there's no way to change the first value in L. You would have to shadow L altogether, and create a new list to shadow the old one.

So, every time you bind a new value declaration it creates a new environment with all the current name/value bindings. None of these bindings can be changed, they're simply shadowed.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.