www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DMD can implicitly convert class pointer to the bool. Is it bug or

reply "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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
next sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
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
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/24/13 6:32 AM, ilya-stromberg wrote:
 On Sunday, 24 November 2013 at 14:16:39 UTC, bearophile wrote:
 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?

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! } } }

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. Andrei
Nov 24 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
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
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
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
prev sibling next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 11/24/2013 11:17 AM, bearophile wrote:
 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++; } }

I meant "bad" as in bad, not as in "good" :-)
  From my experience that's quite bug-prone:
 http://d.puremagic.com/issues/show_bug.cgi?id=3878

I posted an objection there :-)
Nov 24 2013
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/24/13 11:17 AM, bearophile wrote:
 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?

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. Andrei
Nov 24 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/24/13 6:48 PM, ilya-stromberg wrote:
 On Sunday, 24 November 2013 at 23:31:38 UTC, Andrei Alexandrescu wrote:
 On 11/24/13 11:17 AM, bearophile wrote:
 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?

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.

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.

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. Andrei
Nov 24 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/25/13 1:39 AM, ilya-stromberg wrote:
 On Monday, 25 November 2013 at 04:35:10 UTC, Andrei Alexandrescu wrote:
 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.

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? Andrei
Nov 25 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/25/2013 4:05 PM, Andrei Alexandrescu wrote:
 On 11/25/13 1:39 AM, ilya-stromberg 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?

Doesn't that work already?

Sure, but only because I saw the suggestion and traveled back in time to implement it!
Nov 25 2013
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/26/13 1:22 AM, bearophile wrote:
 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.

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, Andrei
Nov 26 2013
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/26/13 9:10 AM, bearophile wrote:
 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?

Someone else adds a global to the code they wrote, with which you build. Aren't you working in a team? Andrei
Nov 26 2013
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/26/13 2:43 AM, ilya-stromberg wrote:
 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?

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, Andrei
Nov 26 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/26/13 8:52 AM, ilya-stromberg wrote:
 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"?

The latter.
 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

I 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
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/26/13 9:39 AM, ilya-stromberg wrote:
 On Tuesday, 26 November 2013 at 17:11:38 UTC, Andrei Alexandrescu wrote:
 On 11/26/13 8:52 AM, ilya-stromberg wrote:
 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"?

The latter.

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.

Apologies for writing the wrong number.
 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

I 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.

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 as was suggested in #9801 It looks like that solves problem. Is it impossible?

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).
 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.com

 So, syntax sugar in #9801 looks like better solution.

That 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
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 11/26/2013 9:39 AM, ilya-stromberg wrote:
 So, syntax sugar in #9801 looks like better solution.

I agree with Andrei. The current situation is the best solution.
Nov 26 2013
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
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
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
prev sibling next sibling parent Ary Borenszweig <ary esperanto.org.ar> writes:
On 11/24/13 11:18 AM, ilya-stromberg wrote:
 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

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?
Nov 24 2013
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
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
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
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:
 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?

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.
Nov 24 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
prev sibling next sibling parent "Dicebot" <public dicebot.lv> writes:
 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
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
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:
 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.

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.
Nov 24 2013
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Sunday, 24 November 2013 at 14:16:39 UTC, bearophile wrote:
 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

OK. What are the problems with converting class references to true when they are not null and false when they are null?
Nov 24 2013
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
On Sunday, 24 November 2013 at 14:16:39 UTC, bearophile wrote:
 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?

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! } } }
Nov 24 2013
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
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:
 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.

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 PowExpression
Nov 24 2013
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
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:
 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?

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 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.
Nov 24 2013
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
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:
 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?

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. "
Nov 24 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
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:
 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.

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.
Nov 24 2013
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Sunday, 24 November 2013 at 15:35:40 UTC, bearophile wrote:
 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

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)
Nov 24 2013
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
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:

 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.

OK, root of the issue is identifier shadowing.
 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
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:

 class 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.

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, bearophile
Nov 24 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
On Sunday, 24 November 2013 at 19:18:18 UTC, Walter Bright wrote:
 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.

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.
Nov 24 2013
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
On Sunday, 24 November 2013 at 19:59:51 UTC, Walter Bright wrote:
 On 11/24/2013 11:17 AM, bearophile wrote:
 From my experience that's quite bug-prone:
 http://d.puremagic.com/issues/show_bug.cgi?id=3878

I posted an objection there :-)

But we can provide a syntax sugar for this case as was suggested in #9801.
Nov 24 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
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:
 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?

