TL;DR
const and = (...fns) => (x) => fns.every(f => f(x))
const or = (...fns) => (x) => fns.some(f => f(x))
(work it out yourself if you can't be bothered reading 🙃)
You know the functional functions compose
and pipe
?
const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);
const compose = (...fns) => (x) => fns.reduceRight((v, f) => f(v), x);
Well, I was writing some code to detect if a window was tiled to the left of the screen, i.e. aligned to the left of the screen and full height.
I already had the functions isLeftAligned
and isFullHeight
and so wrote a new function isTiledLeft
:
function isTiledLeft(window) {
return isLeftAligned(window) && isFullHeight(window)
}
But I didn't like the repetition of window
, heck what if there are more conditions to pass for the window to be considered tiled left?
In a spark of misguided insight I thought "Ah!, I can use compose"
const isTiledLeft = compose(isLeftAligned, isFullHeight)
and call it like this:
if (isTiledLeft(window)) {
// Do something
}
Job done! Neat! Clean! Functional! Legend!
NOT! The more astute of you (and probably the downright stoners) would immediately know that this is not an application of compose
!
The problem is that compose
takes the output of each function and passes it to the next. isLeftAligned
outputs true/false
and compose
then calls isFullHeight(true/false)
!!! Doh! You're a legend in the same sense that Homer is a legend.
But it was so neat! I wanted to use compose 😞.
And straight after 💥 (I'm bipolar) - the signature of compose
composed another idea in my head - i can use Array.every()
const and = (...fns) => (x) => fns.every(f => f(x))
const isTiledLeft = and(isLeftAligned, isFullHeight)
NICE!
And while I'm here I might as well do:
var isTiledRight = and(isRightAligned, isFullHeight)
and:
const or = (...fns) => (x) => fns.some(f => f(x))
And I did use compose after all, just not in code!
Top comments (0)