Joel Thoms
Sep 6, 2018 · 1 min read

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!

    Joel Thoms

    Written by

    Computer Scientist and Technology Evangelist with 20+ years of experience with JavaScript!

    Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
    Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
    Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade