What's wrong with just a runtime-checked const?

Bruno Medeiros brunodomedeirosATgmail at SPAM.com
Wed Jul 26 14:51:15 PDT 2006


xs0 wrote:
> 
>> Ok, I'm not following you guys. Can you explain from scratch what it 
>> is you were trying to achieve (the purpose of the function?), which 
>> when done with static const checking causes unnecessary dups?
> 
> It's really simple. Say you have a function that sometimes modifies its 
> data and sometimes doesn't. The non-const version is simple, as it's 
> allowed in-place modification:
> 
> byte[] filter(byte[] data)
> {
>     if (...)
>         data[0] = 10;
>     return data;
> }
> 
> Now, whenever you have const data, you can only use it by duping:
> 
> const byte[] data = foo();
> byte[] filtered = filter(data.dup);
> 
> That's bad, because you always have to .dup the data, even if filter() 
> does nothing with it. So, you also write a const version:
> 
> const byte[] filter(const byte[] data)
> {
>     if (...) {
>         byte[] result = data.dup;
>         result[0] = 10;
>         return result;
>     }
>     return data;
> }
> 
> That's much better, because a copy is only made when needed. However, 
> there's still a problem - the return type must be const, because you 
> need to be able to return the original (const) parameter. Therefore, the 
> information about whether a copy is made is lost.
> 
> With a single function that's not even a problem, but say your filtering 
> is configurable and you call 20 filters. If you use the const versions, 
> 20 copies will be made, even though only one is necessary. If you use 
> the non-const versions, you're forced to dup before the first filter,
> even when not necessary at all.
> 
> A similar problem occurs in this case:
> 
> const char[] handleDesc()
> {
>     if (_handle) {
>         return format("Handle #%d", _handle.id());
>     } else {
>         return "No handle";
>     }
> }
> 
> Because you sometimes return a literal, you must declare the result 
> const, even though you'll return a fresh writable char[] most of the 
> time, which may or may not be significant. Alternatively, you can .dup 
> the literal before returning it, but it will usually be a wasted .dup..
> 
> In both cases, the problem is the same - there is no way for the 
> function to return information about whether a copy was made along with 
> the data itself. It can't even neatly be solved by wrapping the thing in 
> a struct or checking equality of references, because the type in either 
> case is static and one way or another, you'll have to work around that 
> (by casting or whatever)
> 
> 
> xs0

Ah, I understand the objective now.

But then, this problem you are trying to solve here is one of 
performance only, related to ownership management, but not necessarily 
the same. In particular:

* Whatever mechanism is made to deal with that problem, cannot be 
disabled in release builds: it is not a contract, unlike const/ownership 
checking which is a contract, and being so can be checked at compile 
time, or at runtime in debug releases only.

* For that same reasons, such mechanism should not be a substitute for 
const/ownership checking, since this latter one can be processed at 
compile time, which is naturally more efficient, and the former one can't.

* Such mechanism is likely impractical or too hard to implement in the 
general sense (that is, for any data type). So perhaps the mechanism 
should be implement not by the language/compiler, but by the coder with 
existing language constructs (mixins, etc.)?

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



More information about the Digitalmars-d-learn mailing list