YACP -- Yet Another Const Proposal

Bruno Medeiros brunodomedeirosATgmail at SPAM.com
Wed Aug 9 09:27:41 PDT 2006


Reiner Pope wrote:
>>> *3. rocheck*
>>>
>>
>> I haven't read that part of the paper yet, but I think I get a good 
>> enough picture from your description.
>> And I think rocheck wouldn't fit well with D, due to the runtime 
>> checks and performance penalties, which, like you said, could not be 
>> disabled in release builds (as they are not contracts). Also, it would 
>> only work with classes, and not any kind of type.
>> (You have an example where you have a "rocheck char[]" variable, how 
>> would that work internally?)
> This isn't in the paper. It's my idea, arising from some of the problems 
> with getting CoW to work properly. Consider:
> 
> char[] /*someCOWFunction*/ foo(char[] input) {}
> char[] /*Also COW*/ bar(char[] input) {}
> char[] /*Also COW*/ bam(char[] input) {}
> 
> foo(bar(bam("hello world")));
> 
> Each of them would ordinarily duplicate the string if a modification is 
> required. However, a maximum of 1 is needed in real life, because no-one 
> owns the intermediate copies. So there needs to be some way to know at 
> runtime whether the array reference is readonly or not, because if it is 
> mutable, then the function would be best advised to modify it in-place. 
> That's what rocheck is for. However, in my proposal, it is both:
> -statically verifiable as correct
> -devoid of runtime checking
> 
> this is because the mutating methods can only be accessed via the 
> ensureWritable() method generated by the compiler, so a correct COW 

It is not entirely devoid of runtime checking, since it envolves calling
.ensureWritable() .

> function would look like this:
> 
> rocheck char[] capitalizeAllIfFirstLetterIsLowerThenRunBar(rocheck 
> char[] input)
> {   if (isLowerCase(input[0]))
>     {   /*mutable*/ char[] modified = input.ensureWritable();
>         foreach (inout c; modified)
>         {   c = makeUpper(c);
>         }
>         input = modified;
>     }
>     bar(input);
> }
> 
> So in this function, it is clearly const-safe as well as only doing one 
> check in the entire function (the call to ensureWritable). This means 
> that, although there is a memory cost added to the array reference, 
> there is actually a runtime saving because of the avoidance of 
> duplications. Additionally, since using this requires a special keyword, 
> it will only be used where the memory/speed tradeoff is deemed 
> worthwhile by the programmer (however, I recommend that it is used for 
> any COW function).
> 

Hum. Well, a template version of rocheck can be done already (with or 
without const), and it isn't that much worse from the in-language 
version: (the code may have some errors)

   struct rocheck!(T) {
     immutable T elem;
     bool writable;

     /*mutable*/ Type ensureWritable() {
       if (!writable) return cast(mutable) elem;
       else return elem.dup;
     }
   }

   // A rocheck caster/constructor
   rocheck!(T) asrocheck!(T) (T refval) {
     rocheck!(T) rochk;
     rochk.elem = refval;
     return rochk;
   }

   rocheck!(char[]) capitalizeEtc(rocheck!(char[]) input)
   {
     if (isLowerCase(input.elem[0])) {
       /*mutable*/ char[] modified = input.ensureWritable();
       foreach (inout c; modified) {
         c = makeUpper(c);
       }
       input.elem = modified;
     }
     bar(input);
     return input;
   }

   ...

   char[] mystr = "abc";
   auto str = capitalizeEtc(filter1(mystr.asrocheck));


The differences are that it is a bit more verbose to declare rocheck 
vars, and also you have to explicitly convert from non-rocheck to 
rocheck (what asrocheck() does). Other than that I think it works ok.

-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D




More information about the Digitalmars-d mailing list