On Fri, Apr 27, 2012 at 07:25:30PM +0200, Joseph Rushton Wakeling wrote: > On 27/04/12 19:08, Steven Schveighoffer wrote: > >weak purity, I think, is one of the most revolutionary ideas to come > >from D. Essentially, we get compiler-checked pure functions that can > >be written imperatively instead of functionally. > > I do agree with that; it's a very attractive aspect of D that a > function or object can be internally imperative but pure as far as the > outside world is concerned. Seeing that documented in Andrei's > writings was another "Wow!" moment for me about D. :-) > > What concerned me here was that the way my reputation() function was > set up actually did change the public state of the object, which to my > mind isn't even weakly pure. But I just wrote a fix which, contrary > to my fears, didn't affect the speed of the program.
As mentioned by others, D internally recognizes two kinds of purity, which is unofficially called "strong purity" and "weak purity". The idea is that strong purity corresponds with what functional programming languages call "pure", whereas weak purity allows mutation of state outside the function, *but only through function parameters*. The idea is that strongly pure functions are allowed to call weakly pure functions, provided any reference parameters passed in never escape the scope of the strongly pure function. For example, a strongly pure function is allowed to pass in pointers to local variables which the weakly pure function can modify through the pointer: pure real computationHelper(real arg1, ref real arg2) { // This mutates arg2, so this function is only weakly // pure arg2 = sin(arg1); return cos(arg1); } pure real complexComputation(real[] args) { real tempValue; ... // Note: this changes tempValue real anotherTempValue = computationHelper(args[0], tempValue); // But since tempValue is only used inside this // function, it does not violate strong purity return tempValue + complicatedFunc(args[1]); } As far as the outside world is concerned, complexComputation is a strongly pure function, because even though computationHelper mutates stuff through its arguments, those mutations are all local to complexComputation, and does not actually touch global world state outside. Weakly pure functions cannot mutate anything that they don't receive through their arguments (the 'this' pointer is considered part of their arguments, it's just implicit), so as long as the strongly pure function never passes in a pointer to the outside world, everything is OK. The motivation for distinguishing between these types of purity is to expand the scope of what the strongly-pure function can call. By allowing weakly pure functions to be called from strongly-pure functions, we open up many more implementation possibilities while still retaining all the benefits of strong purity. > >If the function is weakly pure, then it cannot be optimized based on > >purity, so I don't think there is any way marking it pure *hurts*. > > I was more concerned that the compiler wasn't identifying what to me > was a violation of purity. I'm fairly sure I can also find a way to > make some of those "nothrow" functions throw an error ... It's not a violation of purity, it's just "weak purity". If you try to access a global variable, for example, it will trigger an error. And nothrow functions *are* allowed to throw Error objects. That's also a deliberate decision. :-) T -- "640K ought to be enough" -- Bill G., 1984. "The Internet is not a primary goal for PC usage" -- Bill G., 1995. "Linux has no impact on Microsoft's strategy" -- Bill G., 1999.