constness for arrays

Reiner Pope reiner.pope at gmail.com
Wed Jul 19 02:40:17 PDT 2006


Andrew Fedoniouk wrote:
> Dynamic constness versus static (compile time) constness is not new.
So what?

> In case of runtimes like D (natively compileable) such control is not an
> option.
What do you mean by this? The runtime itself doesn't need to be able to 
control the code, as we know, such control could be forced at compile 
time. As to the fact that the runtime could be subverted, well, since we 
have assembly in D, static const can similarly be converted. If speed 
issues are the concern, read on.

> I beleive that proposed runtime flag a) is not a constness in any sense
What about the sense that illegal write operations to readonly arrays 
could be caught in debug builds? That effectively ensures that the 
arrays are kept *constant*, doesn't it?
> b) does not solve compile verification of readonlyness and
There seem two main arguments for compile time verification of 
readonlyness: speed and certainty. For reasons outlined below, speed is 
actually likely to be _greater_ with runtime const than with 
compile-time const. As for certainty, readonlyness is just one of many 
bug-catching mechanisms. Others include:
   - Design by Contract (pre- and post- conditions and invariants)
   - Unit testing
   - Typing mechanism (partial type safety)
   - Array bounds checking
   - GC (catches memory and type-safety errors)
All of these checking mechanisms other than type safety are implemented 
at runtime, yet there is not too much debate about that fact, even 
though they *could* be checked for at compile time, using theorem 
proving, (see http://en.wikipedia.org/wiki/SPARK_programming_language 
for a programming language that does this). The fact that they are 
checked at runtime means that, like runtime const-ness, the certainty of 
static checking isn't present. However, it still many more bugs to be 
caught than no const system at all, and I would even go so far as to say 
that it would catch *most* const violations if combined with good unit 
tests.

The main advantage of runtime checking is flexibility/speed, as well as 
no 'const-pollution', as xs0 put it.

You get the speed gains from avoiding all unnecessary duplications, a 
feat which simple (a la C++) static const-checking can't achieve. 
Imagine that we had a static const-checking system in D:

const char[] tolower(const char[] input)
// the input must be const, because we agree with CoW, so we won't change it
// Because of below, we also declare the output of the function const
{
   // do some stuff
   if ( a write is necessary )
   { // copy it into another variable, since we can't change input (it's 
const)
   }
   return something;
// This something could possibly be input, so it also needs to be 
declared const. So we go back and make the return value of the function 
also a const.
}

// Now, since the return value is const, we *must* dup it whenever we 
call it. This is *very* inefficient if we own the string, because we get 
two unnecessary dups. This is a big price to pay just to keep static 
const-checking.


> c) can be implemented now by defining:
> struct vector
> {
>     bool readonly;
>     T*  data;
>     uint length;
> }
Yes and no. It can be implemented like that because that would 
effectively copy exactly what an array does already, but a) it takes up 
more memory than what xs0 proposed, and b) it isn't supported natively 
by the language's arrays, so it is less likely to be used.

> 
> Declarative contness prevents data misuse at compile time
> when runtime constness moves problem into execution time
> when is a) too late to do anything and b) expensive.
a) Testing, especially when assisted by unit testing and the code 
coverage tool included in DMD, should pick up most, if not all, of the 
const violations in your code, when you still do have a chance to do 
something about it. It's impossible to rely on the compiler to pick up 
all your bugs in any situation.
b) It's not expensive, because it avoids unnecessary duplications and 
there should be a compiler switch to turn of the readonly checks in 
release builds, once you're sure of safety. xs0 covered the costs and 
concluded they weren't many.

> I would mention old idea again - real solution would be in creating of
> mechanism of disabling exiting or creating new opertaions
> for intrinsic types.
> 
> For example string definition might look like as:
> 
> typedef  string char[]
> {
>     disable opAssign;
>     ....
>     char[] tolower() { ..... }
> }
While this could be a useful tool, using this as a form of 
data-protection is just WAY TOO inflexible, and it removes the areas 
where D's string (and array) processing is so powerful.



Cheers,

Reiner



More information about the Digitalmars-d mailing list