As I’ve said before, functions are my favorite building blocks. We can treat them as blackbox abstractions. We don’t have to care about what’s inside, only about what it receives as argument and what returns as output.
We can define a function called inc
that takes a number
as an input and returns a number
as output.
When a function is pure it will always return the same output if we always provide the same input. This implies something interesting: inc
will always return a number
.
It is pretty common to add constraints (or validations) to the inputs received by a function.
// divide :: (number, number) -> number
const divide = (a, b) => {
if (b === 0) {
throw new Error('Cannot divide by zero')
}
return a / b
}
Note: If you don’t know what’s up with the
divide :: (number, number) -> number
check this first.
The function divide
takes two numbers and if the value of the second argument is 0
it will throw an exception. This breaks our pure model. This function won’t return a number
every time we invoke it, even worse; sometimes it will break the flow of execution!
We must make sure our functions not only don’t throw, but they always return a value.
We could, instead of returning one type of output, we could return two. One representing the result, and other representing an error.
When I say return two value types I don’t mean both at the same time, but that the function could either return one or the other. Ptss… this is called foreshadowing.
Let’s modify our function inc
.
// inc :: number -> number | Error
const inc = (x) => {
if (typeof x !== 'number') {
return new Error('Only numbers, pls')
}
return x + 1
}
Our function inc
now returns either a number or an error and the visual representation looks something like this.
inc returns either a number or an error
Our function inc
takes a number and returns either a number or an error.
If we wanted to consume our function inc
we would do something like the following:
const result = inc(2)
// it's an error
if (result.message) {
// handle error
} else {
// use your value
}
This extra code is no different from a try/catch
block of code. So this extra code shouldn’t be an “issue” at the moment.
#functional-programming #software-development #javascript