How often do you guard against an undefined object before executing code?
1 | function getItem() { |
You have to guard because reading the property item.length
crashes if the item
is null
or undefined. Let us replace the if condition with a functor - a wrapped value and function call.
First, let us refactor the above code to cleanly separate the print function
1 | var item = getItem(); |
Second, instead of using the value directly, let us wrap it in an object that provides .then
method.
We will use this .then
method to run the print function.
1 | function Maybe(x) { |
The print is now safe
1 | Maybe('foo').then(print); |
Notice that the condition if (x !== undefined && x !== null)
is hard-coded by the Maybe
function.
We can pass this condition into the functor factory.
1 | function isDefined(x) { |
I placed the condition function first because I believe it will
change less often than the data.
You don't have to write the Conditional
functor yourself, there is an entire library of predicates
we have written to simplify condition checking: check-more-types.
One of the methods is check.then. In our case we can
use it to safely print the property
1 | var check = require('check-more-types'); |
In above example the expression check.then(isDefined, print)
is an applicative - a wrapped function to be
applied to a value. The good aspect of this design is the ease with which you can create safe versions
of functions like print
.
1 | var safePrint = check.then.bind(null, isDefined, print); |
Conclusion
The functor or applicative code is clearner and safer than always using the if
expression.
When using a functor we wrap the individual value and use the original function. When using an applicative
we wrap the function, making it safe to use with any value.
More examples of functors in Combine promises with Maybe functors.