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