www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Const Ideas

reply "Craig Black" <cblack ara.com> writes:
The 2.008 release is an improvement, but it seems like there is still a lot 
of dissatisfaction with the current const stuff.  Janice proposed an idea 
for constifying instance member functions using const(this).  I like that 
idea.  It is explicit and can be used as a prefix without ambiguity.  If we 
did this, I would suggest getting rid of the postfix syntax.

const(this):
void func1() { ... }
void func2() { ... }
void func3() { ... }

or

const(this) void func1() { ... }
const(this) void func2() { ... }
const(this) void func3() { ... }

This is both explicit and remedies the ambiguity between the instance 
pointer and the return type being const.

Another point that Janice makes is that it is confusing that const(X) isn't 
the same as const X.  To solve this problem, I propose using const(ref) to 
constify references.  This removes ambiguity and makes things explicit.

const X x;  // The data is const, the reference is mutable
const(ref) X x;  // The data is mutable, the reference is const
const(ref) const X x;  // Everything is const, nothing is mutable

-Craig 
Nov 30 2007
next sibling parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 11/30/07, Craig Black <cblack ara.com> wrote:
 Janice proposed an idea
 for constifying instance member functions using const(this).
That actually wasn't me. I like the idea (a lot), but I can't claim credit for inventing it. I did come up with the idea of extending it to const(identifier) though.
 If we did this, I would suggest getting rid of the postfix syntax.
I would certainly agree with that!
 const X x;  // The data is const, the reference is mutable
The problem I have with this is that I believe X should mean the same as (X). So if you accept that, const X x; must mean the same thing as const(X) x; And if you believe that const(...) has to mean "everything inside the brackets is const" (which is what I believe) then you have to conclude that const X x must mean "x is completely and absolutely const, and nothing about it is mutable". That's actually what it means right now (so long as you omit the brackets). That's why I argue that you need something else - something /outside the brackets/ - to mean "let the reference be mutable". (And obviously, that mechanism should only be available for reference types).
Nov 30 2007
next sibling parent "Craig Black" <cblack ara.com> writes:
"Janice Caron" <caron800 googlemail.com> wrote in message 
news:mailman.201.1196446640.2338.digitalmars-d puremagic.com...
 On 11/30/07, Craig Black <cblack ara.com> wrote:
 Janice proposed an idea
 for constifying instance member functions using const(this).
That actually wasn't me. I like the idea (a lot), but I can't claim credit for inventing it. I did come up with the idea of extending it to const(identifier) though.
 If we did this, I would suggest getting rid of the postfix syntax.
I would certainly agree with that!
 const X x;  // The data is const, the reference is mutable
The problem I have with this is that I believe X should mean the same as (X). So if you accept that, const X x; must mean the same thing as const(X) x; And if you believe that const(...) has to mean "everything inside the brackets is const" (which is what I believe) then you have to conclude that const X x must mean "x is completely and absolutely const, and nothing about it is mutable". That's actually what it means right now (so long as you omit the brackets). That's why I argue that you need something else - something /outside the brackets/ - to mean "let the reference be mutable". (And obviously, that mechanism should only be available for reference types).
I see the dilemma. So the probem with using const(ref) is that there would be no way to say that the data is const but the reference is mutable. This is also a limitation of the current implementation is it not?
Nov 30 2007
prev sibling parent "Craig Black" <cblack ara.com> writes:
"Janice Caron" <caron800 googlemail.com> wrote in message 
news:mailman.201.1196446640.2338.digitalmars-d puremagic.com...
 On 11/30/07, Craig Black <cblack ara.com> wrote:
 Janice proposed an idea
 for constifying instance member functions using const(this).
That actually wasn't me. I like the idea (a lot), but I can't claim credit for inventing it. I did come up with the idea of extending it to const(identifier) though.
 If we did this, I would suggest getting rid of the postfix syntax.
I would certainly agree with that!
 const X x;  // The data is const, the reference is mutable
The problem I have with this is that I believe X should mean the same as (X). So if you accept that, const X x; must mean the same thing as const(X) x; And if you believe that const(...) has to mean "everything inside the brackets is const" (which is what I believe) then you have to conclude that const X x must mean "x is completely and absolutely const, and nothing about it is mutable". That's actually what it means right now (so long as you omit the brackets). That's why I argue that you need something else - something /outside the brackets/ - to mean "let the reference be mutable". (And obviously, that mechanism should only be available for reference types).
We could also add mutable(ref), but I don't think mutable is even a keyword.
Nov 30 2007
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
I think the new const system makes sense. I think of variables as being
compile time pointers to memory (basically).

Furthermore, const() is like a compile time function that takes a type T and
returns type T that is now a constant.

const (no parenthesis) is telling the compiler something.

