pure int fun(int d, int divisor)
{
if (d < 0)
d -= divisor - 1;
return d / divisor;
}
This doesn't compile because d is assumed to be constant. It doesn't have to because it's a private copy of the function. Beware when fixing this - any indirectly-referenced data is not part of function's private state.
Comment #1 by clugdbug — 2009-07-03T02:17:24Z
Comment: Allowing this would mean that nested pure functions would no longer be able to use the parameters from the enclosing function.
pure int fun(int d, int divisor)
{
int gun() pure { return d+1; } // would be illegal, since 'fun' could modify d.
return gun() + d / divisor;
}
Which in turn would mean that nested pure functions would become quite useless. So there's a price to pay.
Comment #2 by samukha — 2009-10-13T03:46:47Z
Instead of introducing another inconsistency into the language for the not-so-common case, you could take the opposite route:
pure int fun(int d, int divisor)
{
immutable c = d;
int gun() pure { return c + 1; }
return gun() + d / divisor;
}
Comment #3 by clugdbug — 2009-10-13T06:06:14Z
(In reply to comment #2)
> Instead of introducing another inconsistency into the language for the
> not-so-common case, you could take the opposite route:
>
> pure int fun(int d, int divisor)
> {
> immutable c = d;
> int gun() pure { return c + 1; }
>
> return gun() + d / divisor;
> }
I think the existing behaviour -- that you cannot change any of the parameters in a pure function -- is simple and intuitive: pure functions can only modify variables which they created themselves. A rule that pure nested functions can use indirectly-referenced data, but cannot use parameters which are passed by value, just seems complicated.
Especially, in the case where a parameter contains a reference to other data, it seems folly to be allowed to change part of the parameter, but not all of it.
Comment #4 by samukha — 2009-10-13T08:44:23Z
> I think the existing behaviour -- that you cannot change any of the parameters
> in a pure function -- is simple and intuitive: pure functions can only modify
> variables which they created themselves.
But the passed-by-value parts of the arguments are copied and consequently can be qualified as "variables which they created themselves".
> A rule that pure nested functions can
> use indirectly-referenced data, but cannot use parameters which are passed by
> value, just seems complicated.
I don't think it is too complicated. It can be trivially done like this:
pure int foo(in int d, ...)
{
// now we should be able to use d in pure nested functions because it is
// guaranteed to not change during the function call.
}
> Especially, in the case where a parameter contains a reference to other data,
> it seems folly to be allowed to change part of the parameter, but not all of
> it.
I am not sure. For example, it seems to be fairly intuitive to be able to rebind a string parameter, though changing the referenced part of it is not allowed. I would agree if D's function parameters behaved like aliases to the arguments, but they are more like the function's local variables, which arguments are assigned to.
Now that I am trying to purify some functions (most of which have no nested functions) I need to add the useless temporaries to make them compile :(
Comment #5 by bugzilla — 2009-12-11T23:30:21Z
This would reintroduce "tail-const" for the parameters, something that we tried hard to make work and failed. I'd rather just leave the parameters const. If you have to make a mutable copy, as in:
pure int fun(int d, int divisor)
{ auto x = d;
if (x < 0)
x -= divisor - 1;
return x / divisor;
}
that isn't much of a burden, and the compiler will optimize the extra copy away anyway.
Comment #6 by dsimcha — 2010-08-15T21:24:26Z
*** Issue 4630 has been marked as a duplicate of this issue. ***
Comment #7 by tomash.brechko — 2010-09-22T07:39:43Z
Note that (with dmd 2.049)
pure int f(int i)
{
return ++i;
}
doesn't compile, yet
pure auto f(int i)
{
return ++i;
}
does work (int return type is replaced with auto).
Also http://www.digitalmars.com/d/2.0/function.html section "Pure Functions" gives an example of assignment to parameter,
i = y; // ok, reading immutable global state
Comment #8 by tomash.brechko — 2010-09-22T08:05:37Z
Comment #9 by Jesse.K.Phillips+D — 2010-11-16T13:19:39Z
In the recent update of relaxed purity, this code now compiles. However I believe this is a weakly pure function as a strongly pure function requires its parameters to be immutable.