Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> The fact that a function gives you the same result given the same arguments is not meant to be some kind of encouragement to redundantly call a function many times.

All pure functions are by definition idempotent, and this quality is often celebrated as yet another point of merit. What is the point of highlighting this quality if functional programmers do not expect to over-execute them?

> It's meant to give you a tool to better reason about the program logically. You don't have to worry about _when_ a pure function is called…

If you say you don’t have to worry about when a function is called, the implication is that you don’t have to worry about how many times that function has been called. Functional programmers tend to belittle this sort of reasoning, and yet this sort of reasoning continues to be necessary when evaluating long-running, interactive programs for correctness.

This downplaying of executional reasoning is precisely why even if using pure functions on their own doesn’t encourage overexecution, the systems which functional programmers build typically do. We see this most clearly in discussions of reactivity, the fetishization of spreadsheets as programming model. Discrete events are tranformed into discrete outputs in a many-to-many relationship and yet functional programmers continue to think it’s not important to reason about the code which executed in between, the when and how much, just because it’s a composition of pure functions.



// stateful impl

class foo{ enum current_operator;

    init() { current_operator = ADD }

    evalOp(int a, int b){
        if (current_operator == ADD) return a + b;
        else if (current_operator == MULTIPLY) return a * b;
    }

    setOp(enum op){ current_operator = op; }
}

// pure impl

class bar{

    evalOp(enum op, int a, int b){

        if (op == ADD) return a + b;
        else if (op == MULTIPLY) return a * b;
    }
}

In the first case, evalOp is not pure since one has no idea on what is the current_operator set as. In the second case it is pure since the operator is part of the input.

Purity refers to reproducibility, as in no matter what else is going on, that function will always behave the same. You can have pure functions in OOP based languages, but in practice devs just default to managing state and having weird behavior depending on outside state of a given function.

As a side note, and since you mention runtime performance cost: if you implement a dummy generic cache layer and you have pure functions you will have an easier time than having stateful impls. In this case, that cache layer must have the ability to introspect into foo, but in bar that cache layer just keeps track of input and that's it.


Tangential:

Pure impl v2:

  class foo {
  public:
    //enum is a keyword, so let's call it _enum
    const _enum current_operator;
    foo(_enum co) : current_operator(co) { }
  // ... evalOp() as in your stateful impl example ...
  };

  //Example use:
  Reduce(foo{ADD}, 1, 2, 3, 4, 5, 6);
Point being, functional purity doesn't necessarily mean only functions taking all their inputs as arguments. It means no mutable state. In the above example, the class foo essentially represents a partially applied evalOp(). If you have multiple, related functions working on similar sets of parameters, you could put them in such a class with const members to create what is essentially a package of partially applied functions.


Pureness also makes it easier to remove calls to a function. If f is a pure function, then I know that if x, y or z doesn't change, then I never need to call f(x, y, z) again.


(Idempotence means f(f(x)) = f(x), whereas purity means f(x) = f(x).)


All pure functions are idempotent but not all idempotent functions are pure. It has nothing to do with the domain/range of the function.


You are correct in that there is a definition of idempotence that agrees with you, but you are wrong to correct the parent comment, because the most common mathematical definition of idempotence of functions agrees with them (and not you).

There are multiple definitions of idempotence, used even within computer science, and neither of you seem to be aware of the definition used by the other. The common mathematical definition of an idempotent function is that f(f(x)) = f(x) for all x. But in computer science there is another common definition which involves side effects not being repeated (that is, `f(); f();` is the same as `f();`).


> But in computer science there is another common definition which involves side effects not being repeated (that is, `f(); f();` is the same as `f();`).

where have you ever seen that definition ?!


> in imperative programming, a subroutine with side effects is idempotent if the system state remains the same after one or several calls

https://en.wikipedia.org/wiki/Idempotence#Computer_science_m...


It’s used commonly when working with unreliable communication (e.g. networking). For example, if you make a request but you don’t get a response, either the request or the response might have failed to send. It’s convenient if you don’t need to determine which case occurred; idempotent functions free you from worrying about whether the requested action was carried out.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: