On Wednesday, March 09, 2016 09:56:05 Guillaume Piolat via Digitalmars-d-learn wrote: > If I understand purity correctly > (http://klickverbot.at/blog/2012/05/purity-in-d/), every function > out there can be marked pure as long as it doesn't modify > globals, shared variables or do I/O? > > It seems more function can be marked pure that I previously > thought.
Basically, a pure function cannot call a function which is not pure, and it can't access any global or static variables which are mutable (or const if the type has indirections - the variable has to be completely unchangeable to be accessible). And that's it. shared has nothing to do with it one way or the other, and I/O isn't explicitly forbidden, but not being able to access mutable globals or non-pure functions naturally kills I/O. The exception is that inside of debug{} blocks, purity is ignored, so you can do I/O there, but it's intended purely for debugging purposes. So, in general, you can slap pure on most anything, though it will rarely buy you anything in terms of performance. What it primarily buys you is the knowledge that you're not messing with global variables unless the function's arguments give you access to them. The second major gain is that in many cases, a pure function's return type can have its constancy inferred, making it possible to allocate a mutable object inside of a pure function, do whatever needs to be done to it to set it up, and then have it implicitly converted to immutable when it's returned (for that to work though, the compiler has to be able to guarantee that the return value didn't come from any of the function arguments). The main place where performance gains could take place would be in cases where a pure function is called multiple times in the same expression with the same arguments, and the compiler is able to determine that it's impossible for those arguments to have been mutated between calls, allowing the compiler to just make the call once and reuse the result. AFAIK, that currently requires that the function parameters be immutable or implicitly convertible to immutable, though in theory, it should be possible for const parameters when the arguments are immutable. Regardless, it's occasionally useful but not very often. Having lots of pure functions makes it easier to have useful functions with immutable arguments, whereas when pure functions always required that the parameters be immutable (or implicitly convertible to immutable), the really couldn't do much. But the result is that most pure functions can't really be optimized base on their purity. The two places that you need to be careful with pure though are virtual functions and templated functions. If a base class function is pure, then the derived class overrides also have to be pure, whereas if the base class function isn't pure, then the derived class function can't normally be pure (it _might_ be able to be pure if it doesn't call the base class function). So, when dealing with virtual functions, you have to be careful about whether you want to avoid restricting virtual functions from being used in pure code (by not marking the base class function pure) or whether you want to restrict what derived class functions can do (by marking the base class function pure). The reason to avoid pure with templated functions is that whether a templated function can really be pure or not usually depends on its arguments. If the types it's instantiated with use pure functions, then it can be pure, whereas if they don't, then it can't be. So, you'd have a similar problem to that of virtual functions except that pure, nothrow, and @safe are inferred for template functions, so if the function doesn't do anything which makes it so that it can't be pure, the compiler should infer it to be pure without you needing to mark it as pure. In general though, you should use pure wherever possible. - Jonathan M Davis