On Thursday, December 22, 2016 18:04:51 Observer via Digitalmars-d wrote: > It seems to me that a pure function could have a variety of > acceptable side effects which don't modify active memory and > that don't work around the type system or necessarily eat > significant CPU time, and that you probably don't want to > have elided. Here are some examples. > > (1) Serve as a convenient breakpoint handle in the debugger, > perhaps > as a kind of centralized this_cannot_ever_happen() function.
I suppose, but that doesn't really have anything to do with what a purity. Any function could be a point to break in the debugger. > (2) conditionally_die(conditions); Depending on what you mean by conditionally die, yes, that's legit. Errors can be thrown from pure functions (even strongly pure functions), and the spec specifically allows a pure function to terminate the program (so calling exit should be legit, though I'm not sure if it's actually marked as pure). > (3) Sleep for some run-time-computable length of time. This doesn't really make sense. It _might_ make sense for a weakly pure function to do so via a function argument, but once we're talking strongly pure functions, this doesn't make sense at all. At that point, we're talking functional purity. The same input is supposed to give the exact same output, and the compiler is free to optimize out calls to the pure function when it's called multiple times with the same arguments. So, relying on anything to do with timing simply wouldn't work, and sleeping in a strongly pure function just doesn't make sense. It's questionable as to whether it even makes sense in a weakly pure one. Regardless, right now, it certainly isn't legal, because there is no sleep function marked as pure in druntime. > (4) Yield the thread so other threads can take execution priority. > > (5) Yield the entire process so other processes can take execution > priority. These both have basically the same problem as sleeping. They may no sense for strongly pure functions and questionable sense for weakly pure ones and are not currently allowed in pure functions. > (6) Wait for an external trigger (perhaps a hardware interrupt, > for > instance). This definitely does not sound legit. It explicit depends on the OS state, which is the sort of thing that's generally banned in pure functions. > (7) Invoke a pass of garbage collection. This, however, would probably be legit for the same reasons that new and malloc are considered pure. Certainly, most of core.memory.GC is either marked as pure or /* FIXME pure */, and given that GC.free is already pure, having GC.collect be pure would make sense. > My point here is that when considering what functions do, mutating > memory is only part of the story. Control of time and other > resources > can be a critical part of overall program execution, and you > don't want > the compiler assuming it can ignore such aspects. Conceptually, it makes no sense to be doing any of that sort of thing in a strongly pure function, because at that point, we're really talking functional purity. The same input is supposed to give the same output, and while it's debatable whether timing is part of that, it would have to at least be taking the same actions given the same input. And if the compiler has to worry about how the timing of a pure function affects the program, then it could _never_ elide a call to a pure function, which would defeat one of the main reasons that the feature was introduced in the first place. So, I'm inclined to think that anything with regards to timing has no business in a pure function. - Jonathan M Davis
