7

I understand what pure functions are and when someone says pure functions are composable - I believe it means that the output of one function can be passed as an input to another function but same thing goes with impure functions as well, doesn't it? Take the two functions below:

int sum(int a, int b) {
    print("sum");
    return a + b;
}

void save(int result) {
    DB.save(result);
}

void PersistSum(int a, int b) {
    save(sum(a,b));
}

Although the save and sum functions have side effects - they can still be composed as in PersistSum

I am sure am missing some core meaning of composability here. Can someone provide a precise meaning of what composability means and why functions having side effects are non-composable with an example?

  • This depends heavily on what, precisely you mean by "compose" and by "non composable", and it depends even more on what exact properties you want to be maintained by composition. – Jörg W Mittag Nov 3 '19 at 19:55
  • ok, so what exact property of composability people refer to when they say composable function? – rahulaga_dev Nov 3 '19 at 20:07
  • You cannot compose pure functions from impure functions. You can compose impure functions from pure and impure functions. It's as simple as that. – candied_orange Nov 4 '19 at 2:22
13

Function composition is indeed creating a new function that applies one function on the output of another one. More generally, composition allows to create a new function by combining several other functions.

Pure functions are functions that always provide the same output for the same input and have no side effects. So a function without any surprise, that you can call how often you may need to since only its result matters.

You can compose pure functions. You will get, by definition, a pure function.

You can also compose impure functions. It's just that it's more risky.

Take an example with h(x) = g(f(x)):

  • If f and g have two totally independent side effects, sf and sg, these side effects will happen in the following order: first sf, then sg.
  • If the side effects are not independent, then composition can have unexpected effects.

Suppose now that you have a more complex composition, using several variables and more than two functions: h(x,y) = g(f1(x,y),f2(x,y)). As already said, if all these functions are pure the result will be pure without surprise. If these functions are impure a lot of open questions arise:

  • Suppose each of these function has independent side effects sg, sf1, sf2. Here you no longer can predict the order of these side effects: it could be sf1, sf2, sg. It could as well be sf2 sf1 sg or even sf1 and sf2 exactly in the same time and then sg.
  • Suppose that these side effects are not independent, for example that sf1 adds 1 to a global variable and sf2 multiplies by 2 the same global variables, the effect of h on the global variable would be unpredictable.
| improve this answer | |
1

Expressions with pure functions can be rewritten, and then any side effects happen differently.

f x = { print(x), x }
^ (xor) is commutative an associative, x ^ 0 == x, x ^ x == 0

This can be used to filter out duplicates, by resorting the terms:

f 3 ^ f 5 ^ f 7 ^ f 5 ^ f 3 ==
(f 3 ^ f 3) ^ (f 5 ^ f 5) ^ f 7  ==
0 ^ 0 ^ f 7 ==
f 7 ==                     -- Just one print(7)
7

So side effects can happen in different orders or not at all, if they are ignored.

My point: function composition also concerns expression tree operations.

(Also mind that there is no guarantee that two calls with same arguments will give the same result. But that aspect you did not intend.)

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.