More idiomatic reducers
[This brief article is an extraction from the Act docs]
Many people are put off for the usage of switch in reducers:
Although this is an aesthetic judgement and there’s nothing intrinsically wrong with it, there are more idiomatic ways.
First of all a switch statement is the poor cousins of pattern matching and
guards:
This would be the equivalent of our previous example in Haskell. Of course, we can improve this by using Haskell’s features, specially, I would say, proper types instead of strings for the action types (now you probably have a better clue why it is called “type” in JS :D), but the good news it that there is an interesting function in Ramda to get us a little closer to that, namely, cond (I suppose it’s inspired by ClojureScript’s cond).
Here’s the gist of cond:
So if the value passed to the function is zero, it runs the first function
and so on, until getting to final condition T, which is basically the true function, i.e a function that always returns true (like in () => true), so
it always matches any unmatched value, working pretty much as Haskell’s
otherwise or JS’s default or cljs’s :else, or …
So one more idiomatic — in the functional context — way of building a reducer, would be to resort to this helper:
Although this is more composable than a switch, since you can add items to the list dynamically, and more idiomatic functionally speaking, it seems still too verbose and not really idiomatic in a JavaScript context (which I guess it’s a hard to define… probably idiomatic JavaScript is either jQuery or
injecting logic as tag’s attributes :D).
So by looking at cond and the specific use of it in reducers, it seems the most common use case is to use equals in the condition (except for T), and
always a function with the reducer arguments as the 2nd parameter. Therefore, it is natural to assume we could implement something on top of that to end up with a configuration like this:
We could also remove the action being passed to the function (something that cond would always do) by wrapping it, and have the T condition as a default.
It is a little syntactic sugar over Ramda’s cond. Here’s the full example:
Much more concise.
You will find something very similar in the Redux world in redux-actions’s
handleActions.
But still, if we look into Ramda’s utilities we will find functions with exactly the same signatures we need here, namely Number → Number
→ Number (gets two numbers, returns a number). As examples,
add, subtract, multiply and divide.
Therefore, we can do:
And finally, this is the same as:
As a final note, you may be wondering what are the advantages of implementing this on top of , instead of a more “traditional” (in the JS world) way, like other libraries do. One example is, if you may need
more tricky conditions, you can still achieve that, using arrays instead of an object:
And as you can see, using Ramda’s lens make it all so much nicer.
If you got interested here’s an implementation and some usage examples.