Using vs Enforcing Immutability
In The Case for var and let, we showed Array destructuring as a way to support immutability instead of relaying on
const to ensure you cannot modify an Array. There is a subtle, but important, attitude there not be missed. We want to encourage a normal way of returning immutable data instead of enforcing immutable data.
Enforcing immutable data would be using things like
Object.freeze, the Immutable.js library, or heavy handed clone methods such as:
const clone = object => JSON.parse(JSON.stringify(object))
This is not what Functional Programming is about. It's about using and composing pure functions, not ensuring someone cannot mutate data. If you use pure functions and compose them, you end up not mutating data, and thus there is no reason to enforce it.
... however, in the real world, you will be working with non-FP programmers, writing non-FP code, using non-FP libraries. Sometimes knowing how to suss out the mutation, prevent it, or benefit from performance techniques are helpful to support immutability.
For atomics like
Number, they are copied by value, and are easy to clone; by making a new variable/constant or function return value, they give you a new clone.
Frameworks like Redux ensure there is only 1 variable in your application. You never mutate the data yourself, instead asking the
store to hide the access, and provide functions that allow the data to be changed internally using pure functions.
If you're dealing with a legacy system, or with code not written in using pure functions, using
Object.freeze can help probe where the mutation is ocurring in a heavy handed way by triggering an exception wherever the mutation exists. Functional Programming is about returning values, not causing side effects, and throwing errors is just that: intentional side effects.
However, it can be a powerful tool to help find the impurity, fix it, and move forward.
First, ensure your code is in strict mode, typically writing
"use strict" at the top of the file(s). Second, wrap your data in
Anytime code attempts to modify it, it'll throw a
TypeError, and you should be able to glean where the offending non-FP code is from the stack trace.
The bad news is, if you leave this code in your program, you're intentionally leaving a side effect (code that can throw an error) in your coe. Once you've found the offending mutation, you should remove it if you wish to be pure.
The good news is, if you don't, as long as you don't have any mutation, it'll work just fine with Object destructuring.
The Immutable.js library allows you to use common data types, but in an immutable way. For exampe,
Array are immutable. Immutable gives you all these data types with methods that are pure, and the data is immutable. They've also added many performance enhancements beyond just memoize (caching) that you may benefit from.