Similarly, import; tells the compiler to import a symbol table from a file,
whereas import("file") is a compile time function that reads in a file
and returns its data (just like std.read() but at compile time).

Henceforth, let CTF = 'compile time function'.


Thus:

int a;
Adds an entry to the compiler's variable table named 'a' that references
memory that is an int.

const(int) a;
Add an entry named 'a' that references memory that is a constant int. The
const() CTF takes the type int and returns a new type that is a constant int.

const int a;
Add a *constant* entry named 'a' that references memory that is a mutable
int.

const const(int) a;
Adds a constant entry named 'a' that references a constant integer.

Let's deconstruct that conceptually:
variable declaration := [mutability] type name;
Mutability is if the compiler's name entry can be changed (rebinded). It is
optional, and defaults to being mutable.

Type is the type of memory the variable references.

And name is of course the name.

In the above:
const is the mutability of the compiler's variable table entry.
const(int) is a CTF that returns a type - it is the actual type.
a is obviously the name.


Let's consider const(int) a; again.

a = 10; // the compiler sees this as rewriting its internal table:
// something like this: variableMap['a'] = &10;
// Of course, the address of an immediate is pretty silly, but it is consistent
// with thinking about, say, string literals.
// Let's just say the storage for a literal integer is optimized away later
// so the real program just sees immediates.

++a; // also rewriting the table:
// variableMap['a'] = &(variableMap['a'] + 1);

Once again, with strings, that makes more sense:

const(char[]) str = "hello";
// variableMap['str'] = &"hello";

str = replace(str, "hello", "world");
// variableMap['str'] = &what_replace_returns

The actual literal "hello" string pointed to is not changed, it is just
discarded, and may be left behind for the gc to collect later.


From a usability standpoint, I think the last case there of reusing variables
for string replaces is why I think I like the current system best:

string a = "hello";
a = replace(a, ...);

Just works, making me pretend I have in place replaces.

With the proposed const(char[]) making everything const, this would break.




-- 
Adam D. Ruppe
http://arsdnet.net
Nov 30 2007
parent Leandro Lucarella <llucax gmail.com> writes:
Adam D. Ruppe, el 30 de noviembre a las 13:38 me escribiste:
 int a;
 Adds an entry to the compiler's variable table named 'a' that references
 memory that is an int.
 
 const(int) a;
 Add an entry named 'a' that references memory that is a constant int. The
 const() CTF takes the type int and returns a new type that is a constant int.
 
 const int a;
 Add a *constant* entry named 'a' that references memory that is a mutable
 int.
