digitalmars.D - DMD can implicitly convert class pointer to the bool. Is it bug or
- ilya-stromberg (35/35) Nov 24 2013 Code examle:
- Maxim Fomin (2/5) Nov 24 2013 This is neither bug not a terribale feature. Have you coded in C?
- ilya-stromberg (5/7) Nov 24 2013 Yes, only a little. I like D because it dissallow most of
- Maxim Fomin (8/15) Nov 24 2013 void* ptr;
- ilya-stromberg (24/28) Nov 24 2013 Small code change:
- Maxim Fomin (6/35) Nov 24 2013 Yes, because D is separate language, and its comparison operator
- Ary Borenszweig (4/29) Nov 24 2013 Ugh, if the compiler disallows comparison of reference with "==" and
- Jonathan M Davis (6/50) Nov 24 2013 Likely because using == indicates a misunderstanding of what == does and...
- Steven Schveighoffer (13/21) Jan 16 2014 The reason for this was a long fought battle with Walter. f == null woul...
- deadalnix (4/22) Nov 24 2013 No, it is a comparaison with 0. If NULL is 0 on all modern
- Maxim Fomin (7/28) Nov 24 2013 It is comparison with NULL and zero (I though it is obvious that
- deadalnix (2/8) Nov 24 2013 http://c-faq.com/null/machexamp.html
- Maxim Fomin (13/21) Nov 24 2013 You confused runtime bit pattern and zero integer constant. NULL
- ilya-stromberg (3/4) Nov 24 2013 The root of the issue is identifier shadowing, see:
- bearophile (5/6) Nov 24 2013 I think the implicit question of ilya-stromberg was: how much
- Maxim Fomin (3/9) Nov 24 2013 OK. What are the problems with converting class references to
- ilya-stromberg (21/25) Nov 24 2013 Yes, exactly. I personally was VERY surprised. My code example
- Maxim Fomin (6/33) Nov 24 2013 This is identifiers shadowing issue. In best case you could not
- ilya-stromberg (14/20) Nov 24 2013 Yes, I agree that it's also can be identifiers shadowing issue.
- Maxim Fomin (31/51) Nov 24 2013 Many people complain about language features which are really
- ilya-stromberg (8/9) Nov 24 2013 Sorry if I didn't explain the example properly.
- Maxim Fomin (5/14) Nov 24 2013 Yes, it is possible, but AFAIK Walter is opposite because he 1)
- bearophile (16/19) Nov 24 2013 See also the discussion here:
- Maxim Fomin (7/26) Nov 24 2013 Yes, it is confusing. It is especially confusing in an unstable
- Walter Bright (6/11) Nov 24 2013 In what way are D namespace rules unclear? Please file bugzilla reports ...
- Andrei Alexandrescu (4/29) Nov 24 2013 If uncommented that would make for a shadow definition error. In brief I...
- bearophile (13/33) Nov 24 2013 Are you saying this code gives or should give errors?
- Andrei Alexandrescu (6/16) Nov 24 2013 Sorry, I misread the example - thought it's a function local variable.
- Walter Bright (14/18) Nov 24 2013 Shadowing globals is definitely a bad idea. Shadowing members, it's deba...
- ilya-stromberg (6/13) Nov 24 2013 We can allow shadowing members only for function parameters or,
- Walter Bright (3/5) Nov 24 2013 We could, but at the cost of D becoming more of a mass of special cases ...
- ilya-stromberg (13/19) Nov 24 2013 See also:
- bearophile (15/24) Nov 24 2013 So are you saying D here should give an error for the shadowing
- Walter Bright (3/17) Nov 24 2013 I posted an objection there :-)
- ilya-stromberg (3/7) Nov 24 2013 But we can provide a syntax sugar for this case as was suggested
- Andrei Alexandrescu (5/10) Nov 24 2013 I think he meant "shadowing locals". As I wrote in TDPL, it's a bad idea...
- ilya-stromberg (6/19) Nov 24 2013 Yes, but D allows to use it. And in few cases global variable can
- Andrei Alexandrescu (4/21) Nov 24 2013 I agree. What I'm saying is it's not good to make shadowing a global an
- Craig Dillabaugh (11/40) Nov 24 2013 Would it be possible to introduce a global scope of sorts that
- Andrei Alexandrescu (4/13) Nov 24 2013 To put it bluntly, many things are possible but it seems the best is to
- ilya-stromberg (8/25) Nov 25 2013 I personally like Craig Dillabaugh's sugestion. But we can use
- ilya-stromberg (5/32) Nov 25 2013 Sorry if I didn't explain idea properly.
- Maxim Fomin (4/13) Nov 25 2013 And what to do with code already written? What exactly should be
- ilya-stromberg (2/18) Nov 25 2013 OK, I see.
- Craig Dillabaugh (10/26) Nov 25 2013 One of the things I had in mind with my idea at least, was that
- Andrei Alexandrescu (3/26) Nov 25 2013 Doesn't that work already?
- Walter Bright (3/14) Nov 25 2013 Sure, but only because I saw the suggestion and traveled back in time to...
- ilya-stromberg (3/14) Nov 25 2013 I repeat, sorry if I didn't explain idea properly, see:
- Chris Cain (8/10) Nov 26 2013 Like Maxim explained, it's a breaking change to force it.
- ilya-stromberg (4/14) Nov 26 2013 Yes, I already understood this.
- bearophile (5/8) Nov 26 2013 That is named "relying on hand-managed name conventions for
- ilya-stromberg (14/20) Nov 26 2013 Yes, exactly.
- Chris Cain (10/12) Nov 26 2013 Sure. It'd have been nice if the language was designed to avoid
- ilya-stromberg (4/16) Nov 26 2013 Yes, but D/Phobos depreciates/removes a lot of different things.
- bearophile (22/33) Nov 26 2013 This discussion is becoming more interesting, thank you :-)
- Andrei Alexandrescu (7/17) Nov 26 2013 The problem is "you" who added the global and "you" whose code is broken...
- bearophile (7/9) Nov 26 2013 When you have code written by another person, and you add a
- Andrei Alexandrescu (4/10) Nov 26 2013 Someone else adds a global to the code they wrote, with which you build....
- Walter Bright (2/5) Nov 26 2013 That's going to work out not so great for anyone developing a 3rd party ...
- deadalnix (2/10) Nov 26 2013 http://i.imgur.com/H838hA9.jpg
- bearophile (8/9) Nov 26 2013 AH ah, thank you :-) Eventually the official lint will need to
- ilya-stromberg (6/9) Nov 26 2013 So, we have a few suggestions in this thread like:
- Namespace (3/13) Nov 26 2013 Let us vote. I am against 1 .. 3
- Andrei Alexandrescu (7/16) Nov 26 2013 Maybe (2) has something going for it, but (1) and (3) are definite
- ilya-stromberg (12/14) Nov 26 2013 Excuse me, did you mean "disable shadowing global variables" or
- Andrei Alexandrescu (6/17) Nov 26 2013 I think Walter agrees that we can't disallow shadowing globals. Adding
- ilya-stromberg (18/42) Nov 26 2013 Thanks for explanation.
- Andrei Alexandrescu (16/54) Nov 26 2013 It is possible to the extent a lot of things are. But at this point:
- ilya-stromberg (14/21) Nov 26 2013 Thanks for explanation. I really don't understand what's a
- Walter Bright (2/3) Nov 26 2013 I agree with Andrei. The current situation is the best solution.
- Maxim Fomin (3/11) Nov 26 2013 Alternatively, one can start (enforce) using dot operator before
- bearophile (35/40) Nov 24 2013 I understand. It's not a clear cut topic. There are real reasons
- Andrei Alexandrescu (5/9) Nov 24 2013 This is just speculation. It would have been helpful if enabling
- ilya-stromberg (7/11) Nov 24 2013 No, isn't just speculation.
- Jonathan M Davis (9/14) Nov 24 2013 Not at all, and most people coming from C/C++ would likely be annoyed to...
- Dicebot (3/6) Nov 24 2013 Not exactly. It is all about "if" condition. AFAIK, D defines
- ilya-stromberg (10/14) Nov 24 2013 Not exactly.
- Maxim Fomin (20/34) Nov 24 2013 Because '!' operator provides boolean context. It is written in
- ilya-stromberg (5/6) Nov 24 2013 Yes, but it's ambiguously. What should compiler to use:
- Maxim Fomin (9/15) Nov 24 2013 And if instance is null, where compiler can look for opCast?
- deadalnix (2/16) Nov 24 2013
Code examle: import std.stdio; class Foo { } void main() { Foo f; if(f) { writeln("f is true"); } else { writeln("f is false"); } f = new Foo(); if(f) { writeln("f is true"); } else { writeln("f is false"); } } Programm output: f is false f is true So, pointer implicitly converts to false if pointer is null and to true if pointer is not null. Is it bug or terrible feature? Note that we have `f is null` syntax for these cases.
Nov 24 2013
On Sunday, 24 November 2013 at 13:49:25 UTC, ilya-stromberg wrote:So, pointer implicitly converts to false if pointer is null and to true if pointer is not null. Is it bug or terrible feature? Note that we have `f is null` syntax for these cases.This is neither bug not a terribale feature. Have you coded in C?
Nov 24 2013
On Sunday, 24 November 2013 at 13:57:22 UTC, Maxim Fomin wrote:This is neither bug not a terribale feature. Have you coded in C?Yes, only a little. I like D because it dissallow most of dangerous abbilities. We already have `is` operator for pointer comparison. Class doesn't provide cast to bool. So, why it's allowed?
Nov 24 2013
On Sunday, 24 November 2013 at 14:02:43 UTC, ilya-stromberg wrote:On Sunday, 24 November 2013 at 13:57:22 UTC, Maxim Fomin wrote:void* ptr; if(ptr) was a shortcut for 'if(ptr != NULL)' probably since C was created. There is no problem with classes or pointers convertion to booleans in condition statements, it is not a dangerous ability. Is operator is not restricted to pointer comparison, you can use it to bitwise compare any objects.This is neither bug not a terribale feature. Have you coded in C?Yes, only a little. I like D because it dissallow most of dangerous abbilities. We already have `is` operator for pointer comparison. Class doesn't provide cast to bool. So, why it's allowed?
Nov 24 2013
On Sunday, 24 November 2013 at 14:12:18 UTC, Maxim Fomin wrote:void* ptr; if(ptr) was a shortcut for 'if(ptr != NULL)' probably since C was created.Small code change: import std.stdio; class Foo { } void main() { Foo f; if(f == null) { writeln("f is true"); } if(f != null) { writeln("f is false"); } } DMD output: Error: use 'is' instead of '==' when comparing with null Error: use '!is' instead of '!=' when comparing with null So, C style 'if(ptr != NULL)' isn't allowed in D.
Nov 24 2013
On Sunday, 24 November 2013 at 14:18:50 UTC, ilya-stromberg wrote:On Sunday, 24 November 2013 at 14:12:18 UTC, Maxim Fomin wrote:Yes, because D is separate language, and its comparison operator does something special when operands are class references. This is not the same story as in 'if(f)' which is purely bitwise comparison. I think your question is more appropriate for d.learn.void* ptr; if(ptr) was a shortcut for 'if(ptr != NULL)' probably since C was created.Small code change: import std.stdio; class Foo { } void main() { Foo f; if(f == null) { writeln("f is true"); } if(f != null) { writeln("f is false"); } } DMD output: Error: use 'is' instead of '==' when comparing with null Error: use '!is' instead of '!=' when comparing with null So, C style 'if(ptr != NULL)' isn't allowed in D.
Nov 24 2013
On 11/24/13 11:18 AM, ilya-stromberg wrote:On Sunday, 24 November 2013 at 14:12:18 UTC, Maxim Fomin wrote:Ugh, if the compiler disallows comparison of reference with "==" and "!=" and tells you to use "is" and "!is", can't compiler just allow you to write "==" and understand it as "is"? What's the big deal?void* ptr; if(ptr) was a shortcut for 'if(ptr != NULL)' probably since C was created.Small code change: import std.stdio; class Foo { } void main() { Foo f; if(f == null) { writeln("f is true"); } if(f != null) { writeln("f is false"); } } DMD output: Error: use 'is' instead of '==' when comparing with null Error: use '!is' instead of '!=' when comparing with null
Nov 24 2013
On Sunday, November 24, 2013 18:38:19 Ary Borenszweig wrote:On 11/24/13 11:18 AM, ilya-stromberg wrote:Likely because using == indicates a misunderstanding of what == does and how null works. Conceptually, == and is are two very different operations, and they shouldn't be mixed up. Also, using == null incurs some extra overhead, because it ends up calling opEquals. - Jonathan M DavisOn Sunday, 24 November 2013 at 14:12:18 UTC, Maxim Fomin wrote:Ugh, if the compiler disallows comparison of reference with "==" and "!=" and tells you to use "is" and "!is", can't compiler just allow you to write "==" and understand it as "is"? What's the big deal?void* ptr; if(ptr) was a shortcut for 'if(ptr != NULL)' probably since C was created.Small code change: import std.stdio; class Foo { } void main() { Foo f; if(f == null) { writeln("f is true"); } if(f != null) { writeln("f is false"); } } DMD output: Error: use 'is' instead of '==' when comparing with null Error: use '!is' instead of '!=' when comparing with null
Nov 24 2013
On Sun, 24 Nov 2013 16:38:19 -0500, Ary Borenszweig <ary esperanto.org.ar> wrote:On 11/24/13 11:18 AM, ilya-stromberg wrote:The reason for this was a long fought battle with Walter. f == null would crash if f actually WAS null (compiler did blind rewrite to f.opEquals(null), which is a virtual call). This was the solution we could get Walter to implement, and that was a pretty big accomplishment after his opposition :) The rewrite could be done too, but this implementation is actually how Walter was convinced -- it flagged several cases in Phobos where he had done that and didn't realize it. However, x == y has since been changed to forward to object.opEquals(x, y), which can handle null parameters in either position, so this "error" is actually unneeded, and could be removed (I'd recommend removing it). -SteveDMD output: Error: use 'is' instead of '==' when comparing with null Error: use '!is' instead of '!=' when comparing with nullUgh, if the compiler disallows comparison of reference with "==" and "!=" and tells you to use "is" and "!is", can't compiler just allow you to write "==" and understand it as "is"? What's the big deal?
Jan 16 2014
On Sunday, 24 November 2013 at 14:12:18 UTC, Maxim Fomin wrote:On Sunday, 24 November 2013 at 14:02:43 UTC, ilya-stromberg wrote:No, it is a comparaison with 0. If NULL is 0 on all modern architectures I know of, this wasn't always the case.On Sunday, 24 November 2013 at 13:57:22 UTC, Maxim Fomin wrote:void* ptr; if(ptr) was a shortcut for 'if(ptr != NULL)' probably since C was created.This is neither bug not a terribale feature. Have you coded in C?Yes, only a little. I like D because it dissallow most of dangerous abbilities. We already have `is` operator for pointer comparison. Class doesn't provide cast to bool. So, why it's allowed?There is no problem with classes or pointers convertion to booleans in condition statements, it is not a dangerous ability. Is operator is not restricted to pointer comparison, you can use it to bitwise compare any objects.I'd like to know why this feature is dangerous as well.
Nov 24 2013
On Sunday, 24 November 2013 at 20:38:29 UTC, deadalnix wrote:On Sunday, 24 November 2013 at 14:12:18 UTC, Maxim Fomin wrote:It is comparison with NULL and zero (I though it is obvious that the code snippet is written in C), because NULL is always zero by definition ("an integer constant expression with the value 0, or such an expression casted to void*"). If this is not the case, then implementation is broken. Which of them you are talking about?On Sunday, 24 November 2013 at 14:02:43 UTC, ilya-stromberg wrote:No, it is a comparaison with 0. If NULL is 0 on all modern architectures I know of, this wasn't always the case.On Sunday, 24 November 2013 at 13:57:22 UTC, Maxim Fomin wrote:void* ptr; if(ptr) was a shortcut for 'if(ptr != NULL)' probably since C was created.This is neither bug not a terribale feature. Have you coded in C?Yes, only a little. I like D because it dissallow most of dangerous abbilities. We already have `is` operator for pointer comparison. Class doesn't provide cast to bool. So, why it's allowed?
Nov 24 2013
On Sunday, 24 November 2013 at 21:00:53 UTC, Maxim Fomin wrote:It is comparison with NULL and zero (I though it is obvious that the code snippet is written in C), because NULL is always zero by definition ("an integer constant expression with the value 0, or such an expression casted to void*"). If this is not the case, then implementation is broken. Which of them you are talking about?http://c-faq.com/null/machexamp.html
Nov 24 2013
On Sunday, 24 November 2013 at 21:13:12 UTC, deadalnix wrote:On Sunday, 24 November 2013 at 21:00:53 UTC, Maxim Fomin wrote:You confused runtime bit pattern and zero integer constant. NULL is always zero integer constant (probably casted to void*) by definition. http://c-faq.com/null/varieties.html if(ptr) is as good as if(ptr != 0) or if(ptr != NULL) regardless of null bit pattern "The internal (or run-time) representation of a null pointer, which may or may not be all-bits-0 and which may be different for different pointer types. The actual values should be of concern only to compiler writers. Authors of C programs never see them, since they use..The null pointer constant, which is a constant integer 0 "It is comparison with NULL and zero (I though it is obvious that the code snippet is written in C), because NULL is always zero by definition ("an integer constant expression with the value 0, or such an expression casted to void*"). If this is not the case, then implementation is broken. Which of them you are talking about?http://c-faq.com/null/machexamp.html
Nov 24 2013
On Sunday, 24 November 2013 at 20:38:29 UTC, deadalnix wrote:I'd like to know why this feature is dangerous as well.The root of the issue is identifier shadowing, see: http://forum.dlang.org/post/hvxvllyafxnyvjooxhjh forum.dlang.org
Nov 24 2013
Maxim Fomin:This is neither bug not a terribale feature.I think the implicit question of ilya-stromberg was: how much bug-prone is this language feature? Bye, bearophile
Nov 24 2013
On Sunday, 24 November 2013 at 14:16:39 UTC, bearophile wrote:Maxim Fomin:OK. What are the problems with converting class references to true when they are not null and false when they are null?This is neither bug not a terribale feature.I think the implicit question of ilya-stromberg was: how much bug-prone is this language feature? Bye, bearophile
Nov 24 2013
On Sunday, 24 November 2013 at 14:16:39 UTC, bearophile wrote:Maxim Fomin:Yes, exactly. I personally was VERY surprised. My code example from real life: class Foo { } class Bar { Foo f; void bar() { //variable was wrongly commented here //bool f = true; if(f) { //Oops! } } }This is neither bug not a terribale feature.I think the implicit question of ilya-stromberg was: how much bug-prone is this language feature?
Nov 24 2013
On Sunday, 24 November 2013 at 14:32:16 UTC, ilya-stromberg wrote:On Sunday, 24 November 2013 at 14:16:39 UTC, bearophile wrote:This is identifiers shadowing issue. In best case you could not define boolean f, so the problem would not arise in a first place. Anyway, many artifical examples can be provided which shows that some features behave in unexpected ways which is not a reason that they are bad.Maxim Fomin:Yes, exactly. I personally was VERY surprised. My code example from real life: class Foo { } class Bar { Foo f; void bar() { //variable was wrongly commented here //bool f = true; if(f) { //Oops! } } }This is neither bug not a terribale feature.I think the implicit question of ilya-stromberg was: how much bug-prone is this language feature?
Nov 24 2013
On Sunday, 24 November 2013 at 14:50:28 UTC, Maxim Fomin wrote:This is identifiers shadowing issue. In best case you could not define boolean f, so the problem would not arise in a first place.Yes, I agree that it's also can be identifiers shadowing issue. But we allow code like this: class Foo { int i; this(int i) { this.i = i; } }Anyway, many artifical examples can be provided which shows that some features behave in unexpected ways which is not a reason that they are bad.I repeat, this is REAL LIFE example. I just reduce it because it have unnecessary details for this case.
Nov 24 2013
On Sunday, 24 November 2013 at 15:01:34 UTC, ilya-stromberg wrote:On Sunday, 24 November 2013 at 14:50:28 UTC, Maxim Fomin wrote:Many people complain about language features which are really broken, misfunctiong, or both. Sometimes they point out on cases like: assert("Unexpected error occured"); which do not show feature failure, but language can be improved by rejecting or at least warning in such cases. However your case class Foo { } class Bar { Foo f; void bar() { //variable was wrongly commented here //bool f = true; if(f) { //Oops! } } } has nothing to do with either of these two types of defficiencies. No way compiler could guess that you have bool f in mind. There is no way to improve the language because it requires blocking class to bool conversion in boolean context which is pretty nice feature and there are plenty of code which has to be broken.This is identifiers shadowing issue. In best case you could not define boolean f, so the problem would not arise in a first place.Yes, I agree that it's also can be identifiers shadowing issue. But we allow code like this: class Foo { int i; this(int i) { this.i = i; } }Anyway, many artifical examples can be provided which shows that some features behave in unexpected ways which is not a reason that they are bad.I repeat, this is REAL LIFE example. I just reduce it because it have unnecessary details for this case.
Nov 24 2013
On Sunday, 24 November 2013 at 15:39:20 UTC, Maxim Fomin wrote:No way compiler could guess that you have bool f in mind.Sorry if I didn't explain the example properly. The `bool f` variable was in my code and it works correctly, but compiler didn't put attention that I have identifiers shadowing issue. After big code refactoring I wrongly commented the `bool f` variable. So, nothing happens if compiler provides identifier shadowing error - I'll just rename variable. Is it possible to implement?
Nov 24 2013
On Sunday, 24 November 2013 at 15:55:25 UTC, ilya-stromberg wrote:On Sunday, 24 November 2013 at 15:39:20 UTC, Maxim Fomin wrote:OK, root of the issue is identifier shadowing.No way compiler could guess that you have bool f in mind.Sorry if I didn't explain the example properly. The `bool f` variable was in my code and it works correctly, but compiler didn't put attention that I have identifiers shadowing issue. After big code refactoring I wrongly commented the `bool f` variable.So, nothing happens if compiler provides identifier shadowing error - I'll just rename variable. Is it possible to implement?Yes, it is possible, but AFAIK Walter is opposite because he 1) thinks shadowing is OK (and taking into account compability with C, this is dabatable), 2) does not like warnings.
Nov 24 2013
Maxim Fomin:This is identifiers shadowing issue. In best case you could not define boolean f, so the problem would not arise in a first place.See also the discussion here: http://d.puremagic.com/issues/show_bug.cgi?id=9521 Is it right for with to not give an error here? struct Foo { int x; } int x; void main() { Foo f; with (f) { x++; } } Silent shadowing of global (module-level in both Python and D) names has caused me many problems along the years. Bye, bearophile
Nov 24 2013
On Sunday, 24 November 2013 at 15:35:40 UTC, bearophile wrote:Maxim Fomin:Yes, it is confusing. It is especially confusing in an unstable language with absent adequate spec. For example, I can learn C namespace rules, but in D case it is useless. Unfortunately what is right in cases like above depends on what Walter & Andrei think so we stuck with their opinions on the subject. (I think emitting at least warning would be good)This is identifiers shadowing issue. In best case you could not define boolean f, so the problem would not arise in a first place.See also the discussion here: http://d.puremagic.com/issues/show_bug.cgi?id=9521 Is it right for with to not give an error here? struct Foo { int x; } int x; void main() { Foo f; with (f) { x++; } } Silent shadowing of global (module-level in both Python and D) names has caused me many problems along the years. Bye, bearophile
Nov 24 2013
On 11/24/2013 7:49 AM, Maxim Fomin wrote:Yes, it is confusing. It is especially confusing in an unstable language with absent adequate spec. For example, I can learn C namespace rules, but in D case it is useless. Unfortunately what is right in cases like above depends on what Walter & Andrei think so we stuck with their opinions on the subject.In what way are D namespace rules unclear? Please file bugzilla reports for any such, and mark them with the keyword 'spec'.(I think emitting at least warning would be good)I don't think there should be errors for shadowing globals for very good reasons, warnings are a generally bad solution to language issues, and changing the way scoping rules work would be the very definition of instability.
Nov 24 2013
On 11/24/13 6:32 AM, ilya-stromberg wrote:On Sunday, 24 November 2013 at 14:16:39 UTC, bearophile wrote:If uncommented that would make for a shadow definition error. In brief I think you'll have a hard time finding evidence that "if (p)" is dangerous. AndreiMaxim Fomin:Yes, exactly. I personally was VERY surprised. My code example from real life: class Foo { } class Bar { Foo f; void bar() { //variable was wrongly commented here //bool f = true; if(f) { //Oops! } } }This is neither bug not a terribale feature.I think the implicit question of ilya-stromberg was: how much bug-prone is this language feature?
Nov 24 2013
Andrei Alexandrescu:Are you saying this code gives or should give errors? class Foo {} class Bar { Foo f; void bar() { bool f = true; if (f) {} } } void main() {} Bye, bearophileclass Foo { } class Bar { Foo f; void bar() { //variable was wrongly commented here //bool f = true; if(f) { //Oops! } } }If uncommented that would make for a shadow definition error.
Nov 24 2013
On 11/24/13 9:39 AM, bearophile wrote:Are you saying this code gives or should give errors? class Foo {} class Bar { Foo f; void bar() { bool f = true; if (f) {} } } void main() {}Sorry, I misread the example - thought it's a function local variable. I'm not sure whether shadowing globals or members would be a good idea. gcc has a -W flag for that, and someone tried to turn it on at Facebook but with debatable results. We ended up not using that warning. Andrei
Nov 24 2013
On 11/24/2013 9:45 AM, Andrei Alexandrescu wrote:Sorry, I misread the example - thought it's a function local variable. I'm not sure whether shadowing globals or members would be a good idea. gcc has a -W flag for that, and someone tried to turn it on at Facebook but with debatable results. We ended up not using that warning.Shadowing globals is definitely a bad idea. Shadowing members, it's debatable. In any case, I don't think it is some sort of terrible bug generator. In fact, I'll often write: struct S { int m; this(int m) { this.m = m; } } because I like to make it clear I am initializing m. I find code like this to be unduly wretched: struct S { int m; this(int _m) { m = _m; } }
Nov 24 2013
On Sunday, 24 November 2013 at 18:23:51 UTC, Walter Bright wrote:Shadowing globals is definitely a bad idea. Shadowing members, it's debatable. In any case, I don't think it is some sort of terrible bug generator. In fact, I'll often write: struct S { int m; this(int m) { this.m = m; } }We can allow shadowing members only for function parameters or, maybe, only for constructor. Probably, your example is the most often case usage of shadowing members. In other hand, I can always rename local function variable because it isn't part of public API and should not confuse any users.
Nov 24 2013
On 11/24/2013 10:52 AM, ilya-stromberg wrote:We can allow shadowing members only for function parameters or, maybe, only for constructor.We could, but at the cost of D becoming more of a mass of special cases that nobody can remember.
Nov 24 2013
On Sunday, 24 November 2013 at 19:18:18 UTC, Walter Bright wrote:On 11/24/2013 10:52 AM, ilya-stromberg wrote:See also: http://d.puremagic.com/issues/show_bug.cgi?id=9801 Short description: disallow shadowing members, but provide special syntax for constructors like this: struct S { int m; this(this.m) { } } Should be the same as your example above. Other languages like Scala, CoffeeScript and TypeScript support a related but different syntax. So, not only I had problems with shadowing members.We can allow shadowing members only for function parameters or, maybe, only for constructor.We could, but at the cost of D becoming more of a mass of special cases that nobody can remember.
Nov 24 2013
Walter Bright:Shadowing globals is definitely a bad idea. Shadowing members, it's debatable.So are you saying D here should give an error for the shadowing of the module-level x? struct Foo { int x; } int x; void main() { Foo f; with (f) { x++; } }In any case, I don't think it is some sort of terrible bug generator. In fact, I'll often write: struct S { int m; this(int m) { this.m = m; } } because I like to make it clear I am initializing m.From my experience that's quite bug-prone: http://d.puremagic.com/issues/show_bug.cgi?id=3878 Bye, bearophile
Nov 24 2013
On 11/24/2013 11:17 AM, bearophile wrote:Walter Bright:I meant "bad" as in bad, not as in "good" :-)Shadowing globals is definitely a bad idea. Shadowing members, it's debatable.So are you saying D here should give an error for the shadowing of the module-level x? struct Foo { int x; } int x; void main() { Foo f; with (f) { x++; } }From my experience that's quite bug-prone: http://d.puremagic.com/issues/show_bug.cgi?id=3878I posted an objection there :-)
Nov 24 2013
On Sunday, 24 November 2013 at 19:59:51 UTC, Walter Bright wrote:On 11/24/2013 11:17 AM, bearophile wrote:But we can provide a syntax sugar for this case as was suggestedFrom my experience that's quite bug-prone: http://d.puremagic.com/issues/show_bug.cgi?id=3878I posted an objection there :-)
Nov 24 2013
On 11/24/13 11:17 AM, bearophile wrote:Walter Bright:I think he meant "shadowing locals". As I wrote in TDPL, it's a bad idea to add a global somewhere and break a bunch of code that has nothing to do with it. AndreiShadowing globals is definitely a bad idea. Shadowing members, it's debatable.So are you saying D here should give an error for the shadowing of the module-level x?
Nov 24 2013
On Sunday, 24 November 2013 at 23:31:38 UTC, Andrei Alexandrescu wrote:On 11/24/13 11:17 AM, bearophile wrote:Yes, but D allows to use it. And in few cases global variable can be useful. For example, we can have thread-local variable for database connection that used almost everywhere.Walter Bright:I think he meant "shadowing locals". As I wrote in TDPL, it's a bad idea to add a global somewhere and break a bunch of code that has nothing to do with it.Shadowing globals is definitely a bad idea. Shadowing members, it's debatable.So are you saying D here should give an error for the shadowing of the module-level x?
Nov 24 2013
On 11/24/13 6:48 PM, ilya-stromberg wrote:On Sunday, 24 November 2013 at 23:31:38 UTC, Andrei Alexandrescu wrote:I agree. What I'm saying is it's not good to make shadowing a global an error. It puts the onus in the wrong place. AndreiOn 11/24/13 11:17 AM, bearophile wrote:Yes, but D allows to use it. And in few cases global variable can be useful. For example, we can have thread-local variable for database connection that used almost everywhere.Walter Bright:I think he meant "shadowing locals". As I wrote in TDPL, it's a bad idea to add a global somewhere and break a bunch of code that has nothing to do with it.Shadowing globals is definitely a bad idea. Shadowing members, it's debatable.So are you saying D here should give an error for the shadowing of the module-level x?
Nov 24 2013
On Monday, 25 November 2013 at 03:12:03 UTC, Andrei Alexandrescu wrote:On 11/24/13 6:48 PM, ilya-stromberg wrote:Would it be possible to introduce a global scope of sorts that had to be explicitly referenced when one wanted to define or use a global variable. I haven't thought of how this might interface with other D features, but something along the lines of: global int my_gobal_var; //Gets added to global scope. //Then any globals would have to be referenced as: global.my_global_var = 7; Makes for a bit of extra typing, and would mess with any module named 'global', but it might work?On Sunday, 24 November 2013 at 23:31:38 UTC, Andrei Alexandrescu wrote:I agree. What I'm saying is it's not good to make shadowing a global an error. It puts the onus in the wrong place. AndreiOn 11/24/13 11:17 AM, bearophile wrote:Yes, but D allows to use it. And in few cases global variable can be useful. For example, we can have thread-local variable for database connection that used almost everywhere.Walter Bright:I think he meant "shadowing locals". As I wrote in TDPL, it's a bad idea to add a global somewhere and break a bunch of code that has nothing to do with it.Shadowing globals is definitely a bad idea. Shadowing members, it's debatable.So are you saying D here should give an error for the shadowing of the module-level x?
Nov 24 2013
On 11/24/13 8:27 PM, Craig Dillabaugh wrote:Would it be possible to introduce a global scope of sorts that had to be explicitly referenced when one wanted to define or use a global variable. I haven't thought of how this might interface with other D features, but something along the lines of: global int my_gobal_var; //Gets added to global scope. //Then any globals would have to be referenced as: global.my_global_var = 7; Makes for a bit of extra typing, and would mess with any module named 'global', but it might work?To put it bluntly, many things are possible but it seems the best is to do nothing here. We're in good shape. Andrei
Nov 24 2013
On Monday, 25 November 2013 at 04:35:10 UTC, Andrei Alexandrescu wrote:On 11/24/13 8:27 PM, Craig Dillabaugh wrote:I personally like Craig Dillabaugh's sugestion. But we can use `.` operator for this because it alredy used for call global functions and, probably, should break nothing. Like this: int my_gobal_var; .my_global_var = 7; Is it possible?Would it be possible to introduce a global scope of sorts that had to be explicitly referenced when one wanted to define or use a global variable. I haven't thought of how this might interface with other D features, but something along the lines of: global int my_gobal_var; //Gets added to global scope. //Then any globals would have to be referenced as: global.my_global_var = 7; Makes for a bit of extra typing, and would mess with any module named 'global', but it might work?To put it bluntly, many things are possible but it seems the best is to do nothing here. We're in good shape.
Nov 25 2013
On Monday, 25 November 2013 at 09:39:14 UTC, ilya-stromberg wrote:On Monday, 25 November 2013 at 04:35:10 UTC, Andrei Alexandrescu wrote:Sorry if I didn't explain idea properly. We can force using `.` before global variables. Almost everybody agree that use global variables is bad idea, so additional symbol looks acceptable.On 11/24/13 8:27 PM, Craig Dillabaugh wrote:I personally like Craig Dillabaugh's sugestion. But we can use `.` operator for this because it alredy used for call global functions and, probably, should break nothing. Like this: int my_gobal_var; .my_global_var = 7; Is it possible?Would it be possible to introduce a global scope of sorts that had to be explicitly referenced when one wanted to define or use a global variable. I haven't thought of how this might interface with other D features, but something along the lines of: global int my_gobal_var; //Gets added to global scope. //Then any globals would have to be referenced as: global.my_global_var = 7; Makes for a bit of extra typing, and would mess with any module named 'global', but it might work?To put it bluntly, many things are possible but it seems the best is to do nothing here. We're in good shape.
Nov 25 2013
On Monday, 25 November 2013 at 11:07:01 UTC, ilya-stromberg wrote:And what to do with code already written? What exactly should be said to people who have to maintain the code? Do you volunteer to write a dmd/druntime/phobos pull?int my_gobal_var; .my_global_var = 7; Is it possible?Sorry if I didn't explain idea properly. We can force using `.` before global variables. Almost everybody agree that use global variables is bad idea, so additional symbol looks acceptable.
Nov 25 2013
On Monday, 25 November 2013 at 11:12:12 UTC, Maxim Fomin wrote:On Monday, 25 November 2013 at 11:07:01 UTC, ilya-stromberg wrote:OK, I see.And what to do with code already written? What exactly should be said to people who have to maintain the code? Do you volunteer to write a dmd/druntime/phobos pull?int my_gobal_var; .my_global_var = 7; Is it possible?Sorry if I didn't explain idea properly. We can force using `.` before global variables. Almost everybody agree that use global variables is bad idea, so additional symbol looks acceptable.
Nov 25 2013
On Monday, 25 November 2013 at 11:12:12 UTC, Maxim Fomin wrote:On Monday, 25 November 2013 at 11:07:01 UTC, ilya-stromberg wrote:One of the things I had in mind with my idea at least, was that it could be introduced without breaking code, and would simply be a global scope (namespace) that folks could use to store their global variables. It would provide some additional safety/clarity for projects that wanted it. Perhaps it could be implemented as a library (although that would likely preclude the exact syntax I showed). I don't feel I have the experience with D yet to implement such a thing. But maybe I will add it to my list of possible future projects.And what to do with code already written? What exactly should be said to people who have to maintain the code? Do you volunteer to write a dmd/druntime/phobos pull?int my_gobal_var; .my_global_var = 7; Is it possible?Sorry if I didn't explain idea properly. We can force using `.` before global variables. Almost everybody agree that use global variables is bad idea, so additional symbol looks acceptable.
Nov 25 2013
On 11/25/13 1:39 AM, ilya-stromberg wrote:On Monday, 25 November 2013 at 04:35:10 UTC, Andrei Alexandrescu wrote:Doesn't that work already? AndreiOn 11/24/13 8:27 PM, Craig Dillabaugh wrote:I personally like Craig Dillabaugh's sugestion. But we can use `.` operator for this because it alredy used for call global functions and, probably, should break nothing. Like this: int my_gobal_var; .my_global_var = 7; Is it possible?Would it be possible to introduce a global scope of sorts that had to be explicitly referenced when one wanted to define or use a global variable. I haven't thought of how this might interface with other D features, but something along the lines of: global int my_gobal_var; //Gets added to global scope. //Then any globals would have to be referenced as: global.my_global_var = 7; Makes for a bit of extra typing, and would mess with any module named 'global', but it might work?To put it bluntly, many things are possible but it seems the best is to do nothing here. We're in good shape.
Nov 25 2013
On 11/25/2013 4:05 PM, Andrei Alexandrescu wrote:On 11/25/13 1:39 AM, ilya-stromberg wrote:Sure, but only because I saw the suggestion and traveled back in time to implement it!I personally like Craig Dillabaugh's sugestion. But we can use `.` operator for this because it alredy used for call global functions and, probably, should break nothing. Like this: int my_gobal_var; .my_global_var = 7; Is it possible?Doesn't that work already?
Nov 25 2013
On Tuesday, 26 November 2013 at 07:20:47 UTC, Walter Bright wrote:On 11/25/2013 4:05 PM, Andrei Alexandrescu wrote:I repeat, sorry if I didn't explain idea properly, see: http://forum.dlang.org/thread/mydipbvhfjgvjybcyeyn forum.dlang.org?page=6#post-sffdyogipcanorahdtte:40forum.dlang.orgOn 11/25/13 1:39 AM, ilya-stromberg wrote:Sure, but only because I saw the suggestion and traveled back in time to implement it!int my_gobal_var; .my_global_var = 7; Is it possible?Doesn't that work already?
Nov 25 2013
On Tuesday, 26 November 2013 at 07:34:26 UTC, ilya-stromberg wrote:I repeat, sorry if I didn't explain idea properly, see: http://forum.dlang.org/thread/mydipbvhfjgvjybcyeyn forum.dlang.org?page=6#post-sffdyogipcanorahdtte:40forum.dlang.orgLike Maxim explained, it's a breaking change to force it. Unfortunately, that just can't be done. This is one of those kinds of things that is self policing. If you really want to know when something is global when you use it then use g prepended before your global names. That's what a lot of people do to avoid this type of issue.
Nov 26 2013
On Tuesday, 26 November 2013 at 08:01:23 UTC, Chris Cain wrote:On Tuesday, 26 November 2013 at 07:34:26 UTC, ilya-stromberg wrote:Yes, I already understood this. I just wanted to explain that already apologized for incomplete suggestion.I repeat, sorry if I didn't explain idea properly, see: http://forum.dlang.org/thread/mydipbvhfjgvjybcyeyn forum.dlang.org?page=6#post-sffdyogipcanorahdtte:40forum.dlang.orgLike Maxim explained, it's a breaking change to force it. Unfortunately, that just can't be done. This is one of those kinds of things that is self policing. If you really want to know when something is global when you use it then use g prepended before your global names. That's what a lot of people do to avoid this type of issue.
Nov 26 2013
Chris Cain:If you really want to know when something is global when you use it then use g prepended before your global names. That's what a lot of people do to avoid this type of issue.That is named "relying on hand-managed name conventions for something that could be the job of the compiler type system". Bye, bearophile
Nov 26 2013
On Tuesday, 26 November 2013 at 08:23:15 UTC, bearophile wrote:Chris Cain:Yes, exactly. BTW, yesterday I found bug in Vibe.d, see: https://github.com/rejectedsoftware/vibe.d/issues/406 Reduced example: void main() { int i; i = i; } The line `i = i;` does nothing, but compiler doesn't give a error. Why?! Note that `i;` line gives the error: Error: var has no effect in expression (i)If you really want to know when something is global when you use it then use g prepended before your global names. That's what a lot of people do to avoid this type of issue.That is named "relying on hand-managed name conventions for something that could be the job of the compiler type system".
Nov 26 2013
On Tuesday, 26 November 2013 at 08:23:15 UTC, bearophile wrote:That is named "relying on hand-managed name conventions for something that could be the job of the compiler type system".Sure. It'd have been nice if the language was designed to avoid these types of problems from the beginning (though a language feature/syntax rules to learn dedicated to a problem that is easily solved with a naming convention would be debatable). But it wasn't and it'd break too much code for a minuscule gain and there exists a reasonable workaround (that also is commonly used everywhere else for this same problem in most other languages). Changing this now would be horrifically bad and the benefit of such a change is effectively nothing.
Nov 26 2013
On Tuesday, 26 November 2013 at 08:33:58 UTC, Chris Cain wrote:On Tuesday, 26 November 2013 at 08:23:15 UTC, bearophile wrote:Yes, but D/Phobos depreciates/removes a lot of different things. For example, we can use only warning (maybe only with special compiler flag like `-property`).That is named "relying on hand-managed name conventions for something that could be the job of the compiler type system".Sure. It'd have been nice if the language was designed to avoid these types of problems from the beginning (though a language feature/syntax rules to learn dedicated to a problem that is easily solved with a naming convention would be debatable). But it wasn't and it'd break too much code for a minuscule gain and there exists a reasonable workaround (that also is commonly used everywhere else for this same problem in most other languages). Changing this now would be horrifically bad and the benefit of such a change is effectively nothing.
Nov 26 2013
Chris Cain:Sure. It'd have been nice if the language was designed to avoid these types of problems from the beginning (though a language feature/syntax rules to learn dedicated to a problem that is easily solved with a naming convention would be debatable). But it wasn't and it'd break too much code for a minuscule gain and there exists a reasonable workaround (that also is commonly used everywhere else for this same problem in most other languages). Changing this now would be horrifically bad and the benefit of such a change is effectively nothing.This discussion is becoming more interesting, thank you :-) If it's a convention "commonly used everywhere" then it sounds like something important. And replacing name conventions with compiler-enforced features is one of the main purposes of any type system. Because it makes the convention safer and tidier. Regarding the code breaking, probably there are acceptable deprecation paths, that make the such change gradual enough. regarding the gain being minuscule, experiments should be used to verify this. Andrei has written elsewhere in this thread:As I wrote in TDPL, it's a bad idea to add a global somewhere and break a bunch of code that has nothing to do with it.<Global (or module-level in D, often thread-local) variables are sometimes useful, but a D programmer should minimize their number. If you add a global variable, and the compiler gives you several name shadowing errors elsewhere, you choose a different name for the global variable, you don't break the code. If you add a local variable that shadows a global variable and you receive a shadowing error, you choose a different name for the local variable. This avoid using the "g_" prefix. Bye, bearophile
Nov 26 2013
On 11/26/13 1:22 AM, bearophile wrote:Andrei has written elsewhere in this thread:The problem is "you" who added the global and "you" whose code is broken may be in fact two different people. It's safe to end this discussion. Doing absolutely nothing has a lot going for it in this case. Thanks, AndreiAs I wrote in TDPL, it's a bad idea to add a global somewhere and break a bunch of code that has nothing to do with it.<Global (or module-level in D, often thread-local) variables are sometimes useful, but a D programmer should minimize their number. If you add a global variable, and the compiler gives you several name shadowing errors elsewhere, you choose a different name for the global variable, you don't break the code. If you add a local variable that shadows a global variable and you receive a shadowing error, you choose a different name for the local variable. This avoid using the "g_" prefix.
Nov 26 2013
Andrei Alexandrescu:The problem is "you" who added the global and "you" whose code is broken may be in fact two different people.When you have code written by another person, and you add a global variable that causes shadowing errors elsewhere, you choose another variable name. What problems is this going to cause? Bye, bearophile
Nov 26 2013
On 11/26/13 9:10 AM, bearophile wrote:Andrei Alexandrescu:Someone else adds a global to the code they wrote, with which you build. Aren't you working in a team? AndreiThe problem is "you" who added the global and "you" whose code is broken may be in fact two different people.When you have code written by another person, and you add a global variable that causes shadowing errors elsewhere, you choose another variable name. What problems is this going to cause?
Nov 26 2013
On 11/26/2013 1:22 AM, bearophile wrote:If you add a global variable, and the compiler gives you several name shadowing errors elsewhere, you choose a different name for the global variable, you don't break the code.That's going to work out not so great for anyone developing a 3rd party library.
Nov 26 2013
On Tuesday, 26 November 2013 at 08:23:15 UTC, bearophile wrote:Chris Cain:http://i.imgur.com/H838hA9.jpgIf you really want to know when something is global when you use it then use g prepended before your global names. That's what a lot of people do to avoid this type of issue.That is named "relying on hand-managed name conventions for something that could be the job of the compiler type system". Bye, bearophile
Nov 26 2013
deadalnix:http://i.imgur.com/H838hA9.jpgAH ah, thank you :-) Eventually the official lint will need to ship inside the main D distributions. While a lint is useful for some purposes (like verifying the D code doesn't have logically wrong indentations), there are some things that are probably better addressed in the language. Bye, bearophile
Nov 26 2013
On Tuesday, 26 November 2013 at 09:25:56 UTC, bearophile wrote:While a lint is useful for some purposes (like verifying the D code doesn't have logically wrong indentations), there are some things that are probably better addressed in the language.So, we have a few suggestions in this thread like: 1) disable shadowing class members 2) disable shadowing global variables 3) enforce using `.` before global variables What our next step? Shall we add Bugzilla issue or something else?
Nov 26 2013
On Tuesday, 26 November 2013 at 10:43:57 UTC, ilya-stromberg wrote:On Tuesday, 26 November 2013 at 09:25:56 UTC, bearophile wrote:Let us vote. I am against 1 .. 3While a lint is useful for some purposes (like verifying the D code doesn't have logically wrong indentations), there are some things that are probably better addressed in the language.So, we have a few suggestions in this thread like: 1) disable shadowing class members 2) disable shadowing global variables 3) enforce using `.` before global variables What our next step? Shall we add Bugzilla issue or something else?
Nov 26 2013
On 11/26/13 2:43 AM, ilya-stromberg wrote:On Tuesday, 26 November 2013 at 09:25:56 UTC, bearophile wrote:Maybe (2) has something going for it, but (1) and (3) are definite no-nos. The win of (2) itself is yet to be quantified and the breakage is large. So my suggestion is we choose: 4) Do absolutely nothing and move on. Thanks, AndreiWhile a lint is useful for some purposes (like verifying the D code doesn't have logically wrong indentations), there are some things that are probably better addressed in the language.So, we have a few suggestions in this thread like: 1) disable shadowing class members 2) disable shadowing global variables 3) enforce using `.` before global variables What our next step? Shall we add Bugzilla issue or something else?
Nov 26 2013
On Tuesday, 26 November 2013 at 16:27:27 UTC, Andrei Alexandrescu wrote:The win of (2) itself is yet to be quantified and the breakage is large.Excuse me, did you mean "disable shadowing global variables" or "disable shadowing class members"? If I understand everything correctly, Walter said that "Shadowing members, it's debatable". His main objection was about initializing variables in constructor, but we can add syntax sugar for this case. See also: http://forum.dlang.org/post/l6tg7n$2i7s$1 digitalmars.com http://forum.dlang.org/post/l6tjdq$2kvc$1 digitalmars.com http://d.puremagic.com/issues/show_bug.cgi?id=9801
Nov 26 2013
On 11/26/13 8:52 AM, ilya-stromberg wrote:On Tuesday, 26 November 2013 at 16:27:27 UTC, Andrei Alexandrescu wrote:The latter.The win of (2) itself is yet to be quantified and the breakage is large.Excuse me, did you mean "disable shadowing global variables" or "disable shadowing class members"?If I understand everything correctly, Walter said that "Shadowing members, it's debatable". His main objection was about initializing variables in constructor, but we can add syntax sugar for this case. See also: http://forum.dlang.org/post/l6tg7n$2i7s$1 digitalmars.com http://forum.dlang.org/post/l6tjdq$2kvc$1 digitalmars.com http://d.puremagic.com/issues/show_bug.cgi?id=9801I think Walter agrees that we can't disallow shadowing globals. Adding additional sugar is pretty much the kiss of death for the entire notion of disallowing shadowing of members. Andrei
Nov 26 2013
On Tuesday, 26 November 2013 at 17:11:38 UTC, Andrei Alexandrescu wrote:On 11/26/13 8:52 AM, ilya-stromberg wrote:Thanks for explanation. I was confused because number (2) is "disable shadowing global variables" and you wrote that don't want to have it. Thank you for explanation because I can't interpret your opinion as I want.On Tuesday, 26 November 2013 at 16:27:27 UTC, Andrei Alexandrescu wrote:The latter.The win of (2) itself is yet to be quantified and the breakage is large.Excuse me, did you mean "disable shadowing global variables" or "disable shadowing class members"?Excuse me, I didn't understand you. The main idea: 1) disable shadowing class members 2) add additional syntax sugar for initializing variables in It looks like that solves problem. Is it impossible? As alternative solution, we can allow shadowing members only for function parameters or, maybe, only for constructor. Walter agreed that it's possible, "but at the cost of D becoming more of a mass of special cases that nobody can remember". http://forum.dlang.org/post/l6tjdq$2kvc$1 digitalmars.comIf I understand everything correctly, Walter said that "Shadowing members, it's debatable". His main objection was about initializing variables in constructor, but we can add syntax sugar for this case. See also: http://forum.dlang.org/post/l6tg7n$2i7s$1 digitalmars.com http://forum.dlang.org/post/l6tjdq$2kvc$1 digitalmars.com http://d.puremagic.com/issues/show_bug.cgi?id=9801I think Walter agrees that we can't disallow shadowing globals. Adding additional sugar is pretty much the kiss of death for the entire notion of disallowing shadowing of members.
Nov 26 2013
On 11/26/13 9:39 AM, ilya-stromberg wrote:On Tuesday, 26 November 2013 at 17:11:38 UTC, Andrei Alexandrescu wrote:Apologies for writing the wrong number.On 11/26/13 8:52 AM, ilya-stromberg wrote:Thanks for explanation. I was confused because number (2) is "disable shadowing global variables" and you wrote that don't want to have it. Thank you for explanation because I can't interpret your opinion as I want.On Tuesday, 26 November 2013 at 16:27:27 UTC, Andrei Alexandrescu wrote:The latter.The win of (2) itself is yet to be quantified and the breakage is large.Excuse me, did you mean "disable shadowing global variables" or "disable shadowing class members"?It is possible to the extent a lot of things are. But at this point: (a) It's unclear whether a problem even exist, and if it does, what is its magnitude. (b) There has been no convincing refutation of the alternative of doing nothing ("if we do nothing about this, ..."). In fact doing nothing is _very_ attractive from multiple angles (no work, no bugs, no regressions, no breakage, no surprise).Excuse me, I didn't understand you. The main idea: 1) disable shadowing class members 2) add additional syntax sugar for initializing variables in constructor It looks like that solves problem. Is it impossible?If I understand everything correctly, Walter said that "Shadowing members, it's debatable". His main objection was about initializing variables in constructor, but we can add syntax sugar for this case. See also: http://forum.dlang.org/post/l6tg7n$2i7s$1 digitalmars.com http://forum.dlang.org/post/l6tjdq$2kvc$1 digitalmars.com http://d.puremagic.com/issues/show_bug.cgi?id=9801I think Walter agrees that we can't disallow shadowing globals. Adding additional sugar is pretty much the kiss of death for the entire notion of disallowing shadowing of members.As alternative solution, we can allow shadowing members only for function parameters or, maybe, only for constructor. Walter agreed that it's possible, "but at the cost of D becoming more of a mass of special cases that nobody can remember". http://forum.dlang.org/post/l6tjdq$2kvc$1 digitalmars.comThat sugar is already liable of causing cancer of the semicolon. And adding a feature that is predicated on adding sugar? Kiss of death. Just drop this. Ten people come, on their first day using D, with eleven new ideas that shuffle things around a bit at the cost of breaking everybody's code. Thanks, Andrei
Nov 26 2013
On Tuesday, 26 November 2013 at 17:52:27 UTC, Andrei Alexandrescu wrote:On 11/26/13 9:39 AM, ilya-stromberg wrote: That sugar is already liable of causing cancer of the semicolon. And adding a feature that is predicated on adding sugar? Kiss of death.Thanks for explanation. I really don't understand what's a Maybe you can find another solution, I don't know. BTW, it will be great to have static code analyzer, maybe with a custom rules and, maybe built-in into compiler. We already have built-in profiler.Just drop this. Ten people come, on their first day using D, with eleven new ideas that shuffle things around a bit at the cost of breaking everybody's code.I think I use D about 1-2 years. I knew about it when your book TDPL wasn't published and GDC was broken, it was 2009-2010 as I remember. So, it's definitely not a my first day using D. I just found bug that can be catched via compiler and decide to write about it because, theoretically, we can improve this. Sorry for incomprehension.
Nov 26 2013
On 11/26/2013 9:39 AM, ilya-stromberg wrote:I agree with Andrei. The current situation is the best solution.
Nov 26 2013
On Tuesday, 26 November 2013 at 08:23:15 UTC, bearophile wrote:Chris Cain:Alternatively, one can start (enforce) using dot operator before module scope objects :)If you really want to know when something is global when you use it then use g prepended before your global names. That's what a lot of people do to avoid this type of issue.That is named "relying on hand-managed name conventions for something that could be the job of the compiler type system". Bye, bearophile
Nov 26 2013
Andrei Alexandrescu:I'm not sure whether shadowing globals or members would be a good idea.I understand. It's not a clear cut topic. There are real reasons both for and against this idea. But surely it should be considered. I have not yet (re)opened an enhancement request on this.gcc has a -W flag for that, and someone tried to turn it on at Facebook but with debatable results. We ended up not using that warning.In the example I have shown it's with() that is uncovering a struct field with the same name of a module-level name. So it's not exactly the same as a local variable shadowing a module-level name (and currently with has anti-hijacking for local variables). I think that shadowing module-level names with with() is not good. Also because of this idea: https://d.puremagic.com/issues/show_bug.cgi?id=6917 Regarding Facebook, I presume that Gcc flag was applied to plenty of already written code. If you apply it since the start of a new project perhaps (probably) its effects are different. This detail is important, because lot of D code is yet to be written. Regarding more generally the topic of shadowing module-level names with local names, the attribute "pure" helps avoid some cases, because you can only shadow immutable global names, and this is a little less dangerous/troublesome. Time ago I suggested an optional outer() attribute, that's useful to specify what names from outer scopes a function/method is allowed to see and use. It looks a bit excessive, but it shows that I have hated bugs caused by shadowing globals silently. An IDE could underline the shadowing variables, turning the silent shadowing into a visible one, without giving warnings (it's a kind of much noisy warning), but unfortunately a compiler like dmd can't do that. Another problem is that a command like "import std.algorithm" imports lot of names in the current module, and this could cause many false alarms. But this could be a good thing, and it can push Phobos devs to add more "private" tags to Phobos names, and D developers to add more qualified imports in their programs. Bye, bearophile
Nov 24 2013
On 11/24/13 10:31 AM, bearophile wrote:Regarding Facebook, I presume that Gcc flag was applied to plenty of already written code. If you apply it since the start of a new project perhaps (probably) its effects are different. This detail is important, because lot of D code is yet to be written.This is just speculation. It would have been helpful if enabling -Wshadow uncovered at least a few bugs. Instead, it just asked for a lot of code to be changed for no visible benefit. Andrei
Nov 24 2013
On Sunday, 24 November 2013 at 18:41:32 UTC, Andrei Alexandrescu wrote:This is just speculation. It would have been helpful if enabling -Wshadow uncovered at least a few bugs. Instead, it just asked for a lot of code to be changed for no visible benefit.No, isn't just speculation. If you already have working and tested code without `-Wshadow` flag it's really doesn't provide any solid benefits. But in my case it helps because compiler prints error about missing identifier and I have to uncomment `bool` variable.
Nov 24 2013
On Sunday, November 24, 2013 15:16:37 bearophile wrote:Maxim Fomin:Not at all, and most people coming from C/C++ would likely be annoyed to not have it. And a prime place that it's used where using is woludn't work is with the in operator. e.g. if(auto ptr = key in myAA) {...} Granted, that's a pointer rather than a class reference, but it's essentially the same issue. And I see no reason to have pointers and references act differently in this regard. - Jonathan M DavisThis is neither bug not a terribale feature.I think the implicit question of ilya-stromberg was: how much bug-prone is this language feature?
Nov 24 2013
So, pointer implicitly converts to false if pointer is null and to true if pointer is not null. Is it bug or terrible feature? Note that we have `f is null` syntax for these cases.Not exactly. It is all about "if" condition. AFAIK, D defines that condition `if(X)` get re-written to `if(cast(bool)X)` before semantic pass. So it is kind of implicit explicit conversion :)
Nov 24 2013
On Sunday, 24 November 2013 at 14:17:50 UTC, Dicebot wrote:Not exactly. It is all about "if" condition. AFAIK, D defines that condition `if(X)` get re-written to `if(cast(bool)X)` before semantic pass. So it is kind of implicit explicit conversion :)Not exactly. Code: bool b = f; DMD output: Error: cannot implicitly convert expression (f) of type Foo to bool But code: bool b = !f; compiles.
Nov 24 2013
On Sunday, 24 November 2013 at 14:24:09 UTC, ilya-stromberg wrote:On Sunday, 24 November 2013 at 14:17:50 UTC, Dicebot wrote:Because '!' operator provides boolean context. It is written in the spec, although not explicitly. By the way, the same happens with objects with pretty many types (except structs which do not provide necessary operator overloads), so classes are not exceptional here. UnaryExpression: & UnaryExpression ++ UnaryExpression -- UnaryExpression * UnaryExpression - UnaryExpression + UnaryExpression ! UnaryExpression ComplementExpression ( Type ) . Identifier ( Type ) . TemplateInstance DeleteExpression CastExpression PowExpressionNot exactly. It is all about "if" condition. AFAIK, D defines that condition `if(X)` get re-written to `if(cast(bool)X)` before semantic pass. So it is kind of implicit explicit conversion :)Not exactly. Code: bool b = f; DMD output: Error: cannot implicitly convert expression (f) of type Foo to bool But code: bool b = !f; compiles.
Nov 24 2013
On Sunday, 24 November 2013 at 14:45:31 UTC, Maxim Fomin wrote:Because '!' operator provides boolean context.Yes, but it's ambiguously. What should compiler to use: 1) pointer comparing `is null` or 2) bool comparing `cast(bool)` What happens if `cast(bool)` operator will be added or removed?
Nov 24 2013
On Sunday, 24 November 2013 at 14:55:10 UTC, ilya-stromberg wrote:On Sunday, 24 November 2013 at 14:45:31 UTC, Maxim Fomin wrote:And if instance is null, where compiler can look for opCast? Again, why not read the spec and then ask questions? "Notably absent from the list of overloaded unary operators is the ! logical negation operator. More obscurely absent is a unary operator to convert to a bool result. ... This only happens, however, for instances of structs. Class references are converted to bool by checking to see if the class reference is null or not. "Because '!' operator provides boolean context.Yes, but it's ambiguously. What should compiler to use: 1) pointer comparing `is null` or 2) bool comparing `cast(bool)` What happens if `cast(bool)` operator will be added or removed?
Nov 24 2013
On Sunday, 24 November 2013 at 14:24:09 UTC, ilya-stromberg wrote:On Sunday, 24 November 2013 at 14:17:50 UTC, Dicebot wrote:Your say no, but you then confirm. Please reread Dicebot's post.Not exactly. It is all about "if" condition. AFAIK, D defines that condition `if(X)` get re-written to `if(cast(bool)X)` before semantic pass. So it is kind of implicit explicit conversion :)Not exactly.Code: bool b = f; DMD output: Error: cannot implicitly convert expression (f) of type Foo to bool But code: bool b = !f; compiles.
Nov 24 2013