Jump to page: 1 2
Thread overview
It's worse than I thought
Nov 30, 2007
Janice Caron
Nov 30, 2007
Walter Bright
Nov 30, 2007
Janice Caron
Nov 30, 2007
gide
Nov 30, 2007
Janice Caron
Nov 30, 2007
Craig Black
Nov 30, 2007
Craig Black
Nov 30, 2007
Janice Caron
Nov 30, 2007
Sönke Ludwig
Dec 03, 2007
Walter Bright
Dec 03, 2007
Sönke Ludwig
Dec 03, 2007
Sönke Ludwig
Dec 03, 2007
Walter Bright
November 30, 2007
It's worse than I thought. This compiles and runs, both in D2.007 and in D2.008

void main()
{
	const(int) ci = 1;
	invariant(int) ii = 2;

	++ci;
	++ii;
}

It is now becoming quite clear that the "const mess" is very much still with us, and this sort of thing really doesn't help D at all.
November 30, 2007
Janice Caron wrote:
> It's worse than I thought. This compiles and runs, both in D2.007 and in D2.008
> 
> void main()
> {
> 	const(int) ci = 1;
> 	invariant(int) ii = 2;
> 	
> 	++ci;
> 	++ii;
> }
> 
> It is now becoming quite clear that the "const mess" is very much
> still with us, and this sort of thing really doesn't help D at all.

It turns out that making a variable that is typed const (rather than storage class const) immutable makes it impossible to use const references:

	class C { }
	const(C) c;
	if (...)
		c = ...;
	else
		c = ...;

So, variables that are typed const are rebindable. Note that this doesn't break const, as you can always make a copy of a const. To get a non-rebindable const:

	const C c;
November 30, 2007
On Nov 30, 2007 10:52 AM, Walter Bright <newshound1@digitalmars.com> wrote:
> It turns out that making a variable that is typed const (rather than storage class const) immutable makes it impossible to use const references: So, variables that are typed const are rebindable.

Yes, there is another thread on that somewhere. It's got some long arguments in it, which it would be silly to repeat here, but in the end I proposed the syntaxes:

    const(C) c;
    const(C) ref c;

The first makes both the reference and the data const; the second makes only the data const, but the reference rebindable. (Other people have suggested alternative syntaxes through the ages, so don't think I'm particularly hung up on mine, it's just that it seems very clear what's being said).


> Note that this
> doesn't break const

Nobody's saying anything is broken. What I'm saying is that it's TOO CONFUSING. This can break D. I mean, on other threads, you told us that "const X x" was the same thing as "const(X) x". Now it turns out that's not true.

The only, and I mean *ONLY*, thing that makes intuitive sense, is that when I write const(...), it must mean that everything inside the brackets, and nothing else, is const. Nothing else makes sense.
November 30, 2007
Walter Bright wrote:
> Janice Caron wrote:
>> It's worse than I thought. This compiles and runs, both in D2.007 and in D2.008
>>
>> void main()
>> {
>>     const(int) ci = 1;
>>     invariant(int) ii = 2;
>>         ++ci;
>>     ++ii;
>> }
>>
>> It is now becoming quite clear that the "const mess" is very much
>> still with us, and this sort of thing really doesn't help D at all.
> 
> It turns out that making a variable that is typed const (rather than storage class const) immutable makes it impossible to use const references:
> 
>     class C { }
>     const(C) c;
>     if (...)
>         c = ...;
>     else
>         c = ...;
> 
> So, variables that are typed const are rebindable. Note that this doesn't break const, as you can always make a copy of a const. To get a non-rebindable const:
> 
>     const C c;

I've noticed some things that seem to be inconsistent with this behavior for local variables and where I've not found a workaround for (with the exception of casts):


1. Arrays or associative arrays of references to const instances:
  class C {}
  const(C)[] a;
  const(C)[string] b;

  It seems to be impossible here to make the array elements assignable, while at the same time keeping the class instances const. I currently need this in a function, where I'm getting a const array of instances and need to build a map to those.

  void fn( in C[] objs ){
    const(C)[string] map;
    map["test"] = objs[0]; // error, not mutable
  }


