Oskar's const proposal

Bill Baxter dnewsgroup at billbaxter.com
Fri Jan 4 19:51:32 PST 2008


Oskar Linde wrote:
 > Walter Bright wrote:
 >> Janice Caron wrote:
 >>> On 12/28/07, Walter Bright <newshound1 at digitalmars.com> wrote:
 >>>> Janice Caron wrote:
 >>>>> y is a /copy/ of x, and clearly it should be possible to make a copy
 >>>>> of a const thing and have the copy be mutable.
 >
 > *BEEP* Confusion warning: you mean *constant*, not "const". Huge
 > difference. :)
 >
 >>>> That doesn't work for structs or classes.
 >>>
 >>> It doesn't? For structs
 >>>
 >>>     struct S {}
 >>>     const S x;
 >>>     auto y = x;
 >>
 >> Imagine you have:
 >>     struct S { int* p; }
 >> Because const is transitive, const(S) implies that now p points to
 >> const. But if you strip off the const in the assignment, you've lost
 >> the const-ness of p, and now you have a gaping hole in the
 >> const-correctness.
 >
 > The problem with the current const in D is the lack of orthogonality. As
 > far as I can see, those problems would be solved by my orthogonal const
 > proposal posted earlier. Constant values (such as structs) are by their
 > nature always implicitly convertible to mutable values (worst case: just
 > make a copy).
 >
 > The problem with the current const iteration is that there is no way to
 > separate the orthogonal concepts constness (as in constants) from
 > read-only access of references.
 >
 > Also, as far as I can see (not very) there would also not be any need
 > for a third type of constant (the manifest one).
 >
 > const int x = 5;
 >
 > could behave like a template and only be instantiated when the address
 > of x is taken.
 >
 > The result would be a const design, equally powerful but without
 > spoiling the beauty and simplicity of the D1.0 const. In D1.0, when
 > something is *constant*, you simply declare it as const:
 >
 > struct T {
 >     const int a = 5;
 >     int b;
 > }
 >
 > static assert(T.sizeof == int.sizeof);
 >
 > No need to stop and think. In D2.0 it seems like you have to go through:
 > "Hmm, this value will never change. I will mark it as const.... no wait
 > invariant... or maybe manifest constant using the enumeration hack?"
 >

(Referring to http://www.csc.kth.se/~ol/const.pdf in comments below that 
mention "your proposal")

I think everyone has trouble seeing how your const proposal fixes the 
tricky issues.  You give some syntaxes but don't show how they solve the 
problems that have caused all the consternation (!) over the past year 
that arise when you start pulling on the string.  Also your comparison 
table doesn't include structs, which seems a big omission since structs 
often end up causing the trouble with const proposals.  Also it would be 
helpful if your table gave an brief description of the behavior of each 
row: like "in int*: the pointer can be modified but the int cannot via 
this pointer"

But anyway, if I understand from the brief description, the idea is 
basically to use "const" to apply to values only and to mean the value 
will not change, period, no way, never.  And you use 'in' exclusively 
for things that can refer to other memory to say "you can't change what 
it refers to through this reference".

Ok, that sounds pretty neat.

So first question is: what happens when you use "in" on a plain int?  It 
isn't a reference of any kind so is "in int" an error or a no-op?

Does it have to be "const const(int)*"?  Seems like that should be the 
same as "const(int*)".  It's unclear in your proposal how const and in 
are scoped.

I see some potential messiness given a pointer variable t of type 'T' 
determining whether I can modify what it points to or not.  As far as I 
can tell, T can come in 3 non-modifiable flavors:
* "in S*" (readonly ref to mutable S),
* "in const(int)*" (readonly ref to immutable S),
* and "const(int)*" (mutable ref to immutable S)
So i'd need to check if either "typeof(*t) is const" or "typeof(t) is in".

It also seems syntactically rather complex.  Every reference type have 
both "in"-ness and "const"-ness, right?  I take it both things are 
transitive?, so I can't have a const pointer to mutable pointer to const 
value.  But even then If I have int****** how do I say it's 'in' from 
two levels down and 'const' from level 4 on down?  in(const(int**)**)**.

I guess I don't really understand why you'd ever have "const" appear 
twice in a declaration as you do for a couple of cases in your table. 
Both 'const' and 'in' I can see, but not const twice.  Or are you trying 
to have tail const?

Hope my questions are clear enough to you and give you some insight into 
what parts of your proposal people find difficult to understand.

--bb



More information about the Digitalmars-d mailing list