digitalmars.D - a more consistent const syntax
- Daniel919 (91/91) Aug 05 2007 I've got some ideas about how to make the const syntax more
- Chris Nicholson-Sauls (39/154) Aug 05 2007 Well technically if that was what I wanted, I'd use one of 'invariant x
- Rioshin an'Harthen (15/40) Aug 05 2007 I agree, as well. It reads like returning a const P.
- Paul Collier (6/55) Aug 05 2007 Just chiming in on a slightly different note... the line that stuck out
- Reiner Pope (10/67) Aug 05 2007 Although the idea is nice, I tried it out, and I don't like the look of ...
- Paul Collier (14/88) Aug 05 2007 Yeah, I guess there are a lot of tradeoffs with each syntax. I was
- Reiner Pope (19/113) Aug 05 2007 I don't know if I'm missing something, but I thought that const
- Rioshin an'Harthen (20/48) Aug 06 2007 Ok, same list as above, once again, this time using const(this) for meth...
- Daniel919 (55/233) Aug 06 2007 But they are not the same:
- Chris Nicholson-Sauls (25/121) Aug 06 2007 Just like 'invariant' does. Gotcha. Maybe the rule should be as I
- Robert Fraser (8/20) Aug 06 2007 It's not that it's a bad idea, but there's some inner aversion to it in ...
- Derek Parnell (8/9) Aug 06 2007 I love the 'define' proposal. It is totally unambiguous and clear what i...
- Bill Baxter (21/29) Aug 07 2007 What I think would really rock is if 'define' could also be used for
- Chris Nicholson-Sauls (12/49) Aug 07 2007 As I understand it, the reason alias syntax is like this, is so the comp...
- Reiner Pope (68/83) Aug 07 2007 I think that would be just great. I hate having to write two templates,
- Walter Bright (4/4) Aug 06 2007 I realize there are some consistency issues with the current syntax for
- Chris Nicholson-Sauls (7/11) Aug 07 2007 I hadn't even considered alias. Was his idea roughly that have having
- Reiner Pope (8/12) Aug 07 2007 If anyone is interested, there was a brief discussion on this in the D
I've got some ideas about how to make the const syntax more consistent. First I will show you the current situation. Then I will list the confusions and possible solutions. Some days ago I already mentioned my first idea on IRC, but got no replies. Also I know that you, Walter, hardly don't change features, which already have been implemented. And my suggestions would require this of course. The "define proposal" is not such a big change in the language, in opposite to the much more important idea about "putting the return type in a bracket at the end". Because this is what the last idea requires, it's written after "WAIT:". Nevertheless I will give it a try, because 2.0 is still alpha and it will break code compatibility anyway. currently the keyword const(/invariant) has three meanings: ----------------------------------------------------------- 1. alone: const x = 1; compile-time variable (not an lvalue) 2. with(): const(P) p = new Point(1,2); run-time object, which is protected from changes 3. alone: const P func(P p) { writefln(p.x, " ", p.y); }; attribute for a member function: the function can't change any class fields confusions and solutions: ------------------------- 1. const x = 1; 2. const(P) p = new Point(1,2); you see const first and later recognize the brackets one would not expect brackets to lead to a completely different meaning of the forrun keyword 1. define x = 1; 2. const(P) p = new Point(1,2); can't be confused anymore, different keywords define defines a compile-time variable const / invariant has nothing to do with compile-time anymore. it only means protection 3. const P func(P p) { ... } reads like: func returns a const(P) const / invariant alone (without brackets) is an attribute and has no other meaning further proposal: returned types in a bracket at the end: 3. const func (P p) (P) { ... } //templated syntax: const func!(T) (T p) (T) { ... } 1. same meaning: invariant x = 1; const x = 1; not allowed anymore: const(/invariant) alone is an attribute, instead use: 1. define x = 1; //this is ok: final int x = 1; const(int)* xptr = &x; // but: 2. const(int) x = 1; this is nonsense and also atm it could be confused with: 1. const int x = 1; the compiler should issue at least a warning, and instead you should use: 1. define x = 1; void func(const P p) { typeof(p) == const(P) } bad, because one could expect this to be also valid then: const P p = new P(1,2); //but fails of course correctly is has to be: void func(const(P) p) { ... } void func(ref const(P) p) { p = new P(3,4); } //OK compiler should issue an error const(/invariant) alone is an attribute WAIT: ----- because we have another syntax for compile-time variables now, we could say that: const P** ptr2ptr2P means: const(P**) ptr2ptr2P because if it wasn't: const P** func() { ... } would not only be confused with, but it would be THE SAME as: const(P**) func() { ... } then the correct form would have to be: const func() (const P**) { ...} this would be nonsense, because it would be the same as: const(int) x = 1; so the compiler should issue at least a warning PS: Having the return types in a bracket at the end, would make it possible to implement multiple return values / return tuples in a consistent way, too. It would also allow more tricks, like returning local values of a function, avoiding ref, etc etc ... I would really enjoy to get some replies (especially yours, Walter), even if it's just a: "No that's totally stupid" ;) Best regards, Daniel
Aug 05 2007
Daniel919 wrote:I've got some ideas about how to make the const syntax more consistent. First I will show you the current situation. Then I will list the confusions and possible solutions. Some days ago I already mentioned my first idea on IRC, but got no replies. Also I know that you, Walter, hardly don't change features, which already have been implemented. And my suggestions would require this of course. The "define proposal" is not such a big change in the language, in opposite to the much more important idea about "putting the return type in a bracket at the end". Because this is what the last idea requires, it's written after "WAIT:". Nevertheless I will give it a try, because 2.0 is still alpha and it will break code compatibility anyway. currently the keyword const(/invariant) has three meanings: ----------------------------------------------------------- 1. alone: const x = 1; compile-time variable (not an lvalue)Well technically if that was what I wanted, I'd use one of 'invariant x = 1;' or a more explicit 'final invariant(int) x = 1;'.2. with(): const(P) p = new Point(1,2); run-time object, which is protected from changesWell, protected from changes via this reference... but yeah. I'd say the 'const(type)' case would/should be used most often anyhow.3. alone: const P func(P p) { writefln(p.x, " ", p.y); }; attribute for a member function: the function can't change any class fieldsget into that one below.confusions and solutions: ------------------------- 1. const x = 1; 2. const(P) p = new Point(1,2); you see const first and later recognize the brackets one would not expect brackets to lead to a completely different meaning of the forrun keywordMy eyes are trained to spot them... still yes, a sudden shift in meaning can be counter-intuitive. Although its not entirely a shift... you could probably think of 'const x = 1;' as shorthand for 'final const(int) x = 1;'.1. define x = 1; 2. const(P) p = new Point(1,2); can't be confused anymore, different keywords define defines a compile-time variable const / invariant has nothing to do with compile-time anymore. it only means protectionAdding new keywords is usually the absolute last option around here. (There was talk ages past of replacing 'auto x = 1' with 'let x = 1'.)3. const P func(P p) { ... } reads like: func returns a const(P)Which is, indeed, a problem -- in that I agree.const / invariant alone (without brackets) is an attribute and has no other meaning further proposal: returned types in a bracket at the end: 3. const func (P p) (P) { ... } //templated syntax: const func!(T) (T p) (T) { ... }Uhm. Ew. No, seriously, I just could not possibly handle that; I would keep thinking I saw templates where there aren't any. Worse yet, for a long time I'll see the '!(' and keep wondering how I could be instantiating a template in that position, when its really a template declaration. T'is a naughty naughty thing to mix the two -- would give both the compiler and the user headaches. IMHO, its the 'const'/'invariant' keyword on methods that needs to move -- not sure where it should go, though. What looks best down here? ;) (First listing is the current state, for reference.) const P vunc (P p) { ... } P const func (P p) { ... } P const:func (P p) { ... } P const(func) (P p) { ... } P func const (P p) { ... } P func:const (P p) { ... } P func (P p) const { ... }1. same meaning: invariant x = 1; const x = 1;For basic types, there often isn't much difference anyhow. Except that invariant members of structures allocate no memory in the structure, for example.not allowed anymore: const(/invariant) alone is an attribute, instead use: 1. define x = 1; //this is ok: final int x = 1; const(int)* xptr = &x; // but: 2. const(int) x = 1; this is nonsense and also atm it could be confused with: 1. const int x = 1; the compiler should issue at least a warning, and instead you should use: 1. define x = 1; void func(const P p) { typeof(p) == const(P) } bad, because one could expect this to be also valid then: const P p = new P(1,2); //but fails of course correctly is has to be: void func(const(P) p) { ... } void func(ref const(P) p) { p = new P(3,4); } //OK compiler should issue an error const(/invariant) alone is an attribute WAIT: ----- because we have another syntax for compile-time variables now, we could say that: const P** ptr2ptr2P means: const(P**) ptr2ptr2P because if it wasn't: const P** func() { ... } would not only be confused with, but it would be THE SAME as: const(P**) func() { ... } then the correct form would have to be: const func() (const P**) { ...} this would be nonsense, because it would be the same as: const(int) x = 1; so the compiler should issue at least a warning PS: Having the return types in a bracket at the end, would make it possible to implement multiple return values / return tuples in a consistent way, too. It would also allow more tricks, like returning local values of a function, avoiding ref, etc etc ... I would really enjoy to get some replies (especially yours, Walter), even if it's just a: "No that's totally stupid" ;) Best regards, DanielNo that's totally stupid. Ahh I'm just kidding. At least you're thinking about the situation and offering suggestions. (And welcome to the tiny militia of 'const R func()' syntax detractors. ;)) The final/const/invariant system needs some good hammering yet -- although its off to a lovely start, danke Walter. -- Chris Nicholson-Sauls
Aug 05 2007
"Chris Nicholson-Sauls" <ibisbasenji gmail.com> kirjoitti viestissä news:f951kq$2fss$1 digitalmars.com...Daniel919 wrote:I agree, as well. It reads like returning a const P.3. const P func(P p) { ... } reads like: func returns a const(P)Which is, indeed, a problem -- in that I agree.Definitely the last one. It's immediately familiar to anyone with a C++ background, which I guess most of those coming to D has, and which I think are the people Walter is especially targetting. It also has the added bonus of not complicating method declaration grammar too much. Same list, this time a const func returning a const return value: const const(P) func (P p) const(P) const func (P p) const(P) const(func) (P p) const(P) func const (P p) const(P) func:const (P p) const(P) func (P p) const I definitely prefer the last one as the cleanest of these.const / invariant alone (without brackets) is an attribute and has no other meaning further proposal: returned types in a bracket at the end: 3. const func (P p) (P) { ... } //templated syntax: const func!(T) (T p) (T) { ... }Uhm. Ew. No, seriously, I just could not possibly handle that; I would keep thinking I saw templates where there aren't any. Worse yet, for a long time I'll see the '!(' and keep wondering how I could be instantiating a template in that position, when its really a template declaration. T'is a naughty naughty thing to mix the two -- would give both the compiler and the user headaches. IMHO, its the 'const'/'invariant' keyword on methods that needs to move -- not sure where it should go, though. What looks best down here? ;) (First listing is the current state, for reference.) const P vunc (P p) { ... } P const func (P p) { ... } P const:func (P p) { ... } P const(func) (P p) { ... } P func const (P p) { ... } P func:const (P p) { ... } P func (P p) const { ... }
Aug 05 2007
Rioshin an'Harthen wrote:"Chris Nicholson-Sauls" <ibisbasenji gmail.com> kirjoitti viestissä news:f951kq$2fss$1 digitalmars.com...Just chiming in on a slightly different note... the line that stuck out in both examples for me was actually the const(func) line. That seems really intuitive and consistent with the const syntax elsewhere. I do find the const-on-the-end readable too, but really mostly because of familiarity with C++ ;)Daniel919 wrote:I agree, as well. It reads like returning a const P.3. const P func(P p) { ... } reads like: func returns a const(P)Which is, indeed, a problem -- in that I agree.Definitely the last one. It's immediately familiar to anyone with a C++ background, which I guess most of those coming to D has, and which I think are the people Walter is especially targetting. It also has the added bonus of not complicating method declaration grammar too much. Same list, this time a const func returning a const return value: const const(P) func (P p) const(P) const func (P p) const(P) const(func) (P p) const(P) func const (P p) const(P) func:const (P p) const(P) func (P p) const I definitely prefer the last one as the cleanest of these.const / invariant alone (without brackets) is an attribute and has no other meaning further proposal: returned types in a bracket at the end: 3. const func (P p) (P) { ... } //templated syntax: const func!(T) (T p) (T) { ... }Uhm. Ew. No, seriously, I just could not possibly handle that; I would keep thinking I saw templates where there aren't any. Worse yet, for a long time I'll see the '!(' and keep wondering how I could be instantiating a template in that position, when its really a template declaration. T'is a naughty naughty thing to mix the two -- would give both the compiler and the user headaches. IMHO, its the 'const'/'invariant' keyword on methods that needs to move -- not sure where it should go, though. What looks best down here? ;) (First listing is the current state, for reference.) const P vunc (P p) { ... } P const func (P p) { ... } P const:func (P p) { ... } P const(func) (P p) { ... } P func const (P p) { ... } P func:const (P p) { ... } P func (P p) const { ... }
Aug 05 2007
Paul Collier wrote:Rioshin an'Harthen wrote:Although the idea is nice, I tried it out, and I don't like the look of it: int const(getFoo)() { return foo; } My main objection is that the const() is around getFoo, so you're saying that the function won't change -- but how can it, it's static data. What you really mean when you are saying it's a const function is that the this object is constant. So how about that? const(this) int getFoo() { return foo; } (It's syntactically unambiguous because this is a keyword) -- Reiner"Chris Nicholson-Sauls" <ibisbasenji gmail.com> kirjoitti viestissä news:f951kq$2fss$1 digitalmars.com...Just chiming in on a slightly different note... the line that stuck out in both examples for me was actually the const(func) line. That seems really intuitive and consistent with the const syntax elsewhere. I do find the const-on-the-end readable too, but really mostly because of familiarity with C++ ;)Daniel919 wrote:I agree, as well. It reads like returning a const P.3. const P func(P p) { ... } reads like: func returns a const(P)Which is, indeed, a problem -- in that I agree.Definitely the last one. It's immediately familiar to anyone with a C++ background, which I guess most of those coming to D has, and which I think are the people Walter is especially targetting. It also has the added bonus of not complicating method declaration grammar too much. Same list, this time a const func returning a const return value: const const(P) func (P p) const(P) const func (P p) const(P) const(func) (P p) const(P) func const (P p) const(P) func:const (P p) const(P) func (P p) const I definitely prefer the last one as the cleanest of these.const / invariant alone (without brackets) is an attribute and has no other meaning further proposal: returned types in a bracket at the end: 3. const func (P p) (P) { ... } //templated syntax: const func!(T) (T p) (T) { ... }Uhm. Ew. No, seriously, I just could not possibly handle that; I would keep thinking I saw templates where there aren't any. Worse yet, for a long time I'll see the '!(' and keep wondering how I could be instantiating a template in that position, when its really a template declaration. T'is a naughty naughty thing to mix the two -- would give both the compiler and the user headaches. IMHO, its the 'const'/'invariant' keyword on methods that needs to move -- not sure where it should go, though. What looks best down here? ;) (First listing is the current state, for reference.) const P vunc (P p) { ... } P const func (P p) { ... } P const:func (P p) { ... } P const(func) (P p) { ... } P func const (P p) { ... } P func:const (P p) { ... } P func (P p) const { ... }
Aug 05 2007
Reiner Pope wrote:Paul Collier wrote:Yeah, I guess there are a lot of tradeoffs with each syntax. I was wondering what the function pointers would look like as well... const int function() p; // Current const(this) int function() p; // Could be confusing in a member function int const(function)() p; // Looks like a const function pointer int function() const p; // C++ style And combinations... const(const const(int) function(const(int))) p; const(const(this) const(int) function(const(int))) p; const(const(int) const(function)(const(int))) p; const(const(int) function(const(int)) const) p; But the latter isn't really valid material for comparison. Anyways, I think the bikeshed should be orange! ;)Rioshin an'Harthen wrote:Although the idea is nice, I tried it out, and I don't like the look of it: int const(getFoo)() { return foo; } My main objection is that the const() is around getFoo, so you're saying that the function won't change -- but how can it, it's static data. What you really mean when you are saying it's a const function is that the this object is constant. So how about that? const(this) int getFoo() { return foo; } (It's syntactically unambiguous because this is a keyword) -- Reiner"Chris Nicholson-Sauls" <ibisbasenji gmail.com> kirjoitti viestissä news:f951kq$2fss$1 digitalmars.com...Just chiming in on a slightly different note... the line that stuck out in both examples for me was actually the const(func) line. That seems really intuitive and consistent with the const syntax elsewhere. I do find the const-on-the-end readable too, but really mostly because of familiarity with C++ ;)Daniel919 wrote:I agree, as well. It reads like returning a const P.3. const P func(P p) { ... } reads like: func returns a const(P)Which is, indeed, a problem -- in that I agree.Definitely the last one. It's immediately familiar to anyone with a C++ background, which I guess most of those coming to D has, and which I think are the people Walter is especially targetting. It also has the added bonus of not complicating method declaration grammar too much. Same list, this time a const func returning a const return value: const const(P) func (P p) const(P) const func (P p) const(P) const(func) (P p) const(P) func const (P p) const(P) func:const (P p) const(P) func (P p) const I definitely prefer the last one as the cleanest of these.const / invariant alone (without brackets) is an attribute and has no other meaning further proposal: returned types in a bracket at the end: 3. const func (P p) (P) { ... } //templated syntax: const func!(T) (T p) (T) { ... }Uhm. Ew. No, seriously, I just could not possibly handle that; I would keep thinking I saw templates where there aren't any. Worse yet, for a long time I'll see the '!(' and keep wondering how I could be instantiating a template in that position, when its really a template declaration. T'is a naughty naughty thing to mix the two -- would give both the compiler and the user headaches. IMHO, its the 'const'/'invariant' keyword on methods that needs to move -- not sure where it should go, though. What looks best down here? ;) (First listing is the current state, for reference.) const P vunc (P p) { ... } P const func (P p) { ... } P const:func (P p) { ... } P const(func) (P p) { ... } P func const (P p) { ... } P func:const (P p) { ... } P func (P p) const { ... }
Aug 05 2007
Paul Collier wrote:Reiner Pope wrote:I don't know if I'm missing something, but I thought that const functions *only* exist as member functions. By which I mean that only the following makes sense: (supposing, for the purposes of this post, we adopt the existing C++ syntax) class Foo { int getX() const { return x; } } It doesn't make sense declare a free function const, and it doesn't make sense to declare a function pointer (or delegate type) const. The reason I like my syntax (at risk of being too self-centred ;) ) is that it highlights exactly what a const member function is: one with the 'this' pointer declared 'const'. I also can imagine future extensions of this syntax to express globally pure functions, with something like const(scope) or const(module). (Although they don't quite capture the essence of const(world) :-) ) -- ReinerPaul Collier wrote:Yeah, I guess there are a lot of tradeoffs with each syntax. I was wondering what the function pointers would look like as well... const int function() p; // Current const(this) int function() p; // Could be confusing in a member function int const(function)() p; // Looks like a const function pointer int function() const p; // C++ style And combinations... const(const const(int) function(const(int))) p; const(const(this) const(int) function(const(int))) p; const(const(int) const(function)(const(int))) p; const(const(int) function(const(int)) const) p; But the latter isn't really valid material for comparison. Anyways, I think the bikeshed should be orange! ;)Rioshin an'Harthen wrote:Although the idea is nice, I tried it out, and I don't like the look of it: int const(getFoo)() { return foo; } My main objection is that the const() is around getFoo, so you're saying that the function won't change -- but how can it, it's static data. What you really mean when you are saying it's a const function is that the this object is constant. So how about that? const(this) int getFoo() { return foo; } (It's syntactically unambiguous because this is a keyword) -- Reiner"Chris Nicholson-Sauls" <ibisbasenji gmail.com> kirjoitti viestissä news:f951kq$2fss$1 digitalmars.com...Just chiming in on a slightly different note... the line that stuck out in both examples for me was actually the const(func) line. That seems really intuitive and consistent with the const syntax elsewhere. I do find the const-on-the-end readable too, but really mostly because of familiarity with C++ ;)Daniel919 wrote:I agree, as well. It reads like returning a const P.3. const P func(P p) { ... } reads like: func returns a const(P)Which is, indeed, a problem -- in that I agree.Definitely the last one. It's immediately familiar to anyone with a C++ background, which I guess most of those coming to D has, and which I think are the people Walter is especially targetting. It also has the added bonus of not complicating method declaration grammar too much. Same list, this time a const func returning a const return value: const const(P) func (P p) const(P) const func (P p) const(P) const(func) (P p) const(P) func const (P p) const(P) func:const (P p) const(P) func (P p) const I definitely prefer the last one as the cleanest of these.const / invariant alone (without brackets) is an attribute and has no other meaning further proposal: returned types in a bracket at the end: 3. const func (P p) (P) { ... } //templated syntax: const func!(T) (T p) (T) { ... }Uhm. Ew. No, seriously, I just could not possibly handle that; I would keep thinking I saw templates where there aren't any. Worse yet, for a long time I'll see the '!(' and keep wondering how I could be instantiating a template in that position, when its really a template declaration. T'is a naughty naughty thing to mix the two -- would give both the compiler and the user headaches. IMHO, its the 'const'/'invariant' keyword on methods that needs to move -- not sure where it should go, though. What looks best down here? ;) (First listing is the current state, for reference.) const P vunc (P p) { ... } P const func (P p) { ... } P const:func (P p) { ... } P const(func) (P p) { ... } P func const (P p) { ... } P func:const (P p) { ... } P func (P p) const { ... }
Aug 05 2007
"Reiner Pope" <some address.com> kirjoitti viestissä news:f95nqs$lk5$1 digitalmars.com...Paul Collier wrote:Ok, same list as above, once again, this time using const(this) for method constness (and dropping the const(func) from the list): const(this) const(P) func (P p) const(P) const(this) func (P p) const(P) func const(this) (P p) const(P) func:const(this) (P p) const(P) func (P p) const(this) Personally, I find all of these quite unreadable this time around, although I guess I could get used to it. Too many parenthesized consts. I'll do even a list with the parameter of the function as a const: const(this) const(P) func (const(P) p) const(P) const(this) func (const(P) p) const(P) func const(this) (const(P) p) const(P) func:const(this) (const(P) p) const(P) func (const(P) p) const(this) This is getting to where my eyes start to bleed. ;) I'd still have to say that the cleanest syntax, at least to me, seems to be the last one, with the method constness indicator after the parameter list.Rioshin an'Harthen wrote:Although the idea is nice, I tried it out, and I don't like the look of it: int const(getFoo)() { return foo; } My main objection is that the const() is around getFoo, so you're saying that the function won't change -- but how can it, it's static data. What you really mean when you are saying it's a const function is that the this object is constant. So how about that? const(this) int getFoo() { return foo; } (It's syntactically unambiguous because this is a keyword)Same list, this time a const func returning a const return value: const const(P) func (P p) const(P) const func (P p) const(P) const(func) (P p) const(P) func const (P p) const(P) func:const (P p) const(P) func (P p) const I definitely prefer the last one as the cleanest of these.Just chiming in on a slightly different note... the line that stuck out in both examples for me was actually the const(func) line. That seems really intuitive and consistent with the const syntax elsewhere. I do find the const-on-the-end readable too, but really mostly because of familiarity with C++ ;)
Aug 06 2007
Chris Nicholson-Sauls schrieb:Daniel919 wrote:But they are not the same: const x = 1; doesn't take up space final const(int) x = 1; does take up space Example: struct A { const constx = 1; } struct B { final const(int) x = 1; } A.sizeof == 1 B.sizeof == 4I've got some ideas about how to make the const syntax more consistent. First I will show you the current situation. Then I will list the confusions and possible solutions. Some days ago I already mentioned my first idea on IRC, but got no replies. Also I know that you, Walter, hardly don't change features, which already have been implemented. And my suggestions would require this of course. The "define proposal" is not such a big change in the language, in opposite to the much more important idea about "putting the return type in a bracket at the end". Because this is what the last idea requires, it's written after "WAIT:". Nevertheless I will give it a try, because 2.0 is still alpha and it will break code compatibility anyway. currently the keyword const(/invariant) has three meanings: ----------------------------------------------------------- 1. alone: const x = 1; compile-time variable (not an lvalue)Well technically if that was what I wanted, I'd use one of 'invariant x = 1;' or a more explicit 'final invariant(int) x = 1;'.2. with(): const(P) p = new Point(1,2); run-time object, which is protected from changesWell, protected from changes via this reference... but yeah. I'd say the 'const(type)' case would/should be used most often anyhow.3. alone: const P func(P p) { writefln(p.x, " ", p.y); }; attribute for a member function: the function can't change any class fieldsget into that one below.confusions and solutions: ------------------------- 1. const x = 1; 2. const(P) p = new Point(1,2); you see const first and later recognize the brackets one would not expect brackets to lead to a completely different meaning of the forrun keywordMy eyes are trained to spot them... still yes, a sudden shift in meaning can be counter-intuitive. Although its not entirely a shift... you could probably think of 'const x = 1;' as shorthand for 'final const(int) x = 1;'.You might think about spoken languages: You learn more vocabularies to be able to differentiate better, so you are more capable to express what you mean, instead of relying on an absolutely small subset of vocabularies. PS: "auto" also was a new keyword some time ago ;) "define" is also known from C/C++ world to define something you can't change, equivalent to what const x = 1; acutally means: not an lvalue. In my opinion it's better to have a different keyword for something different, and "define" makes much sense for me.1. define x = 1; 2. const(P) p = new Point(1,2); can't be confused anymore, different keywords define defines a compile-time variable const / invariant has nothing to do with compile-time anymore. it only means protectionAdding new keywords is usually the absolute last option around here. (There was talk ages past of replacing 'auto x = 1' with 'let x = 1'.)You are right, it really looks like a template instatiation. So lets try without the ! on declaration: func(T) (T var) (T) //IFTI take T return T func(T) (T var) //IFTI take T func(T) () (T) //IFTI return T func(T) //IFTI func(T var) (T) // take T return T func(T var) // take T func() (T) // return T func() // At least one () should remain, to make clear that it's a function Before the return brackets there must always be the take brackets. So 4. can only mean IFTI. This looks good in my opinion. To compare with the current syntax: T func(T) (T var) //IFTI take T return T void func(T) (T var) //IFTI take T T func(T) () //IFTI return T void func(T) () //IFTI T func(T var) // take T return T void func(T var) // take T T func() // return T void func() //3. const P func(P p) { ... } reads like: func returns a const(P)Which is, indeed, a problem -- in that I agree.const / invariant alone (without brackets) is an attribute and has no other meaning further proposal: returned types in a bracket at the end: 3. const func (P p) (P) { ... } //templated syntax: const func!(T) (T p) (T) { ... }Uhm. Ew. No, seriously, I just could not possibly handle that; I would keep thinking I saw templates where there aren't any. Worse yet, for a long time I'll see the '!(' and keep wondering how I could be instantiating a template in that position, when its really a template declaration. T'is a naughty naughty thing to mix the two -- would give both the compiler and the user headaches. IMHO, its the'const'/'invariant' keyword on methods that needs to move -- not sure where it should go, though. What looks best down here? ;) (First listing is the current state, for reference.) const P vunc (P p) { ... } P const func (P p) { ... } P const:func (P p) { ... } P const(func) (P p) { ... } P func const (P p) { ... } P func:const (P p) { ... } P func (P p) const { ... }I would suggest const: P func (P p) { ... } Not allowed: const: ... func1 ... ... func2 ... You always have to explicitly mention the "const:" for each function. This way the "attribute feeling" is retained.Yes, there seem to be a lot of people not being very happy with the current const syntax. But I have not seen much concrete suggestion how to make it better. Best regards, Daniel1. same meaning: invariant x = 1; const x = 1;For basic types, there often isn't much difference anyhow. Except that invariant members of structures allocate no memory in the structure, for example.not allowed anymore: const(/invariant) alone is an attribute, instead use: 1. define x = 1; //this is ok: final int x = 1; const(int)* xptr = &x; // but: 2. const(int) x = 1; this is nonsense and also atm it could be confused with: 1. const int x = 1; the compiler should issue at least a warning, and instead you should use: 1. define x = 1; void func(const P p) { typeof(p) == const(P) } bad, because one could expect this to be also valid then: const P p = new P(1,2); //but fails of course correctly is has to be: void func(const(P) p) { ... } void func(ref const(P) p) { p = new P(3,4); } //OK compiler should issue an error const(/invariant) alone is an attribute WAIT: ----- because we have another syntax for compile-time variables now, we could say that: const P** ptr2ptr2P means: const(P**) ptr2ptr2P because if it wasn't: const P** func() { ... } would not only be confused with, but it would be THE SAME as: const(P**) func() { ... } then the correct form would have to be: const func() (const P**) { ...} this would be nonsense, because it would be the same as: const(int) x = 1; so the compiler should issue at least a warning PS: Having the return types in a bracket at the end, would make it possible to implement multiple return values / return tuples in a consistent way, too. It would also allow more tricks, like returning local values of a function, avoiding ref, etc etc ... I would really enjoy to get some replies (especially yours, Walter), even if it's just a: "No that's totally stupid" ;) Best regards, DanielNo that's totally stupid. Ahh I'm just kidding. At least you're thinking about the situation and offering suggestions. (And welcome to the tiny militia of 'const R func()' syntax detractors. ;)) The final/const/invariant system needs some good hammering yet -- although its off to a lovely start, danke Walter. -- Chris Nicholson-Sauls
Aug 06 2007
Daniel919 wrote:Chris Nicholson-Sauls schrieb:Just like 'invariant' does. Gotcha. Maybe the rule should be as I "suggested" with the implication that 'final' values of a basic type and an in-place initializer do not take up space? Or at least in the context of final+const|invariant. Then again, the current behavior at least works.Daniel919 wrote:But they are not the same: const x = 1; doesn't take up space final const(int) x = 1; does take up spaceconfusions and solutions: ------------------------- 1. const x = 1; 2. const(P) p = new Point(1,2); you see const first and later recognize the brackets one would not expect brackets to lead to a completely different meaning of the forrun keywordMy eyes are trained to spot them... still yes, a sudden shift in meaning can be counter-intuitive. Although its not entirely a shift... you could probably think of 'const x = 1;' as shorthand for 'final const(int) x = 1;'.Granted; I'm just saying it'll be more work to sell a new keyword. Your nomination of 'define' is itself sound. (I'm sure we'll never get the Ruby rule of "just start the name with a capital letter". ;))Adding new keywords is usually the absolute last option around here. (There was talk ages past of replacing 'auto x = 1' with 'let x = 1'.)You might think about spoken languages: You learn more vocabularies to be able to differentiate better, so you are more capable to express what you mean, instead of relying on an absolutely small subset of vocabularies. PS: "auto" also was a new keyword some time ago ;) "define" is also known from C/C++ world to define something you can't change, equivalent to what const x = 1; acutally means: not an lvalue. In my opinion it's better to have a different keyword for something different, and "define" makes much sense for me.Its... different. And I suppose workable, particularly if it were made optional -- that is, let the current syntax stand, and allow this as an alternate syntax. I do like the idea of: func() { ... } Being apparently equivelant to: void func() { ... } I think perhaps I'm just too "fond" (ie, comfortable, familiar) with the 'M... R func(A)' syntax and therefore scared to change it. Especially since it'd be a radical change at this point in the game. (At least for D/1.0)You are right, it really looks like a template instatiation. So lets try without the ! on declaration: func(T) (T var) (T) //IFTI take T return T func(T) (T var) //IFTI take T func(T) () (T) //IFTI return T func(T) //IFTI func(T var) (T) // take T return T func(T var) // take T func() (T) // return T func() // At least one () should remain, to make clear that it's a function Before the return brackets there must always be the take brackets. So 4. can only mean IFTI. This looks good in my opinion.further proposal: returned types in a bracket at the end: 3. const func (P p) (P) { ... } //templated syntax: const func!(T) (T p) (T) { ... }Uhm. Ew. [etc]Actually... I like it.'const'/'invariant' keyword on methods that needs to move -- not sure where it should go, though. What looks best down here? ;) (First listing is the current state, for reference.) const P vunc (P p) { ... } P const func (P p) { ... } P const:func (P p) { ... } P const(func) (P p) { ... } P func const (P p) { ... } P func:const (P p) { ... } P func (P p) const { ... }I would suggest const: P func (P p) { ... } Not allowed: const: ... func1 ... ... func2 ... You always have to explicitly mention the "const:" for each function. This way the "attribute feeling" is retained.Its a tough nut to crack. Chances are we really need to just do something crazy and new... its the coming-up-with-something-new part that's hard. A 'func(T...)(A...)(R)' function syntax, though. Now that's new. :) -- Chris Nicholson-Sauls[snip] At least you're thinking about the situation and offering suggestions. (And welcome to the tiny militia of 'const R func()' syntax detractors. ;)) The final/const/invariant system needs some good hammering yet -- although its off to a lovely start, danke Walter.Yes, there seem to be a lot of people not being very happy with the current const syntax. But I have not seen much concrete suggestion how to make it better.
Aug 06 2007
Chris Nicholson-Sauls Wrote:It's not that it's a bad idea, but there's some inner aversion to it in me. [Return type] [name] [args] has been a staple of C-based languages (and, indeed, strongly-typed languages in general). Personally, I like the const semantics except: - Compile time constants should be "invariant" only. invariant int x = 3; const int y = 3; Both x and y are compile-time constants... - Class invarinats should be better disambiguated. Personally, I like the idea of "readonly" replacing cost and "const" replacing invariant, with invariant reserved for class invarinats (thus keeping some degree of backwards compatibility).Yes, there seem to be a lot of people not being very happy with the current const syntax. But I have not seen much concrete suggestion how to make it better.Its a tough nut to crack. Chances are we really need to just do something crazy and new... its the coming-up-with-something-new part that's hard. A 'func(T...)(A...)(R)' function syntax, though. Now that's new. :) -- Chris Nicholson-Sauls
Aug 06 2007
On Sun, 05 Aug 2007 14:42:09 +0200, Daniel919 wrote:The "define proposal" is not such a big change in the language,I love the 'define' proposal. It is totally unambiguous and clear what is intended by the code writer, and totally unambiguous and clear about what we expect of the compiler. -- Derek Parnell Melbourne, Australia "Down with mediocrity!"
Aug 06 2007
Derek Parnell wrote:On Sun, 05 Aug 2007 14:42:09 +0200, Daniel919 wrote:What I think would really rock is if 'define' could also be used for types and maybe expressions. I've long felt it was silly that aliases were backwards from normal assignments. define x = 1; define myInt = int; I'd love that. Then just get rid of alias. :-) Or maybe just allow alias to use either syntax: alias x = 1; alias 1 x; alias myInt = some_complex_expr_to_compute_a_type!(int); alias some_complex_expr_to_compute_a_type!(int) myInt; In my opinion it's a lot easier to read the assignment syntax (alias sym=thing) than the current alias syntax (alias thing sym). Mainly because, as you see above, often the 'thing' is really long, but usually the 'sym' is something very short. It makes it easier to see the thing you care about in the end which is the sym that comes out of the statement that you'll be using in subsequent code. --bbThe "define proposal" is not such a big change in the language,I love the 'define' proposal. It is totally unambiguous and clear what is intended by the code writer, and totally unambiguous and clear about what we expect of the compiler.
Aug 07 2007
Bill Baxter wrote:Derek Parnell wrote:As I understand it, the reason alias syntax is like this, is so the compiler can simply parse the alias as though it were a normal 'Type symbol;' decleration -- just like variables and functions (up until argument lists). That said, I don't imagine it would be difficult to have something of a separator in there instead, either '=' as suggested or even ':' as used to specify inheritance of classes and enums. Hmm. In fact, maybe have '=' expect an expression to define a compile-time constant, and ':' expect a type to define an alias as per current behavior. alias x = 1 ; alias myInt : some_complex_expr_to_compute_a_type!(int) ; Just thinking "aloud." -- Chris Nicholson-SaulsOn Sun, 05 Aug 2007 14:42:09 +0200, Daniel919 wrote:What I think would really rock is if 'define' could also be used for types and maybe expressions. I've long felt it was silly that aliases were backwards from normal assignments. define x = 1; define myInt = int; I'd love that. Then just get rid of alias. :-) Or maybe just allow alias to use either syntax: alias x = 1; alias 1 x; alias myInt = some_complex_expr_to_compute_a_type!(int); alias some_complex_expr_to_compute_a_type!(int) myInt; In my opinion it's a lot easier to read the assignment syntax (alias sym=thing) than the current alias syntax (alias thing sym). Mainly because, as you see above, often the 'thing' is really long, but usually the 'sym' is something very short. It makes it easier to see the thing you care about in the end which is the sym that comes out of the statement that you'll be using in subsequent code. --bbThe "define proposal" is not such a big change in the language,I love the 'define' proposal. It is totally unambiguous and clear what is intended by the code writer, and totally unambiguous and clear about what we expect of the compiler.
Aug 07 2007
Bill Baxter wrote:Or maybe just allow alias to use either syntax: alias x = 1; alias 1 x; alias myInt = some_complex_expr_to_compute_a_type!(int); alias some_complex_expr_to_compute_a_type!(int) myInt; In my opinion it's a lot easier to read the assignment syntax (alias sym=thing) than the current alias syntax (alias thing sym). Mainly because, as you see above, often the 'thing' is really long, but usually the 'sym' is something very short. It makes it easier to see the thing you care about in the end which is the sym that comes out of the statement that you'll be using in subsequent code. --bbI think that would be just great. I hate having to write two templates, one for values and one for aliases. It's quite un-generic. A good example is the identity function that Andrei is keen on. It's a fair bit of work to write with templates, so that it works with types, values, and expression aliases: template Identity(T...) { static if (!is(T[0])) const Identity = T[0]; else alias T[0] Identity; } // testing static assert(is(Identity!(int) == int)); static assert(Identity!(5) == 5); int x; void main() { Identity!(x) = Identity!(5); assert(x == 5); } This currently works, but I'm not sure why[1], and it is annoying to require that. I would like to be able to write template Identity(T...) { alias T[0] Identity; } but that currently doesn't work when T[0] is a value parameter. This does actually cause problems with writing compile-time util templates, like FoldR: template FoldR(alias Fn, T...) { static if (T.length == 0) static assert(false, "Must have starting case for FoldR"); else static if (T.length == 1) { static if (is(T[0])) alias T[0] FoldR; else const FoldR = T[0]; } else { // I have to repeat this ugly recursive instantiation 3 times // because I can't keep the result -- do I alias it or use const? static if (is(FoldR!(Fn, Fn!(T[0], T[1]).val, T[2..$]))) alias FoldR!(Fn, Fn!(T[0], T[1]).val, T[2..$]) FoldR; else const FoldR = FoldR!(Fn, Fn!(T[0], T[1]).val, T[2..$]); } } So I think having alias work for values as well as types/symbols would be great. I'm not so fussed either way about alias x = int; I can see it reads better in some situations, though, and I don't see it causing any problems if both were allowed. -- Reiner [1] Here's what's confusing me (I expect it's a bug). In the first code snippet I posted, the !is(T[0]) means that types are aliased, which is good, but the call to Identity!(x) doesn't use the alias, it uses the const Identity = T[0]; part. So what is happening is effectively this: // in the instantiation of Identity!(x) const Identity = x; // in main() Identity!(x).Identity = 5; We're reassigning a constant -- how does that work? -- but somehow that causes x to change... it's oddly doing the alias itself...
Aug 07 2007
I realize there are some consistency issues with the current syntax for const, but it is more complicated than expected. Your idea to separate out compile time constants with a new keyword is a good one, and is similar to one Andrei came up with (using alias).
Aug 06 2007
Walter Bright wrote:I realize there are some consistency issues with the current syntax for const, but it is more complicated than expected. Your idea to separate out compile time constants with a new keyword is a good one, and is similar to one Andrei came up with (using alias).I hadn't even considered alias. Was his idea roughly that have having "two" aliases, one of the form 'alias symbol symbol' and the other 'alias expression symbol'? Depending on how difficult it would be to implement, it might just work. If it was something else entirely, then I missed that one. -- Chris Nicholson-Sauls
Aug 07 2007
Walter Bright wrote:I realize there are some consistency issues with the current syntax for const, but it is more complicated than expected. Your idea to separate out compile time constants with a new keyword is a good one, and is similar to one Andrei came up with (using alias).If anyone is interested, there was a brief discussion on this in the D Const Design Rationale thread here: http://www.digitalmars.com/d/archives/digitalmars/D/D_const_design_rationale_54725.html#N54844 Interestingly, the use of both 'define' and 'alias' were suggested (as well as a 'literal' keyword), so it seems like those two might be quite intuitive syntaxes. -- Reiner
Aug 07 2007