2. Class references as members:
  class D {
    const(C) c;
    const C d;
    this( C c ){
      this.c = c; // error
      this.d = d; // works, but, of course, only inside of the constructor
    }
  }
November 30, 2007
On Fri, 30 Nov 2007 11:06:53 +0000, "Janice Caron" <caron800@googlemail.com> wrote:

>On Nov 30, 2007 10:52 AM, Walter Bright <newshound1@digitalmars.com> wrote:
>> It turns out that making a variable that is typed const (rather than storage class const) immutable makes it impossible to use const references: So, variables that are typed const are rebindable.
>
>Yes, there is another thread on that somewhere. It's got some long arguments in it, which it would be silly to repeat here, but in the end I proposed the syntaxes:
>
>    const(C) c;
>    const(C) ref c;
>
>The first makes both the reference and the data const; the second makes only the data const, but the reference rebindable. (Other people have suggested alternative syntaxes through the ages, so don't think I'm particularly hung up on mine, it's just that it seems very clear what's being said).
>
>
>> Note that this
>> doesn't break const
>
>Nobody's saying anything is broken. What I'm saying is that it's TOO CONFUSING. This can break D. I mean, on other threads, you told us that "const X x" was the same thing as "const(X) x". Now it turns out that's not true.
>
>The only, and I mean *ONLY*, thing that makes intuitive sense, is that when I write const(...), it must mean that everything inside the brackets, and nothing else, is const. Nothing else makes sense.

</lurk>
I agree with Janice on this, I was under the (wrong) impression that
'const(C)' and 'const C'  were synonymous.

Maybe the following syntax will work?
const (C) c = new C;
c = new C; // Error;
c.set(...); // Error

const (ref C) c = new C;
c = new C; // Error;
c.set(...); // Ok

const (C.) c = new C;
c = new C; // Ok;
c.set(...); // Error

Gide
November 30, 2007
On Nov 30, 2007 3:48 PM,  <gide@nwawudu.com> wrote:
> I was under the (wrong) impression that
> 'const(C)' and 'const C'  were synonymous.


Some time ago, Walter started a thread called something like "const sucks", in which he agreed that D2.007 const was a mess, and promised to go away and rethink it. He has indeed done that - however, the only change I can observe is that "head const" has been ditched, along with the keyword "final". Everything else that was bad about const is still there.

I find this distressing, because I /love/ what Walter is trying to do. D-const could be way, way, w-a-y, better than C++ const. I love that const is transitive. I'm prepared to live without "logical const" and see what happens. I love the fact that the language distinguishes between const and invariant, where it makes sense to do that. I love that "const(int***)***" is so much more concise than C++'s corresponding "int const*const*const*const***". All of this is GREAT!

But what I hate about it is the confusion between (1) const as a
type-constructor, (2) const as a storage class for variables, (3)
const as a function parameter storage class, and (4) const as a
storage class for member functions. (And ditto for invariant). I
further hate that const/invariant don't apply to declared symbols
(sometimes). Huh!?

So here are my suggestions for clearing up the mess. They are very simple, clean, and elegant:


(1) ditch "const as a storage class" altogther. Keep "const as a
type-constructor". Stick rigidly to the principle that "const(...)"
means "the stuff in the brackets is const", and nothing else.

(2) allow "const T", where T is a type, to be syntactic sugar for
"const(T)". But it's still just a type constructor.

(3) use the syntax "const(this)" for const member functions. Make
"const(this)" an attribute. Ideally, extend the principle to
"const(anyIdentifier)", but just "const(this)" will do for now.

(4) let "const(C)&" be the syntax for making mutable references to
const classes.

(5) let "const x = y;" be syntactic sugar for "const(typeof(y)) x = y;"

And the same for invariant.


