This is a complex problem because we are seeing both a read and a set in the same function. This function, because it contains a set is not a pure function. The set is a side effect.
I would probably rewrite that block of code to look like this:
if (!map.has('key')) {
map.set('key', extremeComputation('key'))
}
return map.get('key')But I get what you are trying to say with const, so I’ll leave the logic alone and rewrite it as-is.
In functional programming, Side Effects are typically managed using Monads or Functors. I have created a basic Identity Functor so that I can map the object.
I am also using the common tap function, which can be found in Ramda, lodash/fp, Sanctuary or any other functional library. All the tap function does, is execute a function (typically a side effect), and return the original input as the output. (I’m actually writing an article that will contain a section on tap right now).
const tap = func => value => (func(value), value)So here’s a basic Identity Functor. It just holds a value and has a map function.
const identity = value => ({
value,
map: func => identity(func(value))
})Now that function can be written as a single expression:
const someFunction = map =>
map.has('key')
? map.get('key')
: identity(extremeComputation('key'))
.map(tap(generatedVal => map.set('key', generatedVal)))You might also be interested in a previous article I have written:
Cheers!
