5

I saw this impure function on Udacity, but I think it's pure - I am confused. Can some one please explain?

const addAndPrint = (a, b) => { 
  const sum = a+b;
  console.log(`The sum is ${sum}`);
  return sum;
};
atravers
  • 455
  • 4
  • 8
CodeNinja101
  • 1,091
  • 4
  • 11
  • 19
  • 1
    It depends on whether you consider logging to the console to be a side effect or not. Do you? – Bergi Sep 05 '17 at 08:05
  • 2
    Basically, this is opinion-based. – Cerbrus Sep 05 '17 at 08:05
  • I used to think this was pure, but using `console` can only ever be a side effect. So in my _opinion_, no it's not a pure function. – evolutionxbox Sep 05 '17 at 08:15
  • 1
    Sure, it doesn't alter any state within your program, but it does alter the state of the real world, your screen namely. Hence it is impure. @Cerbrus can you replace this expression with its result value without changing the behavior of the program? Purity isn't a matter of opinion. –  Sep 05 '17 at 08:34
  • 1
    @ftor: That's your _opinion_. "Purity" is a theory. It's a "style". It's something someone made up. I'm not saying it's right or wrong, but it's certainly open to interpretation. – Cerbrus Sep 05 '17 at 08:36
  • @Cerberus I think it comes from math and people try to transfer it to programming. I can't tell if this is possible at all. I think every pure language has its dirty, impure secrets. I am not an expert, though. –  Sep 05 '17 at 08:47
  • 1
    @ftor: That I can certainly agree with. – Cerbrus Sep 05 '17 at 08:50
  • 1
    @ftor how about this : `let add => (a, b, f) => { f('the sum is ' + (a + b)); return a + b; };`. Now purity depends on the caller (`f` could be a no-op). Or how about wrapping it in a data.Task? Is it pure then? You can go down that rabbit hole arbitrarily deeply. – Jared Smith Sep 05 '17 at 13:08
  • @JaredSmith I'd say `add` is a HOF and pure, if `f` is pure. And `((x, y) => () => addAndPrint(x, y)) (2, 3)` is also pure, however, not the subsequent call. But I got your point, it's a matter of confidence. –  Sep 05 '17 at 15:44

2 Answers2

17

It is not a pure function, because

console.log(`The sum is ${sum}`);

violates point 2:

  1. Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
4

For the same input it will always give you the same result. You don't have any outer references inside your function, so it depends only on the input parameters.

Something that can be considered as impure inside your function is that, (not related to the return value) somebody can change the console's log function to do another thing.

For example

const addAndPrint = (a, b) => { 
  const sum = a+b;
  console.log(`The sum is ${sum}`);
  return sum;
};

console.log(addAndPrint(4,5));
const log = console.log;
console.log = (t) => log('Not the same output');
console.log(addAndPrint(4,5));

And as @Nina answered, it violates to the second point, so based on the pure function's declaration, it is not a pure function.

Suren Srapyan
  • 66,568
  • 14
  • 114
  • 112
  • 1
    No, we usually don't consider something impure just because it uses an overwritable function; function references are normally treated as constant. – Bergi Sep 05 '17 at 08:08
  • @Bergi understood you. But we only consider, yes? I mean for example I can refer the function to access a global variable and change it's state – Suren Srapyan Sep 05 '17 at 08:10
  • 1
    Well we always have to *consider* something to be pure, as every evaluation on an real computer involves changing memory. We do this kind of reasoning when it is useful, and to be doable we *assume* that references are constant. – Bergi Sep 05 '17 at 17:08