Forcing weak-pure
Steven Schveighoffer
schveiguy at yahoo.com
Tue Mar 25 17:23:36 PDT 2014
On Tue, 25 Mar 2014 19:30:04 -0400, Artur Skawina <art.08.09 at gmail.com>
wrote:
> On 03/25/14 21:51, Steven Schveighoffer wrote:
>> On Tue, 25 Mar 2014 14:49:27 -0400, Artur Skawina <art.08.09 at gmail.com>
>> wrote:
>>
>>> On 03/25/14 14:30, Steven Schveighoffer wrote:
>>>> [...] functions like GC.setAttr and assumeSafeAppend cannot be marked
>>>> pure. For example:
>>>>
>>>> auto str = "hello".idup;
>>>> str = str[0..1];
>>>> str.assumeSafeAppend();
>>>> str ~= "iya";
>>>>
>>>> The compiler could rationally elide the call to assumeSafeAppend if
>>>> it is pure. We are not using the return value, and the only parameter
>>>> is immutable. Since pure functions technically have no side effects,
>>>> this call can be eliminated. A recent compiler change made such calls
>>>> warnings (not using result of strong-pure function). But
>>>> assumeSafeAppend really should be weak-pure, because it does have an
>>>> effect. In essence, you are technically passing to assumeSafeAppend a
>>>> pointer to the block that contains the slice, not the slice itself.
>>>> And that block is mutable.
>>>>
>>>> GC.setAttr has similar issues.
>>>>
>>>> How can we force these to be weak-pure?
>>>
>>> Functions returning 'void' and w/o mutable args cannot be logically
>>> pure,
>>> as long as they aren't no-ops, obviously. While this property could be
>>> used to render them "weak-pure" in d-speak, this (or any other approach
>>> to marking them as such) would not be enough...
>>>
>>> // assuming 'assumeSafeAppend()' is "weak-pure":
>>>
>>> string f(string s) pure { s.assumeSafeAppend(); s ~= "d"; return s;
>>> }
>>> string a = "abc".idup, b = f(a[0..2]);
>>
>> This could not be elided, because you are using the return value. It
>> would have to be called at least once.
>>
>> However, I am OK with it being elided for a second call with the same
>> input. In other words, this strong pure function does not have the same
>> issues.
>
> It's ok to treat allocator and factory functions as pure, because those
> really
> are logically pure, ie can't affect any /visible/ state and return
> results that
> are unique.
> 'assumeSafeAppend()' does have side effects - it can lead to corruption
> of other,
> not directly related, data. The only thing that prevents this is a
> declaration
> by the programmer -- "Trust me, I own this data and there are no other
> live aliases".
> The problem is that this declaration would now happen /implicitly when
> calling
> a (strongly) pure function/.
> Note that the 'a' string in the above example could no longer be "abc"
> after 'f()'
> runs.
> The "pure" concept (re-)definition in D is bad enough even without
> having to worry
> about supposedly pure functions stomping on unrelated data.
You what I wasn't thinking of? parallelization of pure function calls!
Right there, that kills this whole idea.
In fact, I think at this point, any operation to immutable arrays that
affects the metadata for that block, including setting length and
appending, must be by definition impure.
This is not a good turn of events...
-Steve
More information about the Digitalmars-d
mailing list