Thread overview
How purity w/o the specific optimizations then allowed is useful ?
Apr 16
Basile B.
Apr 17
Dom DiSc
April 16

Short story for the context : someone has recently proposed the concept of purity for FreePascal, and only for their own dialect (aka ObjFPC). The proposition is to "check purity only when optimizations are enabled, because essentially the point of purity is only to optimize more" (think CTFE, think memoization).

But I fail to explain the opposite. How is purity a useful concept if not leading to specific optimizations ?

And is that even the case ?

Side note: I dont plan the use your answers to arguee w/ the author. It's more that conceptually I'm interested.

April 16
On Tuesday, April 16, 2024 9:07:34 AM MDT Basile B. via Digitalmars-d wrote:
> Short story for the context : someone has recently proposed the concept of purity for FreePascal, and only for their own dialect (aka _ObjFPC_). The proposition is to "check purity only when optimizations are enabled, because essentially the point of purity is only to optimize more" (think CTFE, think memoization).
>
> But [I fail to explain the opposite](https://gitlab.com/freepascal.org/fpc/source/-/merge_requests/645# note_1863564617). How is purity a useful concept if not leading to specific optimizations ?
>
> And is that even the case ?
>
> Side note: I dont plan the use your answers to arguee w/ the author. It's more that conceptually I'm interested.

In theory, purity allows you to know that you're not dealing with side effects outside of what can be accessed via the function arguments, because it makes it so that you can't access global mutable state except via the function arguments. So, in theory, it helps you to reason about the code.

In practice though, I don't think that that's actually particularly useful. In well-written code, it's almost always the case that functions are conceptually pure and that when they can't actually be pure, it's usually because of reasonable stuff that doesn't actually make it harder to reason about the code. So, personally, I'm increasingly of the opinion that it was a mistake to add pure to D. It's very rare that it can actually be used for optimizations (since that requires that the types involved be immutable and that they be used in some fairly specific circumstances), and unless the code is doing stupid stuff, it doesn't realistically help you reason about the code even if it theoretically does.

Of course, if you have code that's constantly accessing global state, then you're going to have issues, and pure prevents that (at least insofar as you can't access that state except via the function arguments), but in practice, most programs simply don't do that precisely because it makes the code difficult to reason about and maintain.

I've often found that in projects where I've tried to use pure, I've ultimately ended up needing to remove it because of some stray type whose functions can't be pure because of perfectly good reasons that don't make it harder to reason about the code. And I don't think that I've ever actually seen any practical benefit from pure when I have been able to use it. So, if we were creating D today - or if we were seriously looking at reworking the attributes that we have - pure is one of those where I'd argue that it should be on the chopping block simply because even though it's theoretically of value, in practice, it really isn't. And since pure code can't call impure code, it can easily balkanize code bases to have pure be a thing.

- Jonathan M Davis



April 16
On 4/16/24 17:07, Basile B. wrote:
> Short story for the context : someone has recently proposed the concept of purity for FreePascal, and only for their own dialect (aka _ObjFPC_). The proposition is to "check purity only when optimizations are enabled, because essentially the point of purity is only to optimize more" (think CTFE, think memoization).
> ...

Well, that is awful reasoning, but many language designers fall into the non-orthogonality trap due to a lack of imagination.

In contrast, D properly separates debug builds and optimized builds. (Within `debug` statements, `pure` is not checked.)

> But [I fail to explain the opposite](https://gitlab.com/freepascal.org/fpc/source/-/merge_requests/645#note_1863564617). How is purity a useful concept if not leading to specific optimizations ?
> 
> And is that even the case ?
> 
> Side note: I dont plan the use your answers to arguee w/ the author. It's more that conceptually I'm interested.

Purity enables reasoning based on determinism and commutativity and it implies that the involved data structures can have multiple instances.

Optimizations are one application of this improved capability for abstract reasoning.

(Of course, unfortunately in D determinism of `pure` functions is not properly ensured at the moment.)
April 17

On Tuesday, 16 April 2024 at 15:07:34 UTC, Basile B. wrote:

>

How is purity a useful concept if not leading to specific optimizations ?

And is that even the case ?

For me, the main purpose of pure is to distinguish if a statement like

foo();

is valid code or not.
For a pure function this is a bug, as it has no (side)effect. For a non-pure function it may be valid even if the return type is not void.

April 22

On Tuesday, 16 April 2024 at 15:07:34 UTC, Basile B. wrote:

>

Short story for the context : someone has recently proposed the concept of purity for FreePascal, and only for their own dialect (aka ObjFPC). The proposition is to "check purity only when optimizations are enabled, because essentially the point of purity is only to optimize more" (think CTFE, think memoization).

But I fail to explain the opposite. How is purity a useful concept if not leading to specific optimizations ?

And is that even the case ?

Side note: I dont plan the use your answers to arguee w/ the author. It's more that conceptually I'm interested.

In regards to the type system, depending on parameters, the result of a pure function may be assumed unique, which allows it to implicitly convert to immutable. (For an impure function, looking at the signature only, one cannot be determine if its result is unique as it could just return some mutable global.) This means that a pure function can build a structure containing indirections and whatnot and you, the receiver, may decide that it won’t be changed and therefore be treated as immutable (not just const), which in turn can either aid you in reasoning about your code and enable optimizations.