Is Returning A Random Value From Function A Side Effect?
I was working on some F# code and I was working on a function to return a random string from a set of strings. Let's say I had something like this:
open System
let a = [|"a";"b";"c";"d"|]
let rstring (arr:string[]) =
let r = new Random()
arr.[r.Next(0,3)]
let resultstring = rstring a;;
My question is this: My understanding of the notion of functional programming is that if a given function has the same input each time it should always return the same output. So in this particular case is returning a different string each time a "side effect"? I'm just curious.
If this is a duplicate question, just point me to the original and I'll close this. I'm not sure what search string I would 开发者_C百科use to find any questions related to this one.
EDIT: Thanks for all the information everyone. It seems that I conflated the concepts of referential transparency and the lack of side-effects. So, thanks all for setting me straight on the difference and thanks for your answers.
Yes.
The only way that a function can return different values from the same input is via side effects. Other people may claim otherwise, but they are wrong.
(You can claim that 'reading the system time' (which is clearly based on effects) is not an effect. By this definition, it's not a side-effect. But that definition is not useful, since the only reason people "care" about side-effects is because they affect referential transparency. In other words, referential transparency is the only thing that matters, and this function is clearly not referentially transparent.)
"Side effect" means that some state is changed by the function, not that the return value differs. In your case, the function is doing both - it is changing the state of the PRNG and return a different value.
Edit:
I'll also add that if a function always returns the same value for a given input it is called idempotent. Also "side effect" includes functions that read from an external state. For example:
int global = 0;
int function()
{
return global;
}
has side effects.
It's ok for a function to be non-determinate. That is not a side-effect. A side-effect would be if it somehow changed the state of the program in addition to returning a value. I would say that both side-effects and non-determinism are ways that functions in functional programming differ from mathematical functions.
Ignoring implementation details of the random generator(which in practice requires side effects, and in theory doesn't have to), then this function is side effect free but not pure.
Basically imagine the function call to be an oracle machine that returns random numbers based entirely on nothing. There is a proof somewhere that says you can't do this, but for the time being just imagine it to be so.
If you treat a PRNG function as this oracle machine that gives you a random number each time you ask for it, hen it is side-effect free and impure, and the function inherits that.
The type of side effect that doesn't violate referential transparency is sometimes referred to as a "soft side effect" sine it doesn't alter the behavior of the program(note:before you tell me that reading the time changes the behavior of the number generated, the specification of the function call says that the function returns a random number. Reading the time clock is an implementation detail of getting that specification to work. Changing the time clock(except under extremely degenerate circumstances) does not alter the fact that the function returns a psuedo random number, since the specification doesn't detail what that number is.
The classic example of a soft side effect is logging, since programs usually don't inspect their logs and alter behavior based on it.
If you wanted to do this in a functionally pure way you would have to implement a state monad.
http://fsharpcode.blogspot.com/2008/12/f-state-monad-type-state-state-state-of.html
Basically take that, make you state a random number generator and the 'a an int, and then your control flow will isolate the impurity to a single function and creates a hard order on the sequencing.
There is really no point to doing this in F#, as having impure functions doesn't really cause problems(having functions with side effects on the other hand, does).
Of course that monad is impure, but it isolates the impurity nicely.
I don't believe your example would be considered a side effect.
http://en.wikipedia.org/wiki/Side_effect_(computer_science)
精彩评论