On 12/03/2011 20:21, Don wrote:
Bruno Medeiros wrote:
On 23/02/2011 17:47, Steven Schveighoffer wrote:
On Wed, 23 Feb 2011 12:28:33 -0500, Andrei Alexandrescu
<seewebsiteforem...@erdani.org> wrote:

On 2/23/11 11:16 AM, Steven Schveighoffer wrote:

Just because a function is not marked @safe does not mean it is
unsafe.
It just means you can do things the compiler cannot verify are
safe, but
that you know are actually safe. I showed you earlier an example of a
safe pure function that uses malloc and free.

Programmers are allowed to make conceptually safe functions which are
not marked as @safe, why not the same for pure functions?

-Steve

I understand that. My point is that allowing unsafe functions to be
pure dilutes pure to the point of uselessness.

And that's not a point. It's an unsupported opinion.

pure has nothing to do with safety, it has to do with optimization. Safe
functions are no more optimizable than unsafe ones. Safety has to do
with reducing memory bugs.

The two concepts are orthogonal, I have not been convinced otherwise.

-Steve

pure has something to do with @safety. (Also, it has more to do with
than just optimization, it also affects code readability.)

In order to gain any benefit from calling pure functions (whether the
benefit is programmer code readability or compiler optimization) it
needs to be determined from the pure function's signature what is the
transitively reachable mutable state that the function may access.
Normally this state is whatever is transitively reachable from the
parameters. However, if you allow *arbitrary* _pointer arithmetic_ you
could legally manipulate any mutable data in your program from within
the pure function. This would make the pure attribute useless because
it would not offer any additional guarantees whatsoever over an unpure
function. So such a rule is necessary such that, for example, the
following function should not be allowed to be pure:

pure int func(int* ptr, int ix) {
return (ptr + ix)++;
}

I don't think this makes the pure attribute useless, since you still
only get a violation of purity, if you are smuggling in the address of a
global via some other parameter (in this case, ix).

I mean useless for the callers of pure functions (in other words the guarantees it offers externally). Inside the pure function it would still of some (limited) use, as the purity checks would still be present (you could not access a global directly, for example)

You just can't do strong purity optimisation if there are any pointer
parameters. But that remains true even if you disallow pointer
arithmetic inside pure functions.


Why is it the case that it is still true if you disallow pointer arithmetic?
For example:

void main() {
  int[] globalArray = initializedElsewhere();

  int b1 = globalArray[30];
  auto a1 = someComplicatedPureFunction(&globalArray[10], 42);

  int b2 = globalArray[30];

  globalArray[20] = 666;

  auto a2 = someComplicatedPureFunction(&globalArray[10], 42);
}


Can the initial value of b2 be taken from b1, or do we have to access the memory again? Similarly, can the initial value of a2 be taken from a1, or do we have to call someComplicatedPureFunction again?

It seems that if we disallow pointer arithmetic, the answer is yes for both case, but no otherwise. (well, for the a2 case it also needs to be that someComplicatedPureFunction does not return a value that it has allocated) Isn't it so?


--
Bruno Medeiros - Software Engineer

Reply via email to