Don wrote:
> It seems that pure and nothrow are attributes, just like @safe.
> (By contrast, you can overload functions based on const and immutable).
> Should the names be changed?

This runs into another issue I was thinking about.

So I'm working on this property rewrite thing that does the following:

foo.prop.func();

becomes

auto t = foo.prop;
t.func();
foo.prop = t.func();

This of course assumes that calling t.func() will mutate t.  But, as I
understand it, pure member functions can't mutate their aggregates.  So
if func() was pure, then foo.prop.func() shouldn't be rewritten, and the
setter for prop should never be called.

This would mean that pure would change the behavior of a program.  Now,
if attributes are not allowed to change the behavior of a program and
property expressions are rewritten correctly, then @pure would
contradict itself.

Note: This has less to do with pure itself, and more to do with the idea
that pure functions only work with immutable data.  The property
rewriting couldn't care less whether or not the function is
deterministic, but it does care about whether or not a function's
arguments are lvalues (ex: ref parameters), including the hidden
argument containing the aggregate in method calls.

For a (slightly) more concrete example of why this matters:

import std.stdio;

struct IntProxy
{
    int data;

    pure IntProxy opAdd(IntProxy other)
    {
    IntProxy ip;
    ip.data = data + other.data;
        return ip;
    }

    IntProxy opAddAssign(IntProxy other)
    {
        this.data++;
        return this;
    }
}

class Foo
{
    IntProxy bar;
    IntProxy prop() { return bar; }
}

void main()
{
    Foo foo = new Foo();
    IntProxy ip;

    foo.bar.data = 2;
    ip.data = 2;

    IntProxy result = foo.prop + ip;

    assert(result.data == 4);
    writefln("%s",result.data);
}

I expect this program to compile, run, and print "4".

If pure were an annotation AND annotations couldn't change program
behavior AND property expression rewrite were in place, then this
program would fail to compile because there is no corresponding setter
function for foo.prop.  Due to annotations being passive, this requires
the compiler to ignore the pure status of IntProxy.opAdd and treat it
like any other impure function for purposes of property rewriting.  The
setter would then be needed to receive the possibly mutated IntProxy
returned by prop.opAdd(ip).

- Chad

Reply via email to