Bug 11046 – [enh] Pure functions with default and out parameters are allowed
Status
RESOLVED
Resolution
WONTFIX
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-09-15T13:48:00Z
Last change time
2015-06-09T05:15:19Z
Assigned to
nobody
Creator
maxim
Comments
Comment #0 by maxim — 2013-09-15T13:48:26Z
extern(C) int printf(const char*, ...);
pure foo(out int arg = x) { }
int x = 1;
void main()
{
foo();
printf("%d\n", x); // 0
}
Strictly speaking, spec does not prohibit pure functions from modifying its arguments. On the other hand, there is no much sense in supporting such code.
Comment #1 by maxim — 2013-09-15T14:01:10Z
Sorry, it is definitely a bug because global variable is mutable.
Comment #2 by maxim — 2013-09-15T14:02:19Z
Another test-case:
int a;
pure foo(ref int a = a) { ++a; }
void main() pure
{
foo();
}
Comment #3 by issues.dlang — 2013-09-15T14:04:06Z
Of course, it makes sense to support such code. In such a case, it's a weakly pure function rather than a strongly pure one. It can then be used by strongly pure functions.
Weakly pure functions are functions which which cannot access global mutable state (e.g. they can't access mutable global variables or have mutable static variables in their bodies). By itself, that is _all_ that pure indicates. It means _nothing_ about altering its arguments or returning the same value every time or anything of the sort.
Strongly pure functions are pure functions whose parameters are all either immutable or implicitly convertible to immutable. In such a case, the compiler can guarantee that the function's arguments aren't mutated, and the compiler can take advantage of that for optimization - e.g. calling foo only once in the expression foo(2) * foo(2). Weakly pure functions cannot be optimized like that, but they can be called from strongly pure functions (since they do not affect anything outside of the strongly pure function and therefore do not affect its guarantees), so they become very useful in writing strongly pure functions.
So, pure in D really is not functional purity. Rather, it provides the building blocks for function purity (and strongly pure functions are then functionally pure).
In fact, the primary benefit of pure is arguably the fact that it guarantees that the function does not access global mutable state rather than anything to do with functional purity or optimizations.
Comment #4 by issues.dlang — 2013-09-15T14:06:27Z
> Sorry, it is definitely a bug because global variable is mutable.
It mutates global mutable state via one of its arguments. pure functions cannot access global mutable state _directly_, but they can do so if passed a reference or pointer to global data. This is intended behavior and does not present a problem. It's just fine for weakly pure functions and violates nothing for strongly pure functions (because they could never pass a reference or pointer to a weakly pure function, because they can't access them).
Comment #5 by safety0ff.bugz — 2013-09-15T14:44:56Z
I think the problem is this:
import std.stdio;
pure foo1() { bar();} // Compiles (accepts-invalid)
//pure foo2() { bar(x);} // Equivalent but doesn't compile (correct behaviour)
pure bar(out int arg = x) { }
int x = 1;
void main()
{
foo1();
writeln(x); // 0
}
Comment #6 by issues.dlang — 2013-09-15T14:55:05Z
> I think the problem is this:
_That_ is a bug and should be reported as such, but it's different from arguing that pure functions should not be allowed to have out parameters with default arguments, which is what this enhancement request was asking for. It also has nothing to do with out parameters, unlike this enhancement request.
I just reported the issue: Bug# 11048
Comment #7 by maxim — 2013-09-15T22:53:56Z
(In reply to comment #6)
> > I think the problem is this:
>
> _That_ is a bug and should be reported as such, but it's different from arguing
> that pure functions should not be allowed to have out parameters with default
> arguments, which is what this enhancement request was asking for. It also has
> nothing to do with out parameters, unlike this enhancement request.
>
> I just reported the issue: Bug# 11048
The issue was _not_ about banning all pure functions with out parameters for which there are default values, but about not taking into account module scope of default argument. This is essentially the same issue (dmd does not check status) you reported but with a better test case.
Comment #8 by issues.dlang — 2013-09-16T09:33:03Z
> The issue was _not_ about banning all pure functions with out parameters for
> which there are default values, but about not taking into account module scope
> of default argument. This is essentially the same issue (dmd does not check
> status) you reported but with a better test case.
Well, then you needed to have been clearer in the title and description of the issue. "Pure functions with default and out parameters are allowed!" says nothing about global variables, and while the default argument in the example happens to use a global variable, the text that goes with it talks about modifying the arguments, not about global variables, and the fact that a pure function can modify its arguments is completely acceptable. It's just a weakly pure function rather than a strongly pure one in that case.