Consider:
__gshared int a;
pure int fun(int* x) {
if (x == &a) return 1;
return 42;
}
This does not compile. However, it does not depend on global modifiable state because the address of a global is a runtime invariant.
Comment #1 by pro.mathias.lang — 2021-07-28T16:01:54Z
If we allow it, what prevents the function from then passing it down to another pure function that will read / write to it ?
Comment #2 by andrei — 2021-07-28T17:45:07Z
(In reply to Mathias LANG from comment #1)
> If we allow it, what prevents the function from then passing it down to
> another pure function that will read / write to it ?
Good point. There'd need to be appropriate restrictions, e.g. the address is read but not passed around.
This issue prevents the application of the Null Object Pattern (https://en.wikipedia.org/wiki/Null_object_pattern) to Appender in Phobos. I started modifying the code around https://github.com/dlang/phobos/blob/master/std/array.d#L3264 like this:
private static __gshared Data nullData = { 0, null, false };
private Data* _data = &nullData;
It worked really nice because subsequently I could eliminate most tests comparing _data against null - they just worked with the empty data.
The one place I had to test was at https://github.com/dlang/phobos/blob/master/std/array.d#L3356, where I replaced `if (!_data)` with `if (_data != &nullData)`. That made the function impure and caused a bunch of compile-time errors for no good reason.
Comment #3 by n8sh.secondary — 2021-07-29T00:40:28Z
Putting the address in an enum appears to work:
---
__gshared int a;
pure int fun(int* x) {
enum int* addr = &a;
if (x == addr) return 1;
return 42;
}
---
Comment #4 by kinke — 2021-07-29T04:37:51Z
> Putting the address in an enum appears to work:
As does making the global immutable:
pure int fun(int* x) {
static immutable int a;
if (x == &a) return 1;
return 42;
}
Comment #5 by kinke — 2021-07-29T04:48:54Z
(In reply to Nathan S. from comment #3)
> Putting the address in an enum appears to work:
Seems like a great way to violate purity:
pure int fun(int* x) {
enum int* addr = &a;
*addr = *x; // boom
return 42;
}
Comment #6 by robert.schadek — 2024-12-13T19:17:41Z