Purity

Don nospam at nospam.com
Sat Dec 18 12:00:47 PST 2010


spir wrote:
> On Sat, 18 Dec 2010 13:46:11 +0100
> Don <nospam at nospam.com> wrote:
> 
>> spir wrote:
>>> On Sat, 18 Dec 2010 01:08:20 -0800
>>> Jonathan M Davis <jmdavisProg at gmx.com> wrote:
>>>
>>> Thank you for the explanation about strongly pure funcs calling weakly pure ones --this fully makes sense.
>>>
>>>>> I would like weakly pure to include output funcs, and exclude all
>>>>> possibilities to modify (non-local) state.  
>>>> The problem is that output is accessing global variables - which weakly pure 
>>>> functions _cannot_ do.
>>> Why? What is the rationale for excluding output (I don't mean I/O, only O)?
>> You're correct in saying that it doesn't affect the operation of the 
>> program. But in practice, program output is almost always important.
>>
>> For example, suppose we allowed output to be pure. Then consider:
>>
>> writeln("Hello, world!");
>>
>> Since it returns nothing, and has no influence on the future execution 
>> of the program, the writeln can be dropped from the program.
>>
>> Hmmm....
> 
> For sure, if you specify (in the compiler behaviour) that the only purpose of a pure function is to return something. 

Yes, that's what's done.

> Which excudes all "action-fonctions" (= funcs which purpose is to perform an effect). 
> But why should the compiler rewrite of such a func be to erase it? Just let it alone, it won't bother anybody. 

But if you do that, you lose most of the benefits of pure.
 >And can safely be qualified as pure. So that, transitively, pure funcs 
can call funcs that perform output. Just what we want.

You could do this -- but in order to preserve the usefulness of pure, 
you'd need to introduce some way of flagging such functions. The 
signature would need to indicate that it is a "action function".

> 	pure Report getReport (Data data) {
> 	    // compute report from data (only)
> 	    log.write(report);
> 	    writefln("report computed:\n\t%s", report);   // debug
> 	    return report;
> 	}
> 
> Anyway, aside practicle & efficiency purposes, 

> I'm even more annoyed by the "conceptual wrongness" of excluding functions that perform output from the "world of purity" ;-)
 > I would want them included even if this did not buy anything.

I think you're assuming that including them costs nothing. But it does.
Including such functions destroys most of the benefits of pure. You do 
need to treat them differently.


> All of this would be easier and clearer if D made a proper distinction between 'true' functions (that compute a result) and 'action-functions' (that perform an effect). The actual purity criteria need not be the same:
> * actions must not write to state
> * functions must not read from state
> Just state: output ports and memory do not belong to program state, and we're done.

Definitely you could do this. I suspect that it wouldn't be worth it, 
though, because action functions are viral. Once a function is an action 
function, everything which calls it is also an action function.
And from an optimisation perspective, there isn't much you can do with 
action functions.

> There is an asymmetry: runtime/variable data input (from user, file,...) must be considered as state, else a compiler cannot memoize function results.

It also can't memoize the results of functions which call action functions.


But aside from all of this, I'm actually rather sceptical that output 
can be done without using static variables. I cannot imagine how it 
could be done.

It is an interesting point, that is particularly obvious at a low level. 
For example, in DOS text mode, writing 'a' to 0xB000 wrote an 'a' in the 
top left corner of the screen, even if the function never reads that 
address. But writing 'a' to 0x5000 is not output!
Currently, a pure function cannot write to _any_ static variable. This 
disallows a few obscure functions which could be considered to be 
logically pure.

Ultimately, I think your definition of 'pure function' would be: never 
reads from a static variable, and never writes to a static variable 
which is ever read by another function;
and 'pure action function' would be: writes to an output port, or to a 
never-read static variable which is designated as an output.

Again, although this could be done, I doubt that it's worth it. The 
costs seem high and the benefits low.


More information about the Digitalmars-d mailing list