For me, immutability means clarity and understandability. Consider the following Java snippet:
SomeObjsomeObj=newSomeObj();doSomethingOnObj(someObj);doSomethingWithObj(someObj);// how does someObj look like at this point?
Looking at this piece of code alone, can you determine instinctively what is the state of someObj after all the statements have been executed?
Simply put, you can't. In languages where mutability is the default (e.g. in Java), any method that receives an object pointer (reference) are free to do anything to the referenced object. And, speaking from experience, bugs related to this behavior has bitten me more than I want.
"But that should not be a problem with properly named methods!" Oh, but names can be misleading too. Going by the name alone, doSomethingOnObj is expected to somehow change someObj in one way or another, while doSomethingWithObj is not expected to mutate. But language-wise, there's nothing stopping developers chased by deadlines to put mutating code in any of those methods. As such, you don't have any confidence on the state of someObj without digging to both methods' implementations and see where the mutations take place (which of course can be hidden in a chain of nested method calls).
In immutable-by-default languages, such as Haskell, OCaml, Elixir, etc. such things are simply not possible to happen. After creation, entities are immutable, and you can only return a copy (with modifications) of those entities. Now, suppose Java is immutable, let's look at the following code:
SomeObjsomeObj=newSomeObj();someObj=doSomethingOnObj(someObj);// someObj's reference/binding is updateddoSomethingWithObj(someObj);
After executing those statements, someObj is guaranteed to be the same as what it was on line 2. Line 3 is not possible at all to change someObj in any way. To know what the state of someObj is, you only need to look at the implementation of doSomethingOnObj (which, hopefully, is properly represented by the function name), and you can be sure doSomethingWithObj has absolutely nothing to do with it.
Readers might argue that line 2 is mutating someObj; it's not. It's called rebinding. Elixir is one language that is immutable but allows rebinding, which prevents the use of intermediate variables. Consider again the following code:
In this snippet, we are guaranteed that doSomethingOnObj will not in any way modify someObj, because the return value is assigned to a different variable. Which definitely contributes significantly on how we can understand the code at hand.
Hope it helps!
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
For me, immutability means clarity and understandability. Consider the following Java snippet:
Looking at this piece of code alone, can you determine instinctively what is the state of
someObj
after all the statements have been executed?Simply put, you can't. In languages where mutability is the default (e.g. in Java), any method that receives an object pointer (reference) are free to do anything to the referenced object. And, speaking from experience, bugs related to this behavior has bitten me more than I want.
"But that should not be a problem with properly named methods!" Oh, but names can be misleading too. Going by the name alone,
doSomethingOnObj
is expected to somehow change someObj in one way or another, whiledoSomethingWithObj
is not expected to mutate. But language-wise, there's nothing stopping developers chased by deadlines to put mutating code in any of those methods. As such, you don't have any confidence on the state ofsomeObj
without digging to both methods' implementations and see where the mutations take place (which of course can be hidden in a chain of nested method calls).In immutable-by-default languages, such as Haskell, OCaml, Elixir, etc. such things are simply not possible to happen. After creation, entities are immutable, and you can only return a copy (with modifications) of those entities. Now, suppose Java is immutable, let's look at the following code:
After executing those statements,
someObj
is guaranteed to be the same as what it was on line 2. Line 3 is not possible at all to changesomeObj
in any way. To know what the state ofsomeObj
is, you only need to look at the implementation of doSomethingOnObj (which, hopefully, is properly represented by the function name), and you can be suredoSomethingWithObj
has absolutely nothing to do with it.Readers might argue that line 2 is mutating
someObj
; it's not. It's called rebinding. Elixir is one language that is immutable but allows rebinding, which prevents the use of intermediate variables. Consider again the following code:In this snippet, we are guaranteed that
doSomethingOnObj
will not in any way modifysomeObj
, because the return value is assigned to a different variable. Which definitely contributes significantly on how we can understand the code at hand.Hope it helps!