I’m so used to functions in my daily job as software programmer that I was sure to know what it is. As often I was wrong, let me tell you why.
Function and relation
I intuitively called a function anything in my code with an input and an output. I suspected that functions without input and/or output where a special kind of functions. But in truth, f: a->b defines a relation between a and b. The Domain is the set containing a, and the Co-Domain is the set containing b. A relation maps an input from the Domain with an output in the Co-Domain. A relation can be:
Back to code
If a relation can map an element from the Domain with several elements in the Co-Domain, it is not a function. Do I code a lot of relation with different possible outputs for the same input? Yes, any function with side effects when a is an element of the Domain, can produce different output for the same input. They are not functions by the mathematical definition.
It also means that we can’t define a function without defining the Domain and the Co-Domain. If we change the Domain or the Co-Domain, a relation can be a function or not. A famous example is the SquareRoot relation because:
Sqrt : a (|R) -> b (|R) is not a function (indeed, sqrt(4) can be either 2 or – 2).
PositiveSqrt: a (|R+) -> b (|R+) is a function (a subset of squareRoot that return only the positive value)
Note as well that constraining the Domain and the Co-Domain can make the function more specific (injective, bijective, or both).
Ok my coding function are not mathematical function, why should I care? Let me ask a different question: why do mathematicians care to manipulate functions instead of relations? Because it’s easier to reason about.
In the same way, the more specific the relation is, the more predictable the code will be. If a relation can produce several outputs for the same inputs, the code is not predictable. It means that my relation depends of a more global context, and thus I can’t reason at the function scale without taking this context into account. On the other hand when my relation is a function (usually called pure function in FP, ie without side effects) my code is predictable, and I can think at a function scale without considering the global context.
It is really powerful, because It doesn’t really matter how smart you are if you have the ability to split a complex problem into simple ones.