void* ptr; if(ptr) was a shortcut for 'if(ptr != NULL)' probably since C was created.

No, it is a comparaison with 0. If NULL is 0 on all modern architectures I know of, this wasn't always the case.
 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
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
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:
 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.

Your say no, but you then confirm. Please reread Dicebot's post.
 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
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
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:
 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:
 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?

void* ptr; if(ptr) was a shortcut for 'if(ptr != NULL)' probably since C was created.

No, it is a comparaison with 0. If NULL is 0 on all modern architectures I know of, this wasn't always the case.

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?
Nov 24 2013
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
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
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, November 24, 2013 18:38:19 Ary Borenszweig wrote:
 On 11/24/13 11:18 AM, ilya-stromberg wrote:
 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

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?

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 Davis
Nov 24 2013
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, November 24, 2013 15:16:37 bearophile wrote:
 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?

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 Davis
Nov 24 2013
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
On Sunday, 24 November 2013 at 23:31:38 UTC, Andrei Alexandrescu 
wrote:
 On 11/24/13 11:17 AM, bearophile wrote:
 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?

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.

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.
Nov 24 2013
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
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:
 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

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 "
Nov 24 2013
prev sibling next sibling parent "Craig Dillabaugh" <craig.dillabaugh gmail.com> writes:
On Monday, 25 November 2013 at 03:12:03 UTC, Andrei Alexandrescu
wrote:
 On 11/24/13 6:48 PM, ilya-stromberg wrote:
 On Sunday, 24 November 2013 at 23:31:38 UTC, Andrei 
 Alexandrescu wrote:
 On 11/24/13 11:17 AM, bearophile wrote:
 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?

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.

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.

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. Andrei

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?
Nov 24 2013
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
On Monday, 25 November 2013 at 04:35:10 UTC, Andrei Alexandrescu 
wrote:
 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.

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?
Nov 25 2013
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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:
 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.

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?

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
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Monday, 25 November 2013 at 11:07:01 UTC, ilya-stromberg wrote:
 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.

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?
Nov 25 2013
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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:
 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.

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?

OK, I see.
Nov 25 2013
prev sibling next sibling parent "Craig Dillabaugh" <craig.dillabaugh gmail.com> writes:
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:
 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.

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?

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.
Nov 25 2013
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
On Tuesday, 26 November 2013 at 07:20:47 UTC, Walter Bright wrote:
 On 11/25/2013 4:05 PM, Andrei Alexandrescu wrote:
 On 11/25/13 1:39 AM, ilya-stromberg wrote:
 int my_gobal_var;

 .my_global_var = 7;

 Is it possible?

Doesn't that work already?

Sure, but only because I saw the suggestion and traveled back in time to implement it!

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.org
Nov 25 2013
prev sibling next sibling parent "Chris Cain" <clcain uncg.edu> writes:
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.org

Like 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
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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:
 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.org

Like 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.

Yes, I already understood this. I just wanted to explain that already apologized for incomplete suggestion.
Nov 26 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
On Tuesday, 26 November 2013 at 08:23:15 UTC, bearophile wrote:
 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".

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)
Nov 26 2013
prev sibling next sibling parent "Chris Cain" <clcain uncg.edu> writes:
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
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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:
 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.

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`).
Nov 26 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 26 November 2013 at 08:23:15 UTC, bearophile wrote:
 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

http://i.imgur.com/H838hA9.jpg
Nov 26 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
deadalnix:

 http://i.imgur.com/H838hA9.jpg

AH 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
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
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:
 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?

Let us vote. I am against 1 .. 3
Nov 26 2013
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Tuesday, 26 November 2013 at 08:23:15 UTC, bearophile wrote:
 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

Alternatively, one can start (enforce) using dot operator before module scope objects :)
Nov 26 2013
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
On Tuesday, 26 November 2013 at 17:11:38 UTC, Andrei Alexandrescu 
wrote:
 On 11/26/13 8:52 AM, ilya-stromberg wrote:
 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"?

The latter.

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.
 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

I 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.

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 as was suggested in #9801 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.com So, syntax sugar in #9801 looks like better solution.
Nov 26 2013
prev sibling next sibling parent "ilya-stromberg" <ilya-stromberg-2009 yandex.ru> writes:
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 problem with #9801, but believe you that it's bad idea. 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
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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:
 DMD output:

 Error: use 'is' instead of '==' when comparing with null
 Error: use '!is' instead of '!=' when comparing with null

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?

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). -Steve
Jan 16 2014