const

Walter Bright newshound1 at digitalmars.com
Fri Mar 28 18:21:41 PDT 2008


Benji Smith wrote:
> I'm still not convinced that whether or not a function modifies its 
> argument values has anything to do with the type system.

It has to travel along with the types in a manner that is 
indistinguishable from being part of the type system, so it might as 
well be. We did initially try to keep them separate; that didn't last long.

> At the very 
> least, it only applies to the function's type, not the types of the 
> arguments.

That's correct. The argument types must be implicitly convertible to the 
corresponding parameter types.


> The automatic casting of arguments to const, for no purpose other than 
> to satisfy the type system, feels wrong to me. With one hand, you're 
> creating a restriction in the type system, and with the other hand, 
> you're creating a loophole in the type system that only applies to this 
> specific case. I can feel occam's razor prickling at my brain, and it 
> doesn't sit well with me.

By a loophole I infer there's something unsound going on. But I don't 
see what it is you're referring to.


> Just because a function promises not to modify its argument doesn't mean 
> the function can only accept an immutable value. It should accept any 
> value at all, without discriminating based on mutability.

It does, that's the point of the const qualifier. All types are 
implicitly convertible to const.

> In fact, the 
> mutability of the arguments only matters *within* the function (and 
> further down the call stack). To me, that sounds more like a storage 
> class (or some other type of declaration modifier).
> 
> But even putting aside the type-system for a moment, I still think that 
> much of the emphasis of const-correctness is misdirected.
> 
> Asking a method or function to document which arguments it *DOESN'T* 
> modify is a lot like asking the police to keep a detailed record of all 
> law-abiding citizens, as a roundabout way of tracking down criminals. Or 
> calling the doctor everytime you're not sick, so that he can set an 
> appointment for you whenever you don't call.

It's a reasonable position to take that parameters are const by default, 
and must be explicitly marked as mutable in order to change them. The 
horrible problem with that, however, is that it will work in the reverse 
way that other declarations work. It's inconsistent in a very perverse way.



> What about a special syntax 
> to denote all functions that don't throw exceptions?

There is a proposed one: nothrow.

> 
> Wouldn't it make more sense to annotate *MUTABILITY* of function arguments?
> 
> Otherwise, you end up with a bunch of 'const' clutter all over the place:
> 
>    int str_search(const(char[]) needle, const(char[]) haystack,
>       const(char)* start, const(char)* end);
> 
> Egads. It's a nightmare.
> 
> Isn't this code better, in nearly every way?
> 
>    int str_search(char[] haystack, char[] needle, char* start,
>       char* end);
> 
> At a quick glance, I can see that this function is not going to modify 
> any of its arguments (since none of them are marked as 'mutable'), so I 
> can pass any values I want. The function doesn't care whether it 
> *receives* mutable or immutable values, since it's not going to mutate 
> them one way or the other.
> 
> On the other hand, I might have a function declared like this:
> 
>    void str_replace(mutable char[] haystack, char[] needle,
>       char[] replacement, char* start, char* end);
> 
> In this case, there's only one argument that might be modified by the 
> function. Any caller of this function must ensure that the 'haystack' 
> variable provides a mutable view. The other argument values remain 
> unrestricted, so the caller of this function only has to fuss about with 
> one restriction.
> 
> It's easier on the brain that way.
> 
> What if, as a library author, I forgot to mark the haystack variable as 
> mutable? Or if my code accidentally modifies the contents of one of the 
> other variables?
> 
> As soon as I touch the data in that array, the compiler should throw a 
> huge tantrum.
> 
> Shazzam! Const-correct!
> 
> And unlike the ever-so-common casting away of "const-ness", casting away 
> mutability should be completely impossible.
> 
> Under the current regime, the prototype of this method is quite a bit 
> more bulky:
> 
>    void str_replace(char[] haystack, const(char)[] needle,
>       const(char)[] replacement, const(char)* start, const(char)* end);
> 
> Resenting all that extra typing, I'm likely to get lazy and leave off a 
> few of those const modifiers. Either out of my trademark forgetfulness, 
> or just because I'm a spiteful person:
> 
>    void str_replace(char[] haystack, char[] needle, char[] replacement,
>       char* start, char* end);
> 
> Now the compiler is hamstrung. It can't enforce anything. I can change 
> the values of any argument without a single warning message.

You will get an error if you try passing a string to that function.

> 
> So much for const-correctness.

I agree with some of the awfulness of the syntax. That's where 'in' 
comes in:

void str_replace(in char[] haystack, in char[] needle, in char[]
     replacement, in char* start, in char* end);

Not perfect, but not so awful. You should also be using string's instead 
of char[], as they are invariant and you don't need to annotate string 
parameters.


> There's nothing special about a value not changing (at least, not for 
> function arguments), so programmers should't be burdened with annotating 
> the mundane case. Mutability of function arguments is much more 
> interesting.
> 
> Labeling function arguments as mutable would, in my opinion, provide a 
> *stronger* const regime, while simultaneously producing less pointless 
> code clutter.

As this has come up before, I added it to const(FAQ):

http://www.digitalmars.com/d/2.0/const-faq.html#const-parameters

> As for 'invariant' data (and its relocation to read-only memory or 
> whatever), my opinion is: let the compiler do whatever optimizations it 
> wants. I'd rather declare that kind of data as "const", and if the 
> compiler can figure out that a pointer to the data is never taken, then 
> it can burn the value into silicon as far as I care.

I don't want the compiler to figure out that I never took a mutable 
pointer to it, I want the compiler to *prevent* me from taking a pointer 
to it by mistake.


> (Incidentally, when I started this thread, I meant no disrespect toward 
> Walter or Andrei or anyone else for the massive amount of excellent work 
> that they've done. I just wanted to register a few opinions about 
> choices that make the language somewhat less appealing to me.)

Thank you, and I never took your comments any other way. In fact, I'm 
glad you took the time to put them to paper.


> Thanks, everybody, for listening. I've read all the replies so far, and 
> I have a few other things I'd like to say about strings and arrays and 
> whatnot, but this post reflects the entirety of my current thinking 
> about const.

I'll look forward to it.



More information about the Digitalmars-d mailing list