Memory allocation purity

Jonathan M Davis via Digitalmars-d digitalmars-d at puremagic.com
Sun May 18 23:25:08 PDT 2014


On Mon, 19 May 2014 06:05:26 +0000
via Digitalmars-d <digitalmars-d at puremagic.com> wrote:

> On Monday, 19 May 2014 at 05:39:49 UTC, Jonathan M Davis via
> Digitalmars-d wrote:
> > 1. it makes it easier to reason about code, because it
> > guarantees that the
> > function didn't access any global or static variables.
>
> It can, through the parameters, like an array of pointers. And
> avoiding IO is not sufficient to mark 90% of my code as weakly
> pure.

Except that if most of your code is marked pure, then there aren't very many
points where it could access a global or static variable. And regardless of
that, the fact that the only way to access a global or static variable in a
pure function is through one of its arguments still guarantees that the
function isn't messing with anything that wasn't passed to it, so that still
helps a lot with being able to reason about code. Sure, it could still be
passed an argument that points to a global variable (directly or indirectly),
but then you only have to worry about globals being accessed if they were
passed in (directly or indirectly). Sure, it's not as big a gain as when a
function is strongly pure, but it's good enough for most cases.

> > 2. it allows us to implicitly convert to different levels of
> > mutability for
> > the return type of pure functions where the compiler can
> > guarantee that the
> > return value was allocated within the function.
>
> But if you can have a struct/pointer as a parameter then you can
> clearly return objects not allocated in the function?

The compiler is smart enough in many cases to determine whether the return
value could have been passed in or not (though it wouldn't surprise me if it
could be made smarter in that regard). With a function like

string foo(string bar) pure {...}

it can't assume that the return type is unique, because it could have been
passed in via the parameter, but with

string foo(char[] bar) pure {..}

or

int* foo(string bar) pure {..}

it could, because it's impossible for the parameter to be returned from the
function (unless casting that breaks the type system is used anyway - and the
compiler is free to assume that that isn't done). So, it varies quite a bit as
to whether a pure function is guaranteed to be returning newly allocated
memory or not, but the compiler often can determine that, and when it can, it
makes dealing with immutable far, far more pleasant. It's particularly useful
when you need to allocate an immutable object but also need to mutate it as
part of initializing it. If you do it in a pure function where the compiler
knows that the object couldn't have been passed in, then the return type can
be freely converted to various levels of mutability - including immutable -
without having to use immutable within the function.

- Jonathan M Davis


More information about the Digitalmars-d mailing list