Oskar's const proposal
Oskar Linde
oskar.lindeREM at OVEgmail.com
Sat Jan 5 04:23:13 PST 2008
Bill Baxter wrote:
> 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.
I can't say it fixes all tricky issues, and since I have no full grasp
of what all the tricky issues are I regret calling it a proposal. Let's
just consider it a thought experiment.
> 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"
More on that below.
> 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.
It does, doesn't it? My main gripe with the design of the current const
is that the meanings of invariant and const are too overlapping
(non-orthogonal if you wish). A plain int can have three different types:
int
const int
invariant int
Where the latter two are almost (but not fully) identical. There are
other ways to resolve this, but for now I will focus on orthogonalizing
the concepts.
Plain old data would only come in two flavors: variable and constant.
The "plain" data types are:
* all primitive non-reference types (int,float,char,...)
* structs and unions containing only plain data types.
> 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?
Both behaviors are possible, but I think making it a no-op is the most
helpful one. The result in either case is that nothing could ever have
the type "in int".
> 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.
If const only applies to the actual data without imposing any
contractual limitations on what may be done with eg. a copy of the data
we gain the neat effect of always having const T implicitly convertible
to T. From this also follows that const (as opposed to in) has to be
intransitive which is why I wrote "const const(int)*".
We could also consider a design where constness imposes contractual
limitations on the data, eg. making const fully transitive, but we would
lose the implicit const T => T conversion. This is outside the scope of
this thought experiment, but nevertheless leads down some interesting
paths. (*)
> 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".
The "in" attribute of a reference could be implicit from having a
reference to constant data. So
typeof(const(T)*) == in const(T)*
and you'd only need to check the in attribute of the type to know if you
can modify what it refers to.
Regarding in and structs, I think it is advantageous if
T[] and
struct Slice(T) { T *ptr; size_t length; }
behaved identically with respect to a const T and an in type attribute
which would have certain implications.
> Hope my questions are clear enough to you and give you some insight into
> what parts of your proposal people find difficult to understand.
Thank you for the questions. They were good, although not as tricky as I
feared (there exists tricky ones). :) I hope I managed to answer them
and bring some clarity on the topic. At least, I hope this may
possibilities forward for the current debacle.
--
Oskar
More information about the Digitalmars-d
mailing list