I am trying to refactor some JavaScript code to use functional programming principles.
I have some functions that I want to use in a series of maps.
const transformedData = rawData
.map(getIdFromRawData)
.map(getCachedDataById)
.map(transformData)
getIdFromRawData
takes in rawData
:
{
id: 123,
name: "taco",
is_tasty: true
}
And returns 123
.
getCachedDataById
takes in an id like 123
and returns cachedData
(it’s an impure function that gets the data with an I/O operation):
{
transformedValue1: "cheese",
transformedValue2: "taco mix",
transformedValue3: "salsa",
...
}
The final function in the pipeline, transformData
, needs to take in both cachedData
and rawData
:
function transformData({ cachedData, rawData }) {
if (Object.keys(cachedData).length) {
// use cachedData to skip some work while transforming
} else {
// use rawData for transformation
}
}
But I didn’t pass along rawData
in the return value of getIdFromRawData
. I didn’t do that for the following reasons:
getIdFromRawData
is used elsewhere and needs to have a generic signature.- easier to test
getIdFromRawData
- function name
getIdFromRawData
does what it says on the tin
I want to have some kind of “pass through” functionality with my pipeline. In researching how best to handle this, I’ve seen mention of using a reader monad, but I’m not sure how to implement it for this use case, or if it’s even the right approach.
Something like this initially comes to mind:
function passThrough({ data, func, key }) {
const result = func(data[key])
return { ...data, ...result }
}
...
const transformedData = rawData
.map((data) => passThrough({ data, func: getIdFromRawData, key: 'id' }))
.map(getCachedDataById)
.map(transformData)
This doesn’t quite do what I want, though, because now getCachedDataById
is receiving an argument shaped like an object ({ ... }
) and not a number (123
).
rawData
needs to be present and accessible throughout the pipeline, but it only is relevant at certain parts of the pipeline.
Is there a certain kind of monad that applies to this?
Are monads not really relevant here?
Is there another approach for this?
rpivovar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.