Array with extras
Arrays already have
reduce and some other functions. The example from the first post
can then be simplified to (Try it):
This is a clear, concise solution, without lingering variables or awkward syntax.
The problem is that Arrays are hard to extend with new functions. And this is a serious shortcoming, as having some functions does not mean that you’ll never need anything else.
What if you need
head, that returns the first element?
Extending the prototype
A simple solution is to add the function to the Array prototype, amending all Arrays at once (Try it):
But this is a polluting operation. When this code runs, it has far-reaching effects, modifying all Arrays.
It can be a problem in multiple ways. What if different people want to define the function in different ways? Even in this
simple example, should
head throw an Error or return
undefined for an empty Array? Also, were libraries to follow
this practice, that would create a mess on a whole new level.
Moreover, if the function is defined just before usage, it is a side-effect. If it is defined globally, that adds to the surprises people not familiar with the codebase experience. These surprises are what makes onboarding progressively harder.
Consider the following scenario (Try it):
If you decide to get rid of the
function1 call, code that comes after it that also relies on the first version will break.
A possible approach is to undo the pollution after the function is called (Try it):
This might work in some situations but is flawed in several ways.
First, it is ugly. Wrapping everything in a
try...finally just to avoid side effects is a clear sign that we’re doing
something wrong here.
But also, it has more localized problems. What if there is a function call that uses
head? In that case, depending on the
caller, the function may use different versions (Try it):
When all you need to use is present in the Array prototype, use that. It provides the cleanest collection processing you can ever have. But this approach falls short when something is missing.
The lazy solution is to cut corners and augment the prototype, but this approach comes with long-term costs hardly justified by the benefits.
But don’t worry, there are other solutions to this problem. We’ll look into them in the next posts.