...and that's it!
November 30, 2007
"Janice Caron" <caron800@googlemail.com> wrote in message news:mailman.199.1196440211.2338.digitalmars-d@puremagic.com...
> On Nov 30, 2007 3:48 PM,  <gide@nwawudu.com> wrote:
>> I was under the (wrong) impression that
>> 'const(C)' and 'const C'  were synonymous.
>
>
> Some time ago, Walter started a thread called something like "const sucks", in which he agreed that D2.007 const was a mess, and promised to go away and rethink it. He has indeed done that - however, the only change I can observe is that "head const" has been ditched, along with the keyword "final". Everything else that was bad about const is still there.
>
> I find this distressing, because I /love/ what Walter is trying to do. D-const could be way, way, w-a-y, better than C++ const. I love that const is transitive. I'm prepared to live without "logical const" and see what happens. I love the fact that the language distinguishes between const and invariant, where it makes sense to do that. I love that "const(int***)***" is so much more concise than C++'s corresponding "int const*const*const*const***". All of this is GREAT!
>
> But what I hate about it is the confusion between (1) const as a
> type-constructor, (2) const as a storage class for variables, (3)
> const as a function parameter storage class, and (4) const as a
> storage class for member functions. (And ditto for invariant). I
> further hate that const/invariant don't apply to declared symbols
> (sometimes). Huh!?
>
> So here are my suggestions for clearing up the mess. They are very simple, clean, and elegant:
>
>
> (1) ditch "const as a storage class" altogther. Keep "const as a
> type-constructor". Stick rigidly to the principle that "const(...)"
> means "the stuff in the brackets is const", and nothing else.
>
> (2) allow "const T", where T is a type, to be syntactic sugar for
> "const(T)". But it's still just a type constructor.
>
> (3) use the syntax "const(this)" for const member functions. Make
> "const(this)" an attribute. Ideally, extend the principle to
> "const(anyIdentifier)", but just "const(this)" will do for now.

I like the const(this) idea.  Very explicit.

> (4) let "const(C)&" be the syntax for making mutable references to
> const classes.

I don't think adding an amphersand makes it any more understandable.

> (5) let "const x = y;" be syntactic sugar for "const(typeof(y)) x = y;"

Sure.  We can't already do this?

> And the same for invariant.
>
>
> ...and that's it!


November 30, 2007
>> (4) let "const(C)&" be the syntax for making mutable references to
>> const classes.
>
> I don't think adding an amphersand makes it any more understandable.
>

Maybe const(ref) could be used just like const(this).

const X x;  // The reference is mutable
const(ref) X x;  // The data is mutable
const(ref) const X x;  // Nothing is mutable


November 30, 2007
On 11/30/07, Craig Black <cblack@ara.com> wrote:
> > (4) let "const(C)&" be the syntax for making mutable references to
> > const classes.
>
> I don't think adding an amphersand makes it any more understandable.

If you think of the ampersand as meaning "reference to", in the same way that asterisk means "pointer to", then it makes a lot of sense. I did a long explanation of this on the other thread. Essentially, what we're saying is that because the ampersand is outside the brackets, then "reference to" isn't const.

We do need a way of expressing "mutable reference to const class", though. If this isn't the right syntax, I'm sure we can come up with another one.



> > (5) let "const x = y;" be syntactic sugar for "const(typeof(y)) x = y;"
>
> Sure.  We can't already do this?

My rule (5) was necessary because of my rule (1). Janice's rule (1)
would make "const x = y;" (which is currently legal, as you say)
illegal, so I introduced rule (5) to put it back.
December 03, 2007
Sönke Ludwig wrote:
> I've noticed some things that seem to be inconsistent with this behavior for local variables and where I've not found a workaround for (with the exception of casts):
> 
> 
> 1. Arrays or associative arrays of references to const instances:
>   class C {}
>   const(C)[] a;
>   const(C)[string] b;
> 
>   It seems to be impossible here to make the array elements assignable, while at the same time keeping the class instances const. I currently need this in a function, where I'm getting a const array of instances and need to build a map to those.
> 
>   void fn( in C[] objs ){
>     const(C)[string] map;
>     map["test"] = objs[0]; // error, not mutable
>   }
> 
> 
> 2. Class references as members:
>   class D {
>     const(C) c;
>     const C d;
>     this( C c ){
>       this.c = c; // error
>       this.d = d; // works, but, of course, only inside of the constructor
>     }
>   }

There isn't much to be done about this problem except make the implementation of the class itself const.
« First   ‹ Prev
1 2