4

In computer programming (I code in c#), why are pure functions easier to reason about?

From my own experience, I find that pure functions are easier to reason about because they lack side effects, and they lack state management. As a consequence, such code is more simple and straight forward. Beyond this, can anyone share with me additional reasons why such functions are easier on the brain?

  • 2
    I personally couldn't say for certain. I suspect it's because deterministic algorithms flow very distinctly from input to output. Your mind can easily follow a specific point to it's result. You might take a look at functional programming which abandons the concept of changing state and mutable variables to offer more understandable code. In many ways it's an almost exclusively deterministic paradigm. However many of it's conventions can appear rather befuzzling to the first time viewer. And looking at it's code from an imperative background often makes it appear more unreadable. – Ucenna Oct 12 '16 at 16:54
  • 5
    Why are you conflating determinism with purity, lack of side effects or state management? – Andres F. Oct 12 '16 at 18:03
  • @AndresF. Wikipedia's defintion of 'pure function' tells me that 'purity' is a form of determinism - so, no conflation there. – Rock Anthony Johnson Oct 12 '16 at 18:35
  • 2
    @RockAnthonyJohnson The problem is that the implication doesn't go both ways: determinism doesn't imply purity (or lack of state management, or lack of side effects). You have to decide: is your question about purity or about determinism? If it is about purity, you should change your title. – Andres F. Oct 12 '16 at 19:05
  • @AndresF. Thanks, Andres - you've corrected errors in my thinking. I've updated my question appropriately. You are absolutely right, because all pure functions are deterministic, but not all deterministic functions are pure. – Rock Anthony Johnson Oct 12 '16 at 19:34
11

Consider a typical imperative design, with mutating variables and numerous references to equally mutating external resources. When something goes wrong with such code, the normal thing to do is to reach for the debugger. The reason for this is simple: this sort of code requires you to mentally step through each stage, whilst trying to remember the current status of all that mutating state. That's hard to do in your head, which is why we rely on the likes of the debugger, print statements and the like.

If this is replaced with functions that behave in a deterministic way, with immutable variables and no external side-effects, then the need to hold a complex state-machine goes away. As you say, it becomes possible to reason what the code does, rather than trying to execute it in your head to work it out.

This is why "functional programming", with its emphasis on immutability, pure, deterministic functions and the like is growing in popularity. The resultant code from this technique is simpler to understand and thus less prone to bugs.

And one doesn't need to use a "functional language" to write deterministic code. I recently wrote an article, "Why declarative programming is often better than imperative, even in C#" that shows how its possible to write declarative, deterministic code in what's seen traditionally as an OO language.

  • 1
    I can surely relate to the difficulties of using a mental debugger to manage changes in state!! Nice article that you've written. – Rock Anthony Johnson Oct 12 '16 at 18:45
  • 1
    David, I've updated my question to ask specifically about pure functions rather than deterministic algorithms. However, this does not change the appropriateness of your answer. Thank you. – Rock Anthony Johnson Oct 12 '16 at 19:37
  • 4
    +1 It's not just that the determinism is easy to reason about, it's also that the dependencies are explicit. A sequence of imperative statements that mutate state behind the scene all look the same. Pure functions take new values as function arguments and return new values, so who depends on what and who's computing new values becomes clear. You can also rearrange, delay, duplicate or skip the execution of pure functions without fear of breaking other pure functions. – Doval Oct 12 '16 at 19:53

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.