digitalmars.D - confused about pure functions
- markusle (10/10) Mar 17 2012 Using dmd 2.058 I can compile the following
- Adam D. Ruppe (32/32) Mar 17 2012 In D, pure means it doesn't have any side effects outside
- Andrei Alexandrescu (10/20) Mar 17 2012 D's working definition of a pure function is "effect only depends on
- markusle (4/34) Mar 17 2012 Thanks a lot for yours and Adam's detailed explanation. This
Using dmd 2.058 I can compile the following pure bool has_path(string paths[], string needle) { paths[0] = "bad"; ... do something else ... return false; } and change the passed in array "paths". Isn't this a violation of has_path's pure contract? Shouldn't all pure function parameters be passed as "in" to avoid side effects. Sorry if I missed something obvious.
Mar 17 2012
In D, pure means it doesn't have any side effects outside its parameter list. It can change what you pass in, but nothing else. Pass it all in, const, or best of all, immutable params and it can't change anything - that's the pure you're probably thinking of. The reason it lets you change the arguments is so you can use more functions as pure. Consider that you can have mutable local variables in a pure function - a local variable doesn't change the outside world, so it never breaks the contract. You might want to use a helper function on your local variables. Editing a local variable is allowed, so calling a function that edits a local variable should be allowed too. As far as the outside world can tell, this is exactly the same thing. pure void increment(ref int a) { a++; } int myInt = 0; increment(myInt); // is logically the same as myInt++; // we'd allow myInt++;, so we should allow increment(myInt) too. But, under the strictest definition of pure, that increment function wouldn't be allowed. Pure functions can only call other pure functions. That's why D pure is a little looser: this /should/ be allowed. Thus, it can be marked as pure. Does this break the big contract? No, because editing the params is a purely local modification - the outside world doesn't need to care how you build your own local variables. When combined with transitive immutable, you can create nice pockets of purity while retaining flexibility in how you implement the function itself. Only what you pass and get from it is important.
Mar 17 2012
On 3/17/12 12:02 PM, markusle wrote:Using dmd 2.058 I can compile the following pure bool has_path(string paths[], string needle) { paths[0] = "bad"; ... do something else ... return false; } and change the passed in array "paths". Isn't this a violation of has_path's pure contract? Shouldn't all pure function parameters be passed as "in" to avoid side effects. Sorry if I missed something obvious.D's working definition of a pure function is "effect only depends on parameters". Mutating parameters does fit the definition. This is less tight than other languages' definition, but we believe it's a sweet spot between reaping the modularity benefits of purity, and benefiting of the advantages of mutation. Also, not all is lost. If you want to disallow parameter mutation, add "in" to them. That way, you only need to see the function's signature to draw a variety of interesting facts about it. Andrei
Mar 17 2012
On Saturday, 17 March 2012 at 17:59:12 UTC, Andrei Alexandrescu wrote:On 3/17/12 12:02 PM, markusle wrote:Thanks a lot for yours and Adam's detailed explanation. This makes much more sense now.Using dmd 2.058 I can compile the following pure bool has_path(string paths[], string needle) { paths[0] = "bad"; ... do something else ... return false; } and change the passed in array "paths". Isn't this a violation of has_path's pure contract? Shouldn't all pure function parameters be passed as "in" to avoid side effects. Sorry if I missed something obvious.D's working definition of a pure function is "effect only depends on parameters". Mutating parameters does fit the definition. This is less tight than other languages' definition, but we believe it's a sweet spot between reaping the modularity benefits of purity, and benefiting of the advantages of mutation. Also, not all is lost. If you want to disallow parameter mutation, add "in" to them. That way, you only need to see the function's signature to draw a variety of interesting facts about it. Andrei
Mar 17 2012