Logical const

Fawzi Mohamed fawzi at gmx.ch
Thu Dec 2 03:26:48 PST 2010


On 1-dic-10, at 04:52, Jesse Phillips wrote:

> Fawzi Mohamed Wrote:
>
>> The thing is that a lazy structure is very useful in functional
>> programming.
>> A lazy evaluation is something that should be possible using pure and
>> immutable.
>> I find it jarring that to do that one has to avoid D pure and  
>> immutable.
>
> Don't know what you mean by this.

a lazy list (for example one that list all natural numbers) cannot be  
immutable, without the possibility of a backdoor because all the  
"next" elements will have to be set at creation time.
(Lazy structures can be seen as memoizing a value produced by a pure  
function forever (i.e. never forgetting it).

>> To be able to safely use pure and immutable as I said one would need
>> some idioms that are guaranteed to be non optimized by the compiler.
>> for example casting a heap allocated type should be guaranteed to
>> remain modifiable behind the back:
>> auto t=new T;
>> auto t2=cast(immutable(typeof(t)))t;
>>
>> auto tModif=cast(typeof(t))t2; // the compiler has not moved or
>> flagged the memory of t, so one can modify tModif.
>
> This code is valid, the requirements placed on cast will not allow  
> it to move the data. Even types declared to be immutable my be  
> modifiable when cast to Unqual!(T), but the compiler can not  
> guarantee these.
>
> If I am wrong, please let me know why.

The code works now, I would like some assurance that  
cast(immutable(T)) doesn't do fancy stuff (or some equivalent way to  
ensure that *some* idiom will remain allowed.
If you think about it already now with opCast you cannot really know  
what opCast does, so a compiler would be allowed to return an  
immutable copy, or (if it uses whole pages) make the whole memory as  
read only.

>> clearly this is unsafe and it is up to the implementer to make sure
>> that the object is really logically const
>> and no function will see the internal changes.
>
> Yes, and I don't think compiler support adds any more guarantee than  
> casting those you want to modify in a const function. This Mutable  
> struct is supposed to help verify only modifiable data is cast:
>
> https://gist.github.com/721066

you example has an error in parallel, this is a good example of why  
the casting away should not be made convenient, and a user should just  
use well tested library code (for example dong thunk evaluation), that  
might be in a special type or mixed in.

You cannot have separate flag, and value without any synchronization,  
as other threads could see their value in a different order, so they  
could see dirty=false, but still no determinant.

This is somehow related to dataflow variables that can be set several  
times, but only to the same value (and indeed with a lazy list one can  
allow two threads to calculate the next element, but then only one  
should set it (using atomic ops to avoid collistions).
I have implemented DataFlow variables (but using the blip  
paralelization, that delays a task that waits, and resumes it when the  
value is ready, not with a thread lock) in
	https://github.com/fawzi/blip/blob/master/blip/parallel/smp/DataFlowVar.d
using D1


> I've taken many example use-cases for logical const and added them  
> as unittests. I think it is fairly reasonable if I could just get an  
> answer to my question about concurrency and declaring immutable types.
>
>> This is something that should be done sparingly, probably just in
>> library code implementing lazy evaluation or memoization (but code
>> that might be mixed in).
>
> Could you give an example of how lazy evaluation is achieved by  
> modifying state?

lazy structures need to modify the state (as I showed with the linked  
list example), lazy evaluation alone does not need to modify the state  
(and is indeed possible in D), but the storing/memoizing of the result  
needs it. To say the truth in D memoizing can be done with a static  
variable, but think about making the singly linked list like that, and  
you should immediately see that if gets *very* inefficient.


More information about the Digitalmars-d mailing list