But now you lost the idea of transitive constness (if your compile-time pointer is const, the value it points to should be const). This doesn't break your "model" if you think as if D works like Python, where int are inmutables, but you can rebind the variable (your compile-time pointer). Then: const int a = 1; means "I have a variable named 'a' that points to some int that has the value 1 and I can't change where it points to (I can't rebind it)". a = 2; is an error const(int) b = 1; means "I have a variable named 'b' that points to some int, conceptually the same int as 'a', because there is no need to have more than 2 inmutable ints with the same value in the program, but I can change where 'b' points to (I can rebind it).". so b = 2; is ok So graphically: +---+ a -> | 1 | <- b +---+ and after b = 2; +---+ +---+ a -> | 1 | b -> | 2 | +---+ +---+ Of course this is a "conceptual" model, otherwise there would not be value passing and must be a reference internall, which I think is not that efficient ;) This is basically what happens with pointers and the values they point to. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- Did you know the originally a Danish guy invented the burglar-alarm unfortunately, it got stolen
Nov 30 2007
prev sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Craig Black wrote:
 const(ref) const X x;  // Everything is const, nothing is mutable
One too many consts. I will not stand for any solution taht has "const" more than once in the declaration.
Nov 30 2007
parent reply "Craig Black" <cblack ara.com> writes:
"Robert Fraser" <fraserofthenight gmail.com> wrote in message 
news:fipn3b$j8n$2 digitalmars.com...
 Craig Black wrote:
 const(ref) const X x;  // Everything is const, nothing is mutable
One too many consts. I will not stand for any solution taht has "const" more than once in the declaration.
Right. I wasn't thinking straight when I proposed this as Janice pointed out. Simply const X x; will do the trick.
Nov 30 2007
parent reply "Craig Black" <cblack ara.com> writes:
"Craig Black" <cblack ara.com> wrote in message 
news:fipnds$ktf$1 digitalmars.com...
 "Robert Fraser" <fraserofthenight gmail.com> wrote in message 
 news:fipn3b$j8n$2 digitalmars.com...
 Craig Black wrote:
 const(ref) const X x;  // Everything is const, nothing is mutable
One too many consts. I will not stand for any solution taht has "const" more than once in the declaration.
Right. I wasn't thinking straight when I proposed this as Janice pointed out. Simply const X x; will do the trick.
I still like const(ref) though, but it doesn't solve the problem of allowing mutable references to const data. That would would still require something like const(X) x; Which brings us back to where we are already. Another idea is, mutable(ref) const X x; Which is convoluted. Also I don't think that mutable is a keyword anyway.
Nov 30 2007
parent reply "Janice Caron" <caron800 googlemail.com> writes:
Well, I'm still gunning for

    const (X)& x;

for mutable refs to const classes. Since I come from a C++ background,
& means "reference of" to me, and this reads straightforwardly as "x
is a reference to const X".

Of course, x would be a reference even /without/ the ampersand - such
is the nature of classes in D. But writing it explicitly allows one to
put it outside the brackets.
Nov 30 2007
next sibling parent reply "Craig Black" <cblack ara.com> writes:
"Janice Caron" <caron800 googlemail.com> wrote in message 
news:mailman.206.1196453000.2338.digitalmars-d puremagic.com...
 Well, I'm still gunning for

    const (X)& x;

 for mutable refs to const classes. Since I come from a C++ background,
 & means "reference of" to me, and this reads straightforwardly as "x
 is a reference to const X".

 Of course, x would be a reference even /without/ the ampersand - such
 is the nature of classes in D. But writing it explicitly allows one to
 put it outside the brackets
I now better understand why you proposed this syntax. I guess it's not so bad. I can't think of anything better.
Nov 30 2007
parent reply Jason House <jason.james.house gmail.com> writes:
Craig Black wrote:

 
 "Janice Caron" <caron800 googlemail.com> wrote in message
 news:mailman.206.1196453000.2338.digitalmars-d puremagic.com...
 Well, I'm still gunning for

    const (X)& x;

 for mutable refs to const classes. Since I come from a C++ background,
 & means "reference of" to me, and this reads straightforwardly as "x
 is a reference to const X".

 Of course, x would be a reference even /without/ the ampersand - such
 is the nature of classes in D. But writing it explicitly allows one to
 put it outside the brackets
I now better understand why you proposed this syntax. I guess it's not so bad. I can't think of anything better.
Technically, I proposed the syntax. Janice didn't like it at first but has now come full circle. I've had some second thoughts about stuff, but I'm still able to convince myself that a novel syntax for rebindable constant objects is best. Here's what I consider to be requirements: const(...) must mean that everything within the parens is constant "const X" and "const(X)" must mean the same thing Rebindable constant objects are important to have const(X) foo(){...} should mean that what it returns is constant. "non-rebindable const(X) x = foo();" should be allowed "rebindable const(X) x = foo();" should be allowed "const(X) foo(){non-rebindable const(X) x; return x;}" should be allowed "const(X) foo(){rebindable const(X) x; return x;}" should be allowed. From those requirements, "const(X) x;" must mean that x can not be rebound. Using "const(X)& x;" for a rebindable definition seems to be the best I can come up with. Do people disagree with any of the requirements I listed? Most are just sanity requirements, but may not have general agreement. Beyond that, is there a better for for a rebindable definition?
Nov 30 2007
next sibling parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 11/30/07, Jason House <jason.james.house gmail.com> wrote:
 Craig Black wrote:
 Technically, I proposed the syntax.  Janice didn't like it at first but has
 now come full circle.
That's right. I think my earlier attempt was something like "const(X)ref" or "ref const(X)". I came full circle and now fully support Craig's idea, largely because I think there may come a time in the future when D has C++-style references. If and when that day comes, "&" will be preferable to "ref" for the same reason that "*" is preferable to "ptr". If it's /only/ classes we're talking about, it's no big deal either way, but if referencing gets more ubiquitious in the future, less typing => better. So Craig gets the kudos for invention on this one. Nice one, Craig!
Nov 30 2007
next sibling parent reply Jesse Phillips <jessekphillips gmail.com> writes:
On Sat, 01 Dec 2007 06:35:46 +0000, Janice Caron wrote:

 On 11/30/07, Jason House <jason.james.house gmail.com> wrote:
 Craig Black wrote:
 Technically, I proposed the syntax.  Janice didn't like it at first but
 has now come full circle.
That's right. I think my earlier attempt was something like "const(X)ref" or "ref const(X)". I came full circle and now fully support Craig's idea, largely because I think there may come a time in the future when D has C++-style references. If and when that day comes, "&" will be preferable to "ref" for the same reason that "*" is preferable to "ptr". If it's /only/ classes we're talking about, it's no big deal either way, but if referencing gets more ubiquitious in the future, less typing => better. So Craig gets the kudos for invention on this one. Nice one, Craig!
Based off of what you said in my other post, Walter will not change D's transitivity, Craig's proposal violates this. As a lot of the discussion here has suggested a solution for having a const ref with mutable data. So if I am correct then the real problem becomes with, const(char)* foo == const(char*) foo const(char)* foo != const char* foo and thus const X x != const(X) x That is to say that const() means the reference can be rebound and const does not. In this case I will re-propose Adam's idea to explain it that const() returns a constant of what is inside. const TYPE * foo // *foo immutable, foo mutable const(TYPE) * foo // same as above const(TYPE *) foo // foo and *foo immutable, but foo can be rebound const(TYPE * foo) // nothing mutable, no rebinding of foo TYPE * const foo // Same as above It would appear this meets at least most of the complaints const() does not have a special meaning, everything can be achieved with one const keyword, transitivity holds, no ambiguity, everything in const() is const. The only problem is that it would break all previous code, unless you assume const grabs everything after it so that the first and last are the same.
Dec 01 2007
parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 12/1/07, Jesse Phillips <jessekphillips gmail.com> wrote:
 Based off of what you said in my other post, Walter will not change D's
 transitivity, Craig's proposal violates this.
Hmm... Someone's misunderstood something. I totally agree with Walter that transitive const is the right way to go.
 As a lot of the discussion
 here has suggested a solution for having a const ref with mutable data.
I don't think so. It's more about the distinction between const X and const(X). What we're after is a syntax for mutable ref to const data (not the other way round). What I'm saying is, if X is a class, then const X x; // fully const const(X) x; // fully const const(X)& x; // mutable ref to const data There shall be /no/ way to specify const ref to mutable data. Further, if X is not a class (say it's a struct or an int or something), then const(X)& x; // Errror - will not compile.
 So if I am correct then the real problem becomes with,
 const X x != const(X) x
Yes. I've been saying that for a long time now. const(X) must mean the same thing as const X because otherwise it's just silly.
 const TYPE * foo  // *foo immutable, foo mutable
 const(TYPE) * foo // same as above
 const(TYPE *) foo // foo and *foo immutable, but foo can be rebound
I stress again the general principle that const X must mean the same thing as const(X). Thus must be true regardless of the type of X. In particular, it must be true when X == TYPE *, and hence "const TYPE *" needs to mean the exact same thing as "const(TYPE *)". The principles that "everything inside the brackets is const", and "if the brackets are omitted, everything is const", cause no problems /except/ for class references. Pointers are not a problem. Only for class references do we need extra syntax, and it was for this purpose that I proposed "const(X)&". (I wasn't the first person to suggest it though).
 It would appear this meets at least most of the complaints const() does
 not have a special meaning, everything can be achieved with one const
 keyword, transitivity holds, no ambiguity, everything in const() is
 const.
const(X) must mean the same thing as const X, for all X. Unless you have that, there will always be complaints.
 The only problem is that it would break all previous code,
D1 doesn't even /have/ const, so that's hardly true. The D2 branch is experimental, and those of us using it are full expect things to change. It's kind of the whole point of the branch.
Dec 01 2007
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Janice Caron wrote:
 const(X) must mean the same thing as const X, for all X. Unless you
 have that, there will always be complaints.
Let's look at it another way. Consider a class C: alias const(C) CC; void foo(CC c, CC f) { auto d = c; d = f; } This kind of code can be expected, and it should work. It should also work if CC is: alias const(int) CC; because this can happen with metaprogramming. The insight is that, although a type can be const, it can always be copied (shallow copy) without affecting the const. If a variable is bound to a const type, being able to rebind it doesn't affect the const'ness, because it's just another copy. In other words, const'ness of types, const-correctness, etc., *only matters* for a type with references in it. You cannot undermine const-correctness by rebinding a variable that is typed as const. Next, a storage class says something about how the variable is stored, not its type. We'd like to be able to say a variable is stored in read-only memory (even if that is only conceptual). Hence, we'd like to give it a storage class 'const' to put it in read-only memory. Pulling on that string, in order to have transitive const, using a const storage class must also make the type of the variable const, too. Thus, we have: const(T) x; which types x as having a const type, which matters only for references, and: const T x; which types x as having a const type, *and* (conceptually) puts x in read-only memory after it is initialized. I suggest writing some actual code using const. I think you'll find it is rather natural in practice. For example, nobody is going to write: const(int) x = 3; when they want a compile-time constant, they'll write: const int x = 3; The only time you'll see the form: const(T) x; is when T is a reference type, or is an unknown type that could be a reference type. And the only reason one would write this is to protect the references, not x itself. The natural question then, is why have: const(int) x; at all? The reason is when one is deconstructing types using templates, and then reconstructing them, the const-correctness of what is being referred to must be carried along, else the const-correctness is lost.
Dec 02 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Walter Bright wrote:
 Janice Caron wrote:
 const(X) must mean the same thing as const X, for all X. Unless you
 have that, there will always be complaints.
...[explanation snipped] The natural question then, is why have: const(int) x; at all? The reason is when one is deconstructing types using templates, and then reconstructing them, the const-correctness of what is being referred to must be carried along, else the const-correctness is lost.
Great explanation. Any ETA on an updated const article? I think this one is out of date since it still talks about final. http://www.digitalmars.com/d/const.html --bb
Dec 03 2007
parent Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 Any ETA on an updated const article?
 I think this one is out of date since it still talks about final.
 http://www.digitalmars.com/d/const.html
Yes, I need to fix that.
Dec 03 2007
prev sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Janice Caron wrote:
 On 11/30/07, Jason House <jason.james.house gmail.com> wrote:
 Craig Black wrote:
 Technically, I proposed the syntax.  Janice didn't like it at first but has
 now come full circle.
That's right. I think my earlier attempt was something like "const(X)ref" or "ref const(X)". I came full circle and now fully support Craig's idea, largely because I think there may come a time in the future when D has C++-style references. If and when that day comes, "&" will be preferable to "ref" for the same reason that "*" is preferable to "ptr".
Pointers can be stacked like T***. References cannot. The 'ref' can only ever apply to the head. So I think a syntax with ref in front would be workable if Walter wants to go that way. In some ways it makes more sense to put the sigil for references out in front because, for the most part, ref doesn't affect the way you use the thing. ref T acts just like a T for most purposes, whereas T* is a quite different thing. --bb
Dec 01 2007
next sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 12/1/07, Bill Baxter <dnewsgroup billbaxter.com> wrote:
 Pointers can be stacked like T***.  References cannot.
You are completely correct, of course. T&& is the same type as T& (or indeed, T&&&&&&&). Honestly, I don't mind if we end up with a syntax of ref const(X) x; // mutable reference to const data instead of const(X)& x; // mutable reference to const data Either will make me happy.
Dec 01 2007
prev sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 12/1/07, Janice Caron <caron800 googlemail.com> wrote:
 On 12/1/07, Bill Baxter <dnewsgroup billbaxter.com> wrote:
 Pointers can be stacked like T***.  References cannot.
You are completely correct, of course. T&& is the same type as T& (or indeed, T&&&&&&&). Honestly, I don't mind if we end up with a syntax of ref const(X) x; // mutable reference to const data instead of const(X)& x; // mutable reference to const data Either will make me happy.
Actually, the "ref" way is better than the "&" way. (Do I get to change my mind again?) Here's why. Imagine a time in the future when we have references to things that aren't classes - say, ints, structs, whatever. When that day comes, we'll need a way to distinguish between "assign the reference" and "assign the data". Well, the obvious syntax for that is x = y; // assign the data x ref= y; // assign the reference Obviously, &= is already taken! :-)
Dec 01 2007
prev sibling parent reply "Craig Black" <craigblack2 cox.net> writes:
  "const X" and "const(X)" must mean the same thing
Sorry if this is a stupid question, but if const XY means that both X and Y are const, then const(X)Y will not be equivalent to const XY and thus const(X) will not always be equivalent to const X So what does everyone mean when they make this a requirement? It seems to be a contradiction with the current approach to const.
Dec 02 2007
parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 12/3/07, Craig Black <craigblack2 cox.net> wrote:
 Sorry if this is a stupid question, but if

 const XY

 means that both X and Y are const, then
But it doesn't. I don't understand what you're saying. A statement like "const XY x;" would mean that x is fully const and of type XY. A statement like "const X Y x;" just won't compile.
Dec 02 2007
parent reply "Craig Black" <cblack ara.com> writes:
"Janice Caron" <caron800 googlemail.com> wrote in message 
news:mailman.224.1196658519.2338.digitalmars-d puremagic.com...
 On 12/3/07, Craig Black <craigblack2 cox.net> wrote:
 Sorry if this is a stupid question, but if

 const XY

 means that both X and Y are const, then
But it doesn't. I don't understand what you're saying. A statement like "const XY x;" would mean that x is fully const and of type XY. A statement like "const X Y x;" just won't compile.
I guess using X and Y is bad since you assume they are both types.. Am I wrong in assuming the following? const X* x; is not equivalent to const(X)* x; Thus const X is not always equivalent to const(X)
Dec 03 2007
parent reply "Janice Caron" <caron800 googlemail.com> writes:
On Dec 3, 2007 2:34 PM, Craig Black <cblack ara.com> wrote:
 I guess using X and Y is bad since you assume they are both types..
 Am I wrong in assuming the following?

 const X* x;

 is not equivalent to

 const(X)* x;

 Thus const X is not always equivalent to const(X)
OK. Start again, You've misunderstood me. My X stands for /everything between the word const and the identifier being declared/. (Not literally the symbol "X"). So I would want "const X* x" to be interchangeable with "const(X*) x", since, in this case, /everything between the word const and the identifier being declared/ is "X*".
Dec 03 2007
parent reply "Craig Black" <cblack ara.com> writes:
"Janice Caron" <caron800 googlemail.com> wrote in message 
news:mailman.227.1196693680.2338.digitalmars-d puremagic.com...
 On Dec 3, 2007 2:34 PM, Craig Black <cblack ara.com> wrote:
 I guess using X and Y is bad since you assume they are both types..
 Am I wrong in assuming the following?

 const X* x;

 is not equivalent to

 const(X)* x;

 Thus const X is not always equivalent to const(X)
OK. Start again, You've misunderstood me. My X stands for /everything between the word const and the identifier being declared/. (Not literally the symbol "X"). So I would want "const X* x" to be interchangeable with "const(X*) x", since, in this case, /everything between the word const and the identifier being declared/ is "X*".
Right! And the same principle can be applied to references as well. So "const X x;" could be interpreted to be interchangeable with "const (X x);" (even though technically the latter that will not compile). Thus your const X == const(X) rule holds with "const(X) x;" and "const X x;"
Dec 03 2007
parent reply "Craig Black" <cblack ara.com> writes:
"Craig Black" <cblack ara.com> wrote in message 
news:fj16ut$qgf$1 digitalmars.com...
 "Janice Caron" <caron800 googlemail.com> wrote in message 
 news:mailman.227.1196693680.2338.digitalmars-d puremagic.com...
 On Dec 3, 2007 2:34 PM, Craig Black <cblack ara.com> wrote:
 I guess using X and Y is bad since you assume they are both types..
 Am I wrong in assuming the following?

 const X* x;

 is not equivalent to

 const(X)* x;

 Thus const X is not always equivalent to const(X)
OK. Start again, You've misunderstood me. My X stands for /everything between the word const and the identifier being declared/. (Not literally the symbol "X"). So I would want "const X* x" to be interchangeable with "const(X*) x", since, in this case, /everything between the word const and the identifier being declared/ is "X*".
Right! And the same principle can be applied to references as well. So "const X x;" could be interpreted to be interchangeable with "const (X x);" (even though technically the latter that will not compile). Thus your const X == const(X) rule holds with "const(X) x;" and "const X x;"
Just to expound further, the pointer and reference syntax seems difference since the reference is implicit. Just think of "const X x;" as "const X& x;" and you will see that the same principle that applies to pointers should also apply to references.
Dec 03 2007
parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 12/3/07, Craig Black <cblack ara.com> wrote:
 Just to expound further, the pointer and reference syntax seems difference
 since the reference is implicit.  Just think of  "const X x;" as "const X&
 x;" and you will see that the same principle that applies to pointers should
 also apply to references.
Yes, I think we're on the same page here. Of course, only classes have references. Structs don't, ints don't, etc., but for classes, my preference would be for all four of the following to be exactly equivalent: const C c; const(C) c; const C& c; const(C&) c; (Which leaves open the possibility of "const(C)& c;" to mean mutable ref to const data"). That's not the status quo, however
Dec 03 2007
parent reply "Craig Black" <cblack ara.com> writes:
"Janice Caron" <caron800 googlemail.com> wrote in message 
news:mailman.229.1196702116.2338.digitalmars-d puremagic.com...
 On 12/3/07, Craig Black <cblack ara.com> wrote:
 Just to expound further, the pointer and reference syntax seems 
 difference
 since the reference is implicit.  Just think of  "const X x;" as "const 
 X&
 x;" and you will see that the same principle that applies to pointers 
 should
 also apply to references.
Yes, I think we're on the same page here. Of course, only classes have references. Structs don't, ints don't, etc., but for classes, my preference would be for all four of the following to be exactly equivalent: const C c; const(C) c; const C& c; const(C&) c; (Which leaves open the possibility of "const(C)& c;" to mean mutable ref to const data"). That's not the status quo, however
That syntax would looks OK, but I think it also makes sense to make "const(C) c" equivalent to "const(C)& c;". Walter said that this is how the syntax already works. Am I misunderstanding something? What I don't understand is why Walter and others think that "C const c" violates transitivitiy. What do they mean by transitivity?
Dec 03 2007
parent reply Christopher Wright <dhasenan gmail.com> writes:
Craig Black wrote:
 "Janice Caron" <caron800 googlemail.com> wrote in message 
 news:mailman.229.1196702116.2338.digitalmars-d puremagic.com...
 On 12/3/07, Craig Black <cblack ara.com> wrote:
 Just to expound further, the pointer and reference syntax seems 
 difference
 since the reference is implicit.  Just think of  "const X x;" as "const 
 X&
 x;" and you will see that the same principle that applies to pointers 
 should
 also apply to references.
Yes, I think we're on the same page here. Of course, only classes have references. Structs don't, ints don't, etc., but for classes, my preference would be for all four of the following to be exactly equivalent: const C c; const(C) c; const C& c; const(C&) c; (Which leaves open the possibility of "const(C)& c;" to mean mutable ref to const data"). That's not the status quo, however
That syntax would looks OK, but I think it also makes sense to make "const(C) c" equivalent to "const(C)& c;". Walter said that this is how the syntax already works. Am I misunderstanding something?
We don't like the syntax. It makes a tiny bit of sense, with that description, but it's unintuitive and error-prone.
 What I don't understand is why Walter and others think that "C const c" 
 violates transitivitiy.  What do they mean by transitivity?
"C const c" -> c is a pointer that cannot be reassigned, but you can modify its members. This violates transitivity, the property that you cannot follow a series of const pointers/references and end up with something mutable. It is also useful, but it isn't useful as a public interface sort-of-thing; it's useful at a relatively small scope. Which is why Walter hasn't implemented it; he doesn't see enough of a benefit yet.
Dec 03 2007
parent reply "Craig Black" <cblack ara.com> writes:
 "C const c" -> c is a pointer that cannot be reassigned, but you can 
 modify its members.
Right.
 This violates transitivity, the property that you cannot follow a series 
 of const pointers/references and end up with something mutable. It is also 
 useful, but it isn't useful as a public interface sort-of-thing; it's 
 useful at a relatively small scope. Which is why Walter hasn't implemented 
 it; he doesn't see enough of a benefit yet.
If that is correct, then transitivity just seems like an artificial restriction for no reason. It's not like we are violating some fundamental law here. I still don't see a good reason not to allow "C const c" syntax. To me, it's straightforward. However, it may complicate the compiler implementation. I wouldn't know.
Dec 03 2007
parent Christopher Wright <dhasenan gmail.com> writes:
Craig Black wrote:
 If that is correct, then transitivity just seems like an artificial 
 restriction for no reason.  It's not like we are violating some fundamental 
 law here.  I still don't see a good reason  not to allow "C const c" syntax. 
 To me, it's straightforward.  However, it may complicate the compiler 
 implementation.  I wouldn't know. 
You're right in that it's an artificial restriction. As for complicating the implementation, I doubt that. It should be easier to do head-const than transitive const. You have to arrange for an initial assignment, which could be awkward. The main issue is language bloat, I think. This is a common feature of other languages, though, so that in itself is an argument in favor of considering the feature. And the fact that it can help find local bugs is an argument in favor of implementing it. I think people have been expecting const always to give a rebindable reference for reference types, and then wanting final in addition. Maybe. But I'm not sure.
Dec 03 2007
prev sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Janice Caron wrote:
 Well, I'm still gunning for
 
     const (X)& x;
 
 for mutable refs to const classes. Since I come from a C++ background,
 & means "reference of" to me, and this reads straightforwardly as "x
 is a reference to const X".
 
 Of course, x would be a reference even /without/ the ampersand - such
 is the nature of classes in D. But writing it explicitly allows one to
 put it outside the brackets.
I like where this is going, but my guess is that when/if Walter ever introduces reference types, the syntax for reference-to-T will be "ref T" like the parameter signature rather than C++'s "T&". So if you're going peel off the hidden ref, I think you might should make it: ref X x --> const ref(T) x; or --> const (T)ref x; or --> ref const(T) x; decide to do. About references generally, one big difference between C++ references and D classes is that you can't reassign a C++ reference. // C++ int& x = y; x = z; /// error In that sense, the C++ references themselves are always 'const' (aka head-const / final). I seem to remember some example in Stroustrup that explained why this behavior was important. But anyway, D's class references aren't like that, and it makes me wonder if more general D reference types in D would be like that. --bb
Nov 30 2007
next sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Bill Baxter wrote:
 Janice Caron wrote:
 Well, I'm still gunning for

     const (X)& x;

 for mutable refs to const classes. Since I come from a C++ background,
 & means "reference of" to me, and this reads straightforwardly as "x
 is a reference to const X".

 Of course, x would be a reference even /without/ the ampersand - such
 is the nature of classes in D. But writing it explicitly allows one to
 put it outside the brackets.
I like where this is going, but my guess is that when/if Walter ever introduces reference types, the syntax for reference-to-T will be "ref T" like the parameter signature rather than C++'s "T&". So if you're going peel off the hidden ref, I think you might should make it: ref X x --> const ref(T) x; or --> const (T)ref x; or --> ref const(T) x; decide to do. About references generally, one big difference between C++ references and D classes is that you can't reassign a C++ reference. // C++ int& x = y; x = z; /// error
Er. Not 'error' per se, it just doesn't rebind x, it modifies y.
 In that sense, the C++ references themselves are always 'const' (aka 
 head-const / final).
 I seem to remember some example in Stroustrup that explained why this 
 behavior was important.  
I remembered. You can't reassign them because it's ambiguous whether you want to make x just refer to the new thing or call the opAssign on the previously bound thing. Ok, so D classes get around this by eliminating opAssign for classes and saying you can *only* rebind the reference. But I don't think that will fly for references to structs or built-in value types. --bb
Nov 30 2007
prev sibling next sibling parent reply "Craig Black" <cblack ara.com> writes:
 So if you're going peel off the hidden ref, I think you might should make 
 it:

     ref X x --> const ref(T) x;
 or          --> const (T)ref x;
 or          --> ref const(T) x;


 decide to do.
Good point here. Here's another idea. If we reverse the meaning of const(X) then we could do this: const X x; // all const const(X) x; // data const, ref mutable X const x; // data mutable, ref const
Nov 30 2007
next sibling parent reply Denton Cockburn <diboss hotmail.com> writes:
On Fri, 30 Nov 2007 15:27:20 -0600, Craig Black wrote:

 
 Here's another idea.  If we reverse the meaning of const(X) then we could do 
 this:
 
 const X x;  // all const
 const(X) x; // data const, ref mutable
 X const x; // data mutable, ref const
I like this, nice and clear. ++vote.
Nov 30 2007
parent "Janice Caron" <caron800 googlemail.com> writes:
On 11/30/07, Denton Cockburn <diboss hotmail.com> wrote:
 const X x;  // all const
 const(X) x; // data const, ref mutable
I like this, nice and clear.
I don't think I'll ever like any scheme in which const(X) != const X.
Nov 30 2007
prev sibling next sibling parent Jesse Phillips <jessekphillips gmail.com> writes:
On Fri, 30 Nov 2007 15:27:20 -0600, Craig Black wrote:

 So if you're going peel off the hidden ref, I think you might should
 make it:

     ref X x --> const ref(T) x;
 or          --> const (T)ref x;
 or          --> ref const(T) x;


 decide to do.
Good point here. Here's another idea. If we reverse the meaning of const(X) then we could do this: const X x; // all const const(X) x; // data const, ref mutable X const x; // data mutable, ref const
On that note, we could try to keep Janice's idea that const X = const(X) and Adam's explanation of compile time function. const X x; // data const X const x; // ref const const(X x); // both const This would mean that const(T) takes a type T and returns a constant of it. Since in the last one, const(X x) takes a class and ref it will return a const of both. Equivalents of the above to help demonstrate the concept. const(X) x; // data const X const(x); // ref const const(X) const(x); // both const
Nov 30 2007
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Craig Black wrote:
 Here's another idea.  If we reverse the meaning of const(X) then we could do 
 this:
 
 const X x;  // all const
 const(X) x; // data const, ref mutable
This is what we have now.
 X const x; // data mutable, ref const 
This breaks transitivity of const.
Dec 02 2007
parent Christopher Wright <dhasenan gmail.com> writes:
Walter Bright wrote:
 Craig Black wrote:
 Here's another idea.  If we reverse the meaning of const(X) then we 
 could do this:

 const X x;  // all const
 const(X) x; // data const, ref mutable
This is what we have now.
 X const x; // data mutable, ref const 
This breaks transitivity of const.
That's our goal. Other languages have the final keyword for this; we don't want to feel left out.
Dec 03 2007
prev sibling parent BC <NOTmi_emayl_adrez hotmail.com.remove.not> writes:
On Fri, 30 Nov 2007 20:44:33 -0000, Bill Baxter  =

<dnewsgroup billbaxter.com> wrote:

 Janice Caron wrote:
 Well, I'm still gunning for
      const (X)& x;
  for mutable refs to const classes. Since I come from a C++ backgroun=
d,
 & means "reference of" to me, and this reads straightforwardly as "x
 is a reference to const X".
  Of course, x would be a reference even /without/ the ampersand - suc=
h
 is the nature of classes in D. But writing it explicitly allows one t=
o
 put it outside the brackets.
I like where this is going, but my guess is that when/if Walter ever =
 introduces reference types, the syntax for reference-to-T will be "ref=
=
 T" like the parameter signature rather than C++'s  "T&".

 So if you're going peel off the hidden ref, I think you might should  =
 make it:

      ref X x --> const ref(T) x;
 or          --> const (T)ref x;
 or          --> ref const(T) x;


=
 decide to do.
 About references generally, one big difference between C++ references =
=
 and D classes is that you can't reassign a C++ reference.
       // C++
       int& x =3D y;
       x =3D z;  /// error

 In that sense, the C++ references themselves are always 'const' (aka  =
 head-const / final).
 I seem to remember some example in Stroustrup that explained why this =
=
 behavior was important.  But anyway, D's class references aren't like =
=
 that, and it makes me wonder if more general D reference types in D  =
 would be like that.

 --bb
imo c++ should have had &r =3D &x to rebind r to x. maybe d could do 'ref r =3D x' or 'ref r =3D ref x'
Dec 02 2007