> 1) function is intrinsically pure in the mathematical sense: it produces the same output for the same input each time. In practical terms, code execution must not have side effects on the system.
Now if we go back to the example and Odersky's citation. If you have a function `foo` that returns `IO[String]` using e.g. cats.effect.IO or zio.IO. And the String is e.g. the content of a file or something else. Then, is this function pure or not? Answer: it is. You can call it multiple times, it proces the same output for the same input.
val x = foo
val x2 = foo
val x3 = foo
No matter which of those x you use, the result will always be the same. You can call the function as often as you want. There is no side effect being executed. Hence the function is pure by your the definition you just gave and hence Odersky's claim is incorrect (I think he probably would not say this again nowadays).
> 2) function has been made pure in the sense that a compiler can reason about its inputs and outputs as if it was actually pure in the mathematical sense. Code execution can have side effects on the system, but this has been neatly abstracted away.
What does "neatly abstracted away" means? How is this function different from a one in 1) and how is it different from a function that is just impure? Can you give an example?
> Memory limitations are not a good analogue: I/O requires interrupts.
They are a very good analogue, because conceptioally they too cannot exist on Von Neumann architectures. Why does the reason matter? I also gave another example: generics. How about those? They don't even require any specific physical limitations, they simply vanish. I can come up with more examples, but I don't really see the point. Obviously people use pure functional programming and they call it like that. If you say that isn't possible, I think we are now discussion (again) terminology and not practical implications.
Now if we go back to the example and Odersky's citation. If you have a function `foo` that returns `IO[String]` using e.g. cats.effect.IO or zio.IO. And the String is e.g. the content of a file or something else. Then, is this function pure or not? Answer: it is. You can call it multiple times, it proces the same output for the same input.
No matter which of those x you use, the result will always be the same. You can call the function as often as you want. There is no side effect being executed. Hence the function is pure by your the definition you just gave and hence Odersky's claim is incorrect (I think he probably would not say this again nowadays).> 2) function has been made pure in the sense that a compiler can reason about its inputs and outputs as if it was actually pure in the mathematical sense. Code execution can have side effects on the system, but this has been neatly abstracted away.
What does "neatly abstracted away" means? How is this function different from a one in 1) and how is it different from a function that is just impure? Can you give an example?
> Memory limitations are not a good analogue: I/O requires interrupts.
They are a very good analogue, because conceptioally they too cannot exist on Von Neumann architectures. Why does the reason matter? I also gave another example: generics. How about those? They don't even require any specific physical limitations, they simply vanish. I can come up with more examples, but I don't really see the point. Obviously people use pure functional programming and they call it like that. If you say that isn't possible, I think we are now discussion (again) terminology and not practical implications.