Reputation: 198318
In the book of "function programming in Scala", it gives several example of what is "side-effects", one of them is:
I can understand "writing to a file" is not pure, because it changes the environment. But why "reading a file" is not pure? It doesn't change anything.
See my example:
val readFile: File => String = file => readingTheContentFromFile(file)
Upvotes: 6
Views: 1671
Reputation: 4620
A function is pure if for the same input arguments it gives the same result, so:
the function write(file)
is not pure because it can result in success or failure given the same file
.
the function read(file)
is not pure because it can return different data each time or fail, given the same file
.
Because they are not pure, they are not referentially transparent, that is, a function call write(file)
or read(file)
cannot be replaced by its result, because the next time the same call is made it can produce a different result.
The beauty of pure functions is that if they succeed now, then you can be confident that they will continue to succeed if they and the function they call did not change thereafter.
Note that purity has nothing to do with changing or not changing the environment, because:
every function internally reads and writes the computer memory, and consumes energy, so every function changes the environment;
if reading and writing the same file always returned the same result, then these functions would be pure, despite the fact they touch the environment.
Upvotes: 0
Reputation: 1647
A pure function allways returns the same value given the same input. Otherwise it is based on side effects (like changing a file). If you read from a file the results might change without the parameters given to the function changing.
The relevant concept is 'referential transparency'. This means you can substitute a function call and a given set of parameters with the result the function would return. Reading from a file is therefore not referentially transparent!
Upvotes: 16
Reputation: 47402
If a function is pure, then it is always safe to perform common subexpression elimination i.e. you could replace the following pseudocode
do {
x = readFile "file.txt"
writeFile "file.txt" "Goodbye"
return (x + readFile "file.txt")
}
with
do {
x = readFile "file.txt"
writeFile "file.txt" "Goodbye"
return (x + x)
}
and you would get the same result. But plainly, because of the call to writeFile
which appears between the two calls to readFile
in the first example, this is not a safe transformation to make, and therefore the function is not pure.
Upvotes: 8
Reputation: 16125
In functional programming, a function is pure if
- The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change while program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices.
- 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.
I/O can be modelled in a pure way if
- the sequence of operations on the relevant I/O devices is modeled explicitly as both an argument and a result, and
- I/O operations are taken to fail when the input sequence does not describe the operations actually taken since the program began execution.
That is, instead of actually reading from a file, you get the "file's content" as a parameter, and instead of actually writing to a file, you return the "file's output" as a value. This seems to be a thought exercise in most practical languages.
Upvotes: 3