Getting the const-correctness of Object sorted once and for all

era scarecrow rtcvb32 at yahoo.com
Wed May 23 13:43:51 PDT 2012


On Tuesday, 15 May 2012 at 21:18:11 UTC, Chad J wrote:
> On 05/15/2012 03:32 PM, Chris Cain wrote:
>> On Tuesday, 15 May 2012 at 18:07:12 UTC, Chad J wrote:
>>> An idea I thought of is to introduce a method local 
>>> declaration that
>>> allows a method to access instance-specific-state that isn't
>>> accessible to the rest of the class:
>>
>> This is an interesting idea (as it seems to really try to keep
>> the state changes internal to the function, which can be seen  
>> as
>> how D handles purity)... however, it breaks the point of 
>> purity due to
>> this:
>>
>> pure nothrow hash_t toHash() const {
>> @instance hash_t bad = 0;
>> ++bad;
>> return hashfn(field) + bad;
>> }
>>
>> Now it violates everyone's definition of purity and we can no
>> longer make our sweet optimizations and reasoning about the  
>> code.
>> Sure, we could "trust the programmers to not do this" ... but
>> that's another debate entirely.
>
>
> Yes.  I intend to "trust the programmers to not do this".
>
> Otherwise we need to find some way to ensure that a function 
> that alters external state will always return the same value as 
> long as the rest of the program doesn't change the state it 
> looks at.
>
>>
>> ... and setting toStringCacheValid to true in toString violates
>> const, so this is absolutely not allowed. Sorry.
>>
>
> Yep, ya got me.
>
>>
>> Maybe there's a solution, but I doubt the solution is something
>> the programmer can/should do completely transparently.

  I think I have an answer. It came to me last night when I was 
going to sleep. Anyways, it may be a little verbose but I Hope I 
got it all right. Oddly enough it stays within D's own rules :)

--

import std.stdio;
import std.conv;

struct CachedHash(T) {
   T element;
   uint hash;
   alias element this;

   this(T inVal) {
     element = inVal;
   }

   @property uint toHash(){
     if(!hash) {
       writeln("Hashing!");
       hash = element.toHash();
     } else
       writeln("From Cache!");
     return hash;
   }
}

uint toHash(string x){
   return 123456; //for example
}

class AString {
   string str;

   this(string s) {
     str = s;
   }

   const uint toHash(){
     return 123456;
   }
}

uint calledHash(T)(T as){
   return as.toHash();
}

int main() {
   immutable char[] s = "this is a test!";

   auto ch_s = CachedHash!string(s);  //since s is inherently 
immutable..

   writeln(s);
   writeln(s.toHash, "\n");

   writeln(ch_s);
   writeln(ch_s.toHash);
   writeln(ch_s.toHash, "\n");

   AString as = new AString(s);
   immutable AString ias = cast(immutable AString) new AString(s);

   auto as_s = CachedHash!AString(as);
   auto ias_s = CachedHash!(immutable AString)(ias);

   writeln(as.toHash, "\n");
   writeln(as_s.toHash);
   writeln(as_s.toHash);
   writeln(ias_s.toHash);
   writeln(ias_s.toHash, "\n");

   writeln(calledHash!AString(as_s)); //non-CachedHash aware 
simulate
   writeln(calledHash!(typeof(as_s))(as_s));

   return 0;
}




More information about the Digitalmars-d mailing list