jargon

Design patterns·topic 9 of 10

Functional ideas that went mainstream

Most of these arrived in ordinary object-oriented codebases without the theory attached, and they are now said in reviews by people who have never written a line of Haskell. This is what they mean when they are.

Read in order · tick what you already know

  1. 01

    you called it twice with the same arguments, got the same answer, and nothing anywhere else changed.

    Pure function

  2. 02

    the function returned a number and also wrote a row, and the second half is not in the signature anywhere.

    Side effect

  3. 03

    you replaced the call with the value it returned and the program behaved identically, which is not true of most calls.

    Referential transparency

  4. 04

    all the decisions are in functions with no I/O, and a thin outer layer does the reading and writing around them.

    Functional core, imperative shell

  5. 05

    nothing that was handed out can be changed, so you stopped copying defensively and stopped worrying about who else holds it.

    Immutability

  6. 06

    the copy was free until somebody wrote to it, and only then did the data actually get duplicated.

    Copy-on-write

  7. 07

    you added an item and got a new list back, and the old one is still there and still valid.

    Persistent data structure

  8. 08

    the new version copied five nodes rather than ten thousand elements, because everything unchanged is the same objects.

    Structural sharing

  9. 09

    you put the function in a variable, passed it to something and returned it from somewhere else, like any other value.

    First-class function

  10. 10

    the function's argument is another function, and what it actually does depends entirely on what you passed.

    Higher-order function

  11. 11

    the loop with an accumulator and two conditions became three named steps, and the intermediate variable disappeared.

    Map, filter, reduce

  12. 12

    you built one function out of three others, and the intermediate values never got names.

    Function composition

  13. 13

    the two-argument function became a function of one argument that returns a function of one argument.

    Currying

  14. 14

    you fixed the first argument once and passed the resulting one-argument function around instead.

    Partial application

  15. 15

    you built a pipeline over a million rows, took the first ten, and only about ten rows were ever processed.

    Lazy evaluation

  16. 16

    the recursion went a million deep and the stack never grew, because the call was the very last thing the function did.

    Tail call optimisation

  17. 17

    the type says it is exactly one of four things, and the compiler will not let you forget the fourth.

    Algebraic data type

  18. 18

    one expression takes the value apart, names its pieces and picks a branch, all in the same line.

    Pattern matching

  19. 19

    you added a fifth case to the type and the build failed in nine places, which is exactly what you wanted.

    Exhaustiveness checking

  20. 20

    the type says the value might not be there, so you cannot use it without saying what happens when it is not.

    Option type

  21. 21

    the failure came back as a return value with the reason attached, and no exception was ever thrown.

    Result type

  22. 22

    each step either continues the happy path or diverts to the failure track, and no step checks whether the last one worked.

    Railway-oriented programming

  23. 23

    you had a value in a box, a function returning another box, and needed one box out rather than a box in a box.

    Monad

  24. 24

    each function takes the next one and returns a new one, so authentication wrapped logging wrapped the actual handler.

    Middleware

  25. 25

    one version says what the result should be and the other lists the steps, and only one of them can be optimised for you.

    Declarative vs imperative