The Or, And, Ors, and Ands
Why people kept sticking with deeply nested if-else statements while there’s better alternative from functional paradigm? I’ve been ranting alot about this through all previous articles. And I must admit that this one wasn’t the first time I tried dissing the if statements. I love reinventing things even though the old ones in my projects works just fine so far.
We all knew that there’re short circuits such as the double slits || to represent ‘or’ logic while the double and && represents ‘and’ logic. I’ve employed both of them extensively throughout my projects codebases. I got no beef with them as they’re natively present in any JS engines and readily to use any time. But the longer I gaze upon it, the more I ask myself “is it already satisfactory?”
We love functions, we use it to do just about anything in functional paradigm. To generate array, modify them, reduce them, or anything. I’m just few functions away from doing my weekly laundry by JS functions. Neglecting the itch to reinvent the ‘or’ and ‘and’ logic can only be postponed so long. Just like what CJ said, “Oh sh*t, here we go again”.
// old ors and ands
ors = arr => arr.find(Boolean)
ands = arr => arr.reduce((a, b) => a && b, true)
Have a look at the snippet above. Those two functions has been the backbone of my projects of the past few years. They’re short, concise, elegant, aesthetically pleasing, yet I still have an overengineering itch to fiddle with them. Few latent reasons is that, 1) they don’t cultivate the good old recursion, 2) it depends on JS native array methods, 3) the invocation requires treating your arguments as values of an array. But before I serve you the main dish, first let me entice your appetite — or lack thereof — by showing how I use both || and && below:
expression1 =
someStupidValue ||
anotherSillyValue
expression2 =
someStupidValue &&
anotherSillyValue &&
lastGivenValue
Look at that sudden indentations, golly! Can’t I just have something tidy with the help of parenthesis? That’s why I repack the short circuit expressions into a set of concise functions:
const
or = (a, b) => a || b,
and = (a, b) => a && b
expression1 = or(
someStupidValue,
anotherSillyValue
) // aaahh
expression2 = and(
someStupidValue,
anotherSillyValue,
lastGivenValue
) // what a delight
“Balanced, as all things should be” said Thanos. Other than enclosing the expression in tidy parenthesis, we got rid of those pesky symbols born from the early days of JS. Now all ‘or’ and ‘and’ logic can be carried out by these brand new functions. Now, how do we suppose to make them work for inputs more than two, like 3 to arbitrarily given expressions? The answer is recursion! Have a look at this:
const
or = (a, b) => a || b,
and = (a, b) => a && b,
ors = (a, ...b) => b.length === 1
? or(a, ...b) : or(a, ors(...b)),
ands = (a, ...b) => b.length === 1
? and(a, ...b) : and(a, ands(...b))
or(0, 4) // get 4
or(2, 3) // get 2
and(1, 0) // get false
and(4, 7) // get 7
ors(0, 2, 5) // get 2
ors(3, 1, 0) // get 3
ands(2, 1, 4) // get 4
ands(3, 0, 5) // get false
// deep chaining
ands(
2, 3,
ors(
6, 0, 4
)
) // get 6
Got curious how the recursion works? Follow me:
const // declare a constant
ors = (a, ...b) => // it shall accept arbitrary number of arguments
b.length === 1 // let's check, if the b is only 1 arguments
? or(a, ...b) // if yes, then it shall 'or' the a and that remaining 1 b
: or(a, ors(...b)) // if b > 1 arguments, recursively iterate the remaining b's
The same logic could also be applied to the ‘ands’ function, that’s why they look exactly similar. Soo,, what do we do now? Maybe I’ll use these new form of short circuit functions in my future projects. Hopefully these shall useful for you too. Thanks for the read.