pure functions

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Sep 13 13:42:58 PDT 2016


On Tuesday, September 13, 2016 20:08:22 Patrick Schluter via Digitalmars-d-
learn wrote:
> On Tuesday, 13 September 2016 at 06:59:10 UTC, Jonathan M Davis
>
> wrote:
> > On Tuesday, September 13, 2016 03:33:04 Ivy Encarnacion via
> >
> > Digitalmars-d- learn wrote:
> >  A pure function cannot call any function that is not pure [...]
>
> I've read that a lot but it's not true. A pure function can call
> impure function. The restriction is, that the impure function
> called within the pure function does not depend or mutate on
> state existing outside of that function. If the called function
> changes local variable, it has no bearing on outside the scope.
> Here a contrived example in C.
>
> size_t strlen(const char *str); is pure. If I define it this way
> for example:
>
> size_t my_strlen(const char *str)
> {
>    char temp[50];
>
>    strlcpy(temp, str, sizeof temp);  /* strlcpy is not pure as it
> mutates something outside of its "scope" */
>
>    return strlen(str);
> }
>
> That function is pure. There is no visible change outside of it.
>
> my_strlen and strlen have exactly the same properties.

That's because you're talking about functional purity and _not_ D's pure. If
you want to talk about D's pure, you pretty much need to forget about
functional purity. While D's pure allows you to get functional purity, it's
actually something different. It would be far more accurate at this point if
it were called something like @noglobal. Actual, functional purity really
only comes into play when a pure function's parameters are immutable or
implicitly convertible to immutable, at which point the compiler can
guarantee that the same arguments to the function will result in the
function returning the same result. Sometimes, pure functions whose
parameters are immutable or implicitly convertible to immutable are referred
to as strongly pure functions, whereas those whose parameters aren't are
called weakly pure. So-called strongly pure functions are what you need if
you want to talk about functional purity, whereas so-called weakly pure
functions are still pure as far as D is concerned, because they don't
violate the functional purity of a strongly pure function if they're called
by it.

Originally, for a function to be pure in D, it _had_ to have parameters
which were immutable or implicitly convertible to immutable, which actually
was functionally pure, but it was too restrictive to be useful, so pure was
expanded to what it is now, which makes it so that it's not really about
functional purity anymore even though it enables functional purity in a way
that the compiler can detect it and optimize for it.

But when a D programmer talks about a function that's imppure, they're
generally not talking about functional purity but about whether it's marked
with pure or inferred as pure by the compiler, and per that definition, the
code that you have above _is_ pure. In a way, what you're trying to prove
about impure in D is both right and wrong, because we're dealing with
conflicting definitions of purity here. When discussing pure in D, if you
want to talk about whether a function is functionally pure in the sense that
one would normally talk about pure functions outside of D, then you need to
clearly state that you're talking about functional purity and not about D's
pure. When simply saying that something is pure or not, folks here are going
to expect you to be talking about D's definition of purity.

By the way, the only ways to get around pure are:

1. use debug blocks (where pure is ignored in order to facilite debugging).

2. use an extern(*) other than extern(D) so that the body of the function
   doesn't have to be marked pure like the prototype does (since other types
   of linkage don't actually use pure), allowing you to lie to the compiler.

3. use function pointers and cast an impure function pointer to a pure one
   and thereby lie to the compiler.

So, there are a couple of ways to fool the compiler, but there's only one
wayt that's sanctioned by it, and it's only intended for debugging purposes.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list