www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Block Scope Rules

reply Derek Parnell <derek psych.ward> writes:
Either the documentation is wrong or DMD is wrong. The examples below
compile and run successfully, but according to the docs they should fail.

<code>
 void func2()
 {
    int x;

    {int x;// illegal, x is multiply defined in function scope
    }
 }

 void func3()
 {
    {int x;
    }
    {int x;// illegal, x is multiply defined in function scope
    }
 }
</code>

I need this clarified as I use block-scoped variables heavily and need to
know if I have to change my coding style.

-- 
Derek Parnell
Melbourne, Australia
http://www.dsource.org/projects/build/ V1.17 released
http://www.prowiki.org/wiki4d/wiki.cgi?FrontPage
31/03/2005 9:35:40 AM
Mar 30 2005
next sibling parent reply "Walter" <newshound digitalmars.com> writes:
"Derek Parnell" <derek psych.ward> wrote in message
news:2sue67wyp7ug$.f1delgy6x2ql.dlg 40tude.net...
 Either the documentation is wrong or DMD is wrong. The examples below
 compile and run successfully, but according to the docs they should fail.

 <code>
  void func2()
  {
     int x;

     {int x;// illegal, x is multiply defined in function scope
     }
  }

  void func3()
  {
     {int x;
     }
     {int x;// illegal, x is multiply defined in function scope
     }
  }
 </code>

 I need this clarified as I use block-scoped variables heavily and need to
 know if I have to change my coding style.

What do people think? Should this feature be dropped, or implemented?
Apr 03 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Sun, 3 Apr 2005 11:45:57 -0700, Walter wrote:

 "Derek Parnell" <derek psych.ward> wrote in message
 news:2sue67wyp7ug$.f1delgy6x2ql.dlg 40tude.net...
 Either the documentation is wrong or DMD is wrong. The examples below
 compile and run successfully, but according to the docs they should fail.

 <code>
  void func2()
  {
     int x;

     {int x;// illegal, x is multiply defined in function scope
     }
  }

  void func3()
  {
     {int x;
     }
     {int x;// illegal, x is multiply defined in function scope
     }
  }
 </code>

 I need this clarified as I use block-scoped variables heavily and need to
 know if I have to change my coding style.

What do people think? Should this feature be dropped, or implemented?

I'm in the camp that says that each block has its own scope, and thus a symbol declared in a block is visible to statements in that block and takes precedence over same-named symbols declared in other blocks. Note that not every block is bounded by braces. The 'for' and 'foreach' statements are already implemented thus, as are functions. for (int x = 0; ...) foreach( char c; ...) myFunc(int x) ... -- Derek Parnell Melbourne, Australia 4/04/2005 6:31:30 AM
Apr 03 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 4 Apr 2005 06:39:31 +1000, Derek Parnell <derek psych.ward> wrote:
 On Sun, 3 Apr 2005 11:45:57 -0700, Walter wrote:

 "Derek Parnell" <derek psych.ward> wrote in message
 news:2sue67wyp7ug$.f1delgy6x2ql.dlg 40tude.net...
 Either the documentation is wrong or DMD is wrong. The examples below
 compile and run successfully, but according to the docs they should  
 fail.

 <code>
  void func2()
  {
     int x;

     {int x;// illegal, x is multiply defined in function scope
     }
  }

  void func3()
  {
     {int x;
     }
     {int x;// illegal, x is multiply defined in function scope
     }
  }
 </code>

 I need this clarified as I use block-scoped variables heavily and need  
 to
 know if I have to change my coding style.

What do people think? Should this feature be dropped, or implemented?

I'm in the camp that says that each block has its own scope, and thus a symbol declared in a block is visible to statements in that block and takes precedence over same-named symbols declared in other blocks. Note that not every block is bounded by braces. The 'for' and 'foreach' statements are already implemented thus, as are functions. for (int x = 0; ...) foreach( char c; ...) myFunc(int x) ...

Having a variable 'hide' (or take precedence over) a previously defined variable, be it global or in an enclosing scope, is a source of bugs. Especially if the local variable is renamed but not all instances of it's use are renamed. On the other hand, having to name your variables so that they do not collide may cause you to have to use names which are less than 100% appropriate. Then again, having a global called 'index' is probably less than 100% appropriate, what is it the index of? I think that should be included in it's name i.e. fileIndex, boatIndex, etc. In this case I think I personally would choose safety over convenience as there are workarounds for the convenience issue, but none for the safety issue. It's important to note (I'm sure Derek realises/meant this) that a function "call" is not the same as a new scope. A function "definition" is the same as a new scope. A function call is not expected to have access to variables in the enclosing scope, therefore it cannot 'hide' them. A function definition (typically placed in the global scope) is expected to have access to variables declared in the enclosing scope (global variables). So, as for these 2 examples specifically I believe the first to be illegal and the second to be legal (as Stewart noted). Regan
Apr 03 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Mon, 04 Apr 2005 09:18:01 +1200, Regan Heath wrote:

 On Mon, 4 Apr 2005 06:39:31 +1000, Derek Parnell <derek psych.ward> wrote:
 On Sun, 3 Apr 2005 11:45:57 -0700, Walter wrote:

 "Derek Parnell" <derek psych.ward> wrote in message
 news:2sue67wyp7ug$.f1delgy6x2ql.dlg 40tude.net...
 Either the documentation is wrong or DMD is wrong. The examples below
 compile and run successfully, but according to the docs they should  
 fail.

 <code>
  void func2()
  {
     int x;

     {int x;// illegal, x is multiply defined in function scope
     }
  }

  void func3()
  {
     {int x;
     }
     {int x;// illegal, x is multiply defined in function scope
     }
  }
 </code>

 I need this clarified as I use block-scoped variables heavily and need  
 to
 know if I have to change my coding style.

What do people think? Should this feature be dropped, or implemented?

I'm in the camp that says that each block has its own scope, and thus a symbol declared in a block is visible to statements in that block and takes precedence over same-named symbols declared in other blocks. Note that not every block is bounded by braces. The 'for' and 'foreach' statements are already implemented thus, as are functions. for (int x = 0; ...) foreach( char c; ...) myFunc(int x) ...

Having a variable 'hide' (or take precedence over) a previously defined variable, be it global or in an enclosing scope, is a source of bugs. Especially if the local variable is renamed but not all instances of it's use are renamed.

True. So the questions is on what basis do we "draw the line". Currently there is no fundamental difference between ... int x; void Foo(){int x; ... } and void Foo(){ int x; { int x; ... } } or even void Foo(){ int x; for(int x = 0; ... } } It could be argued that case-sensitivity is also a source of bugs. But no-one is really wanting that to change (except VB and Progress coders :D ) int index_a; Foo() { int index_A; . . . index_a = 1; // Did I really mean this or index_A? } Maybe we could have an explicit resolution mechanism to disambiguate such name hiding?
 On the other hand, having to name your variables so that they do not  
 collide may cause you to have to use names which are less than 100%  
 appropriate.
 
 Then again, having a global called 'index' is probably less than 100%  
 appropriate, what is it the index of? I think that should be included in  
 it's name i.e. fileIndex, boatIndex, etc.

Hands up all of us who have used 'i' as a variable name? ;-) But meanwhile, in the world of compromise, people don't think ahead enough and we lazily use abbreviated names and meaningless names far too often. But even if we didn't, we could still wish to declare variables physically close to where they are going to be used.
 In this case I think I personally would choose safety over convenience as  
 there are workarounds for the convenience issue, but none for the safety  
 issue.

Yeah, I guess you are right here, but explaining the exceptions to the rule to a new comer could be interesting. Module scope is okay to hide but function scope is a no-no.
 It's important to note (I'm sure Derek realises/meant this) that a  
 function "call" is not the same as a new scope. A function "definition" is  
 the same as a new scope.

void myFunc(int x) ... -- Derek Melbourne, Australia 4/04/2005 9:00:32 AM
Apr 03 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 4 Apr 2005 09:15:45 +1000, Derek Parnell <derek psych.ward> wrote:
 On Mon, 04 Apr 2005 09:18:01 +1200, Regan Heath wrote:

 On Mon, 4 Apr 2005 06:39:31 +1000, Derek Parnell <derek psych.ward>  
 wrote:
 On Sun, 3 Apr 2005 11:45:57 -0700, Walter wrote:

 "Derek Parnell" <derek psych.ward> wrote in message
 news:2sue67wyp7ug$.f1delgy6x2ql.dlg 40tude.net...
 Either the documentation is wrong or DMD is wrong. The examples below
 compile and run successfully, but according to the docs they should
 fail.

 <code>
  void func2()
  {
     int x;

     {int x;// illegal, x is multiply defined in function scope
     }
  }

  void func3()
  {
     {int x;
     }
     {int x;// illegal, x is multiply defined in function scope
     }
  }
 </code>

 I need this clarified as I use block-scoped variables heavily and  
 need
 to
 know if I have to change my coding style.

What do people think? Should this feature be dropped, or implemented?

I'm in the camp that says that each block has its own scope, and thus a symbol declared in a block is visible to statements in that block and takes precedence over same-named symbols declared in other blocks. Note that not every block is bounded by braces. The 'for' and 'foreach' statements are already implemented thus, as are functions. for (int x = 0; ...) foreach( char c; ...) myFunc(int x) ...

Having a variable 'hide' (or take precedence over) a previously defined variable, be it global or in an enclosing scope, is a source of bugs. Especially if the local variable is renamed but not all instances of it's use are renamed.

True. So the questions is on what basis do we "draw the line". Currently there is no fundamental difference between ... int x; void Foo(){int x; ... }

A global variable with a *bad* name and a function declaration with a temporary var called "x".
 and

   void Foo(){ int x;  { int x; ... } }

A function with a temporary called "x" and another temporary called "x". Soln: rename one temporary "y" or "i".. So, my first assumption is that a variable like "x" or "i" is a temporary, or rather a variable that is not going to "live" very long. I believe it bad practice to give a long lived variable (a global, or one with a specific purpose) a nondescript or unspecific name. In my mind there is a fundamental difference here. That difference is that in the example with the global, the global "x" was given a *bad* name. The solution being to give it a good name, this is just good programming practice.
 or even

   void Foo(){ int x; for(int x = 0; ... } }

I see this as the same as the 2nd example above. In this case "x" is a temporary in both cases. Soln: rename one temporary "y" or "i"..
 It could be argued that case-sensitivity is also a source of bugs. But
 no-one is really wanting that to change (except VB and Progress coders  
 :D )

Some typos will always be bugs. In the example below, it's only a bug if the variables "index_a" and "index_A" both exist at the scope where the typo occurs. I'd argue this to be very unlikely given a few assumptions: - it's bad practice to use a naming sceme that allows both "index_a" and "index_A". - it relies on the global being named badly (unspecific, nondescript name). You can argue given a particular coding style and naming sceme that this is more likely to occur, in answer I'd say that coding style and/or naming sceme is inapproriate for use with D. Sadly we cannot accomodate everyones style and have a language that spots lots of bugs cased by style, it appears to be a tradeoff.
 int index_a;
 Foo()
 {
   int index_A;
   . . .

   index_a = 1; // Did I really mean this or index_A?
 }

 Maybe we could have an explicit resolution mechanism to disambiguate such
 name hiding?

This is a joke, right? If not please explain.
 On the other hand, having to name your variables so that they do not
 collide may cause you to have to use names which are less than 100%
 appropriate.

 Then again, having a global called 'index' is probably less than 100%
 appropriate, what is it the index of? I think that should be included in
 it's name i.e. fileIndex, boatIndex, etc.

Hands up all of us who have used 'i' as a variable name? ;-)

/me puts hand up.
 But meanwhile, in the world of compromise, people don't think ahead  
 enough
 and we lazily use abbreviated names and meaningless names far too often.

Sure, but, I believe good programming style dictates that you only use abbreviated/meaningless names for short-lived temporary variables and more descriptive names for long lived globals, in which case, no collisions should occur between globals and locals. leaving only local to local collision, which can usually be resolved by giving the local another random name i, j, k, l etc.
 But even if we didn't, we could still wish to declare variables  
 physically
 close to where they are going to be used.

Sure, and that will/should be possible eg. { int x; ... } { int x; ... } no problems here. { int x; ... { int x; <-error, rename to 'y' or 'i' or ... ... } }
 In this case I think I personally would choose safety over convenience  
 as
 there are workarounds for the convenience issue, but none for the safety
 issue.

Yeah, I guess you are right here, but explaining the exceptions to the rule to a new comer could be interesting.

The rule is if a variable in any scope hides a variable in an outer scope it's an error, plain and simple.
 Module scope is okay to hide but
 function scope is a no-no.

That's not an exception. Module scope is similar to: { int x; <-module 1 ... } <-module 2 { int x; ... } each module has it's own 'global' scope. Which you access by using the module name. However, D gives us a shortcut, and detects collisions requiring alias to resolve eg. [a.d] int i; [b.d] int i; import a; import b; i = 5; <-error, which one //soln1 a.i = 5; //soln2 alias i a.i; i = 5; Regan
Apr 03 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Mon, 04 Apr 2005 12:11:54 +1200, Regan Heath wrote:

 On Mon, 4 Apr 2005 09:15:45 +1000, Derek Parnell <derek psych.ward> wrote:
 On Mon, 04 Apr 2005 09:18:01 +1200, Regan Heath wrote:

 On Mon, 4 Apr 2005 06:39:31 +1000, Derek Parnell <derek psych.ward>  
 wrote:
 On Sun, 3 Apr 2005 11:45:57 -0700, Walter wrote:

 "Derek Parnell" <derek psych.ward> wrote in message
 news:2sue67wyp7ug$.f1delgy6x2ql.dlg 40tude.net...
 Either the documentation is wrong or DMD is wrong. The examples below
 compile and run successfully, but according to the docs they should
 fail.

 <code>
  void func2()
  {
     int x;

     {int x;// illegal, x is multiply defined in function scope
     }
  }

  void func3()
  {
     {int x;
     }
     {int x;// illegal, x is multiply defined in function scope
     }
  }
 </code>

 I need this clarified as I use block-scoped variables heavily and  
 need
 to
 know if I have to change my coding style.

What do people think? Should this feature be dropped, or implemented?

I'm in the camp that says that each block has its own scope, and thus a symbol declared in a block is visible to statements in that block and takes precedence over same-named symbols declared in other blocks. Note that not every block is bounded by braces. The 'for' and 'foreach' statements are already implemented thus, as are functions. for (int x = 0; ...) foreach( char c; ...) myFunc(int x) ...

Having a variable 'hide' (or take precedence over) a previously defined variable, be it global or in an enclosing scope, is a source of bugs. Especially if the local variable is renamed but not all instances of it's use are renamed.

True. So the questions is on what basis do we "draw the line". Currently there is no fundamental difference between ... int x; void Foo(){int x; ... }

A global variable with a *bad* name and a function declaration with a temporary var called "x".

Oh come off it, Regan. Its a f****** example in a post, sheesh! Give me some brains. Okay, I'll spell it out 'nicely' then ... uint Line_Counter; . . . uint Foo(char[] File_Path) { uint Line_Counter; ... return Line_Counter; } Line_Counter = Foo("C:\\autoexec.bat");
 and

   void Foo(){ int x;  { int x; ... } }


void Foo(){ uint Line_Counter; { uint Line_Counter; ... } }
 
 A function with a temporary called "x" and another temporary called "x".  
 Soln: rename one temporary "y" or "i"..
 
 So, my first assumption is that a variable like "x" or "i" is a temporary,  
 or rather a variable that is not going to "live" very long. I believe it  
 bad practice to give a long lived variable (a global, or one with a  
 specific purpose) a nondescript or unspecific name.

Of course it is, but it happens all the time. How are you going to stop that!
 In my mind there is a fundamental difference here. That difference is that  
 in the example with the global, the global "x" was given a *bad* name. The  
 solution being to give it a good name, this is just good programming  
 practice.

Sure, but we a talking about syntax and semantics here, and not what, in some people's option, is good programming practice.
 or even

   void Foo(){ int x; for(int x = 0; ... } }

I see this as the same as the 2nd example above. In this case "x" is a temporary in both cases. Soln: rename one temporary "y" or "i"..

ITS AN EXAMPLE! I couldn't be bother writing an example with a decent variable name because I figured people reading this could see beyond the specific and generalize it instead.
 It could be argued that case-sensitivity is also a source of bugs. But
 no-one is really wanting that to change (except VB and Progress coders  
 :D )

Some typos will always be bugs. In the example below, it's only a bug if the variables "index_a" and "index_A" both exist at the scope where the typo occurs. I'd argue this to be very unlikely given a few assumptions: - it's bad practice to use a naming sceme that allows both "index_a" and "index_A". - it relies on the global being named badly (unspecific, nondescript name).

Regan, you are just not getting it are you? These are just examples, dashed off in the heat of writing a news-group post! Seriously, would my point be any worse if I'd come up with names more pleasing to you? Try generalizing by examples, instead of nit picking. What if I had've used "Text_Offset" and "Text_offset", etc, etc, etc, etc ...
 You can argue given a particular coding style and naming sceme that this  
 is more likely to occur, in answer I'd say that coding style and/or naming  
 sceme is inapproriate for use with D. Sadly we cannot accomodate everyones  
 style and have a language that spots lots of bugs cased by style, it  
 appears to be a tradeoff.
 
 int index_a;
 Foo()
 {
   int index_A;
   . . .

   index_a = 1; // Did I really mean this or index_A?
 }

 Maybe we could have an explicit resolution mechanism to disambiguate such
 name hiding?

This is a joke, right? If not please explain.

No, it was not a joke. Ok, try not to get hung up with the specific characters I just coincidently happen to use in this reply; try generalizing it instead. But what if, the character ' ' when prefixing a symbol name, was an instruction for the compile to use the inner most scope to resolve an otherwise ambiguous symbol name. For example ... void Foo() { int Pretend_That_This_Is_A_Decent_Variable_Name; { double Pretend_That_This_Is_A_Decent_Variable_Name; . . . // Explicitly refer to the innermost scope. Pretend_That_This_Is_A_Decent_Variable_Name += 1.2; } } See, no joke involved.
 On the other hand, having to name your variables so that they do not
 collide may cause you to have to use names which are less than 100%
 appropriate.

 Then again, having a global called 'index' is probably less than 100%
 appropriate, what is it the index of? I think that should be included in
 it's name i.e. fileIndex, boatIndex, etc.

Hands up all of us who have used 'i' as a variable name? ;-)

/me puts hand up.

Smack! ;-)
 But meanwhile, in the world of compromise, people don't think ahead  
 enough
 and we lazily use abbreviated names and meaningless names far too often.

Sure, but, I believe good programming style dictates that you only use abbreviated/meaningless names for short-lived temporary variables and more descriptive names for long lived globals, in which case, no collisions should occur between globals and locals. leaving only local to local collision, which can usually be resolved by giving the local another random name i, j, k, l etc.

And I'm sure everybody always does that religiously.
 But even if we didn't, we could still wish to declare variables  
 physically
 close to where they are going to be used.

Sure, and that will/should be possible eg. { int x; ... } { int x; ... } no problems here. { int x; ... { int x; <-error, rename to 'y' or 'i' or ... ... } }

Yep, I'm sure this would be the most common workaround.
 In this case I think I personally would choose safety over convenience  
 as
 there are workarounds for the convenience issue, but none for the safety
 issue.

Yeah, I guess you are right here, but explaining the exceptions to the rule to a new comer could be interesting.

The rule is if a variable in any scope hides a variable in an outer scope it's an error, plain and simple.

Except for module scoped symbols ;-) A variable declared inside a function hides a same-named variable declared outside the function inside the same module. Example ... uint Line_Counter; import std.stdio; uint foo() { uint Line_Counter; Line_Counter = 2; return Line_Counter; } And thus we have an exception to the rule "if a variable in any scope hides a variable in an outer scope it's an error".
 Module scope is okay to hide but
 function scope is a no-no.

That's not an exception. Module scope is similar to: { int x; <-module 1 ... } <-module 2 { int x; ... } each module has it's own 'global' scope. Which you access by using the module name. However, D gives us a shortcut, and detects collisions requiring alias to resolve eg. [a.d] int i; [b.d] int i; import a; import b; i = 5; <-error, which one //soln1 a.i = 5; //soln2 alias i a.i; i = 5;

I wasn't talking about same-named symbols declared in different modules. And note, we have a mechanism to disambiguate that situation, so thus I (unjokingly) suggested that a similar mechanism might be useful within a single module. -- Derek Parnell Melbourne, Australia http://www.dsource.org/projects/build/ v.1.19 released 04/Apr/2005 http://www.prowiki.org/wiki4d/wiki.cgi?FrontPage 4/04/2005 10:55:12 AM
Apr 03 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
I've done a bad job of explaining myself. Let me try again:

I believe the rule should be "If a variable in a scope hides a variable in  
an outer scope it is an error" - no exceptions, none.

What I was trying to do below was give solutions to the obvious problems  
this rule will create, reasons for those solutions in terms of good  
programming practice and the reasons why I see it as good programming  
practice.

In short, all of these would be errors:

int a;
void foo(int a) {}

int a
void foo() { int a; }

int a;
void foo() {
   if(true) {
     int a;
   }
}

void foo() {
   int a;
   if(true) {
     int a;
   }
}

int a;
for(int a;;){}

int a;
for(;;){ int a; }

..etc.. you get the idea.

To solve the above you have to rename one of the variables. I don't see  
that as a bad thing, in fact I believe it could force better programming  
practice. For example:

int index;
void foo() {
   int index;
}

here, perhaps the global should be renamed (or even moved). Why is it  
global? What is "index" an index of? Possble solutions:

#1
class File {
   int index;
}
void foo() {
   int index;
}

#2
int fileIndex;
void foo() {
   int index;
}

or perhaps the temporary should be renamed:

int index;
void foo() {
   int i;
}

I appologise for missunderstanding your next comment...

 int index_a;
 Foo()
 {
   int index_A;
   . . .

   index_a = 1; // Did I really mean this or index_A?
 }

 Maybe we could have an explicit resolution mechanism to disambiguate  
 such
 name hiding?

This is a joke, right? If not please explain.

No, it was not a joke. Ok, try not to get hung up with the specific characters I just coincidently happen to use in this reply; try generalizing it instead. But what if, the character ' ' when prefixing a symbol name, was an instruction for the compile to use the inner most scope to resolve an otherwise ambiguous symbol name. For example ... void Foo() { int Pretend_That_This_Is_A_Decent_Variable_Name; { double Pretend_That_This_Is_A_Decent_Variable_Name; . . . // Explicitly refer to the innermost scope. Pretend_That_This_Is_A_Decent_Variable_Name += 1.2; } } See, no joke involved.

I thought you were referring to the typo above not the original topic when you said "Maybe we could have an explicit resolution mechanism to disambiguate ... ". I thought you might be jokingly suggesting that to resolve the problem with the typo was to type the correct character. :) Using a symbol to refer to the inner/current scope isn't a bad idea. It's like the "." used for outermost?/module?/file? scope. If however my rule was implemented you wouldn't get as far as to actually use it, as:
   void Foo()
   {
      int Pretend_That_This_Is_A_Decent_Variable_Name;

      {
         double Pretend_That_This_Is_A_Decent_Variable_Name;

would error here. The rest of the post I have snipped as it appears to me to revolve around our missunderstanding. Regan
Apr 03 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
This is interesting and sort-of on point. :)

http://www.cse.unsw.edu.au/~cs3141/ip.asf
http://www.codegeneration.net/tiki-read_article.php?articleId=61
http://www.edge.org/digerati/simonyi/simonyi_p1.html

Regan

On Mon, 04 Apr 2005 15:11:14 +1200, Regan Heath <regan netwin.co.nz> wrote:
 I've done a bad job of explaining myself. Let me try again:

 I believe the rule should be "If a variable in a scope hides a variable  
 in an outer scope it is an error" - no exceptions, none.

 What I was trying to do below was give solutions to the obvious problems  
 this rule will create, reasons for those solutions in terms of good  
 programming practice and the reasons why I see it as good programming  
 practice.

 In short, all of these would be errors:

 int a;
 void foo(int a) {}

 int a
 void foo() { int a; }

 int a;
 void foo() {
    if(true) {
      int a;
    }
 }

 void foo() {
    int a;
    if(true) {
      int a;
    }
 }

 int a;
 for(int a;;){}

 int a;
 for(;;){ int a; }

 ..etc.. you get the idea.

 To solve the above you have to rename one of the variables. I don't see  
 that as a bad thing, in fact I believe it could force better programming  
 practice. For example:

 int index;
 void foo() {
    int index;
 }

 here, perhaps the global should be renamed (or even moved). Why is it  
 global? What is "index" an index of? Possble solutions:

 #1
 class File {
    int index;
 }
 void foo() {
    int index;
 }

 #2
 int fileIndex;
 void foo() {
    int index;
 }

 or perhaps the temporary should be renamed:

 int index;
 void foo() {
    int i;
 }

 I appologise for missunderstanding your next comment...

 int index_a;
 Foo()
 {
   int index_A;
   . . .

   index_a = 1; // Did I really mean this or index_A?
 }

 Maybe we could have an explicit resolution mechanism to disambiguate  
 such
 name hiding?

This is a joke, right? If not please explain.

No, it was not a joke. Ok, try not to get hung up with the specific characters I just coincidently happen to use in this reply; try generalizing it instead. But what if, the character ' ' when prefixing a symbol name, was an instruction for the compile to use the inner most scope to resolve an otherwise ambiguous symbol name. For example ... void Foo() { int Pretend_That_This_Is_A_Decent_Variable_Name; { double Pretend_That_This_Is_A_Decent_Variable_Name; . . . // Explicitly refer to the innermost scope. Pretend_That_This_Is_A_Decent_Variable_Name += 1.2; } } See, no joke involved.

I thought you were referring to the typo above not the original topic when you said "Maybe we could have an explicit resolution mechanism to disambiguate ... ". I thought you might be jokingly suggesting that to resolve the problem with the typo was to type the correct character. :) Using a symbol to refer to the inner/current scope isn't a bad idea. It's like the "." used for outermost?/module?/file? scope. If however my rule was implemented you wouldn't get as far as to actually use it, as:
   void Foo()
   {
      int Pretend_That_This_Is_A_Decent_Variable_Name;

      {
         double Pretend_That_This_Is_A_Decent_Variable_Name;

would error here. The rest of the post I have snipped as it appears to me to revolve around our missunderstanding. Regan

Apr 03 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Mon, 04 Apr 2005 16:33:21 +1200, Regan Heath wrote:

 On Mon, 04 Apr 2005 15:11:14 +1200, Regan Heath <regan netwin.co.nz> wrote:
 I've done a bad job of explaining myself. Let me try again:

 I believe the rule should be "If a variable in a scope hides a variable  
 in an outer scope it is an error" - no exceptions, none.

 What I was trying to do below was give solutions to the obvious problems  
 this rule will create, reasons for those solutions in terms of good  
 programming practice and the reasons why I see it as good programming  
 practice.


I can live with this. It will mean that occasionally I will be forced to do the 'right thing' but, hey, why not try something new ;-) -- Derek Melbourne, Australia 4/04/2005 3:36:36 PM
Apr 03 2005
next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 4 Apr 2005 15:38:31 +1000, Derek Parnell <derek psych.ward> wrote:
 On Mon, 04 Apr 2005 16:33:21 +1200, Regan Heath wrote:

 On Mon, 04 Apr 2005 15:11:14 +1200, Regan Heath <regan netwin.co.nz>  
 wrote:
 I've done a bad job of explaining myself. Let me try again:

 I believe the rule should be "If a variable in a scope hides a variable
 in an outer scope it is an error" - no exceptions, none.

 What I was trying to do below was give solutions to the obvious  
 problems
 this rule will create, reasons for those solutions in terms of good
 programming practice and the reasons why I see it as good programming
 practice.


I can live with this. It will mean that occasionally I will be forced to do the 'right thing' but, hey, why not try something new ;-)

I realise some people are going to disagree about what the "right thing" to do is. Of course this *is* a divergance from C/C++ where this is "legal" code (at least according to MSVC). --[hide.c]-- int the_var = 0; void foo(int the_var) { the_var = 2; } void bar() { int the_var; the_var = 3; } int main() { int the_var = 1; foo(the_var); bar(); //for(int the_var = 4;;) { break; } for(;;) { int the_var = 5; break; } { int the_var = 6; the_var = 7; { int the_var = 8; the_var = 9; } } return 0; } NOTE: The commented line above, C does not allow this for construction. --[hide.cpp]-- int the_var = 0; void foo(int the_var) { the_var = 2; } void bar() { int the_var; the_var = 3; } int main() { //int the_var = 1; foo(the_var); bar(); for(int the_var = 4;;) { break; } for(;;) { int the_var = 5; break; } { int the_var = 6; the_var = 7; { int the_var = 8; the_var = 9; } } return 0; } NOTE: The commented line above, if added to the code causes an error on the first for loop. But notice the global did not cause the same error. Regan p.s. Did you read/watch the link on IP. IIRC it's basically using a database to detatch the identity of a variable from it's name, allowing you to call variables by the most appropriate name in each situation/location. Sort of like D's alias (but not quite) and sort of like what happens when you pass things to a function i.e. void foo(int index) {} int i; //temporary var used to calculate something i = //calculate something foo(i); So 'i' a temporary becomes "index" when passed to foo. The name has changed but the variable is the same.
Apr 03 2005
parent Derek Parnell <derek psych.ward> writes:
On Mon, 04 Apr 2005 18:00:35 +1200, Regan Heath wrote:

[snip]

 I realise some people are going to disagree about what the "right thing"  
 to do is.
 
 Of course this *is* a divergance from C/C++ where this is "legal" code (at  
 least according to MSVC).

I still want D to be D, rather than an evolved C, so that's not going to worry me.
 p.s. Did you read/watch the link on IP. 

-- Derek Parnell Melbourne, Australia http://www.dsource.org/projects/build/ v1.19 released 04/Apr/2005 http://www.prowiki.org/wiki4d/wiki.cgi?FrontPage 4/04/2005 4:18:46 PM
Apr 03 2005
prev sibling parent reply Thomas Kuehne <thomas-dloop kuehne.thisisspam.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Derek Parnell schrieb am Mon, 4 Apr 2005 15:38:31 +1000:
 On Mon, 04 Apr 2005 16:33:21 +1200, Regan Heath wrote:

 On Mon, 04 Apr 2005 15:11:14 +1200, Regan Heath <regan netwin.co.nz> wrote:
 I've done a bad job of explaining myself. Let me try again:

 I believe the rule should be "If a variable in a scope hides a variable  
 in an outer scope it is an error" - no exceptions, none.



<snip>
 I can live with this. It will mean that occasionally I will be forced to do
 the 'right thing' but, hey, why not try something new ;-)

That's sensible - with one restriction: modules are the higest scope level, trying to enforce this for package/subpackage scopes would be troublesome. Please activate that rule for the -w mode first, so that there is enough time to fix existing code. Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFCUOkC3w+/yD4P9tIRAuYQAJ9z3z3tL3UrQmQkiptJ1rP+32ZQkQCbBFNQ ggz8iZBUVeArGH1qNFnrQFw= =EL8s -----END PGP SIGNATURE-----
Apr 04 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 4 Apr 2005 09:13:06 +0200, Thomas Kuehne  
<thomas-dloop kuehne.thisisspam.cn> wrote:
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1

 Derek Parnell schrieb am Mon, 4 Apr 2005 15:38:31 +1000:
 On Mon, 04 Apr 2005 16:33:21 +1200, Regan Heath wrote:

 On Mon, 04 Apr 2005 15:11:14 +1200, Regan Heath <regan netwin.co.nz>  
 wrote:
 I've done a bad job of explaining myself. Let me try again:

 I believe the rule should be "If a variable in a scope hides a  
 variable
 in an outer scope it is an error" - no exceptions, none.



<snip>
 I can live with this. It will mean that occasionally I will be forced  
 to do
 the 'right thing' but, hey, why not try something new ;-)

That's sensible - with one restriction: modules are the higest scope level, trying to enforce this for package/subpackage scopes would be troublesome.

Do you mean? --[pack\mod1.d]-- int i; --[pack\mod2.d]-- int i; --[foo.d]-- import pack.mod1; import pack.mod2; i = 5; <- error, which one.
 Please activate that rule for the -w mode first, so that there is enough  
 time to fix existing code.

Good idea. Walter what do you think? Regan
Apr 04 2005
parent reply Thomas Kuehne <thomas-dloop kuehne.thisisspam.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Regan Heath schrieb am Tue, 05 Apr 2005 09:45:23 +1200:
 On Mon, 4 Apr 2005 09:13:06 +0200, Thomas Kuehne  
<thomas-dloop kuehne.thisisspam.cn> wrote:
 Derek Parnell schrieb am Mon, 4 Apr 2005 15:38:31 +1000:
 On Mon, 04 Apr 2005 16:33:21 +1200, Regan Heath wrote:

 On Mon, 04 Apr 2005 15:11:14 +1200, Regan Heath <regan netwin.co.nz>  
 wrote:
 I've done a bad job of explaining myself. Let me try again:

 I believe the rule should be "If a variable in a scope hides a  
 variable
 in an outer scope it is an error" - no exceptions, none.



<snip>
 I can live with this. It will mean that occasionally I will be forced  
 to do
 the 'right thing' but, hey, why not try something new ;-)

That's sensible - with one restriction: modules are the higest scope level, trying to enforce this for package/subpackage scopes would be troublesome.

Do you mean?

<snip> - --[pack\mod1.d]-- int i; - --[pack\mod2.d]-- int i; <- error, second i in package scope "pack" Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFCUbwr3w+/yD4P9tIRApMYAKC1GLbWe6wkis53ZbZsr2VAFyvAawCgjpQo GSGXEvV+dbOoi+XTz9PlQWw= =yIcs -----END PGP SIGNATURE-----
Apr 04 2005
parent "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 5 Apr 2005 00:14:04 +0200, Thomas Kuehne  
<thomas-dloop kuehne.thisisspam.cn> wrote:
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1

 Regan Heath schrieb am Tue, 05 Apr 2005 09:45:23 +1200:
 On Mon, 4 Apr 2005 09:13:06 +0200, Thomas Kuehne
 <thomas-dloop kuehne.thisisspam.cn> wrote:
 Derek Parnell schrieb am Mon, 4 Apr 2005 15:38:31 +1000:
 On Mon, 04 Apr 2005 16:33:21 +1200, Regan Heath wrote:

 On Mon, 04 Apr 2005 15:11:14 +1200, Regan Heath <regan netwin.co.nz>
 wrote:
 I've done a bad job of explaining myself. Let me try again:

 I believe the rule should be "If a variable in a scope hides a
 variable
 in an outer scope it is an error" - no exceptions, none.



<snip>
 I can live with this. It will mean that occasionally I will be forced
 to do
 the 'right thing' but, hey, why not try something new ;-)

That's sensible - with one restriction: modules are the higest scope level, trying to enforce this for package/subpackage scopes would be troublesome.

Do you mean?

<snip> - --[pack\mod1.d]-- int i; - --[pack\mod2.d]-- int i; <- error, second i in package scope "pack"

To me, the above is comparable to: void pack() { { //mod1 int i; } { //mod2 int i; } } as in mod1 and mod2 are beside each other, one is not inside the other. However, if it were possible for "int i" to exist in "pack" itself, then the one in "mod1" or "mod2" would be in hiding a variable in an outer scope "pack". Regan
Apr 04 2005
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Derek Parnell wrote:

 Either the documentation is wrong or DMD is wrong. The examples below
 compile and run successfully, but according to the docs they should fail.
 
 <code>
  void func2()
  {
     int x;
 
     {int x;// illegal, x is multiply defined in function scope
     }
  }

I'm not sure if this should be allowed. Does it really make sense for local variables to eclipse each other?
  void func3()
  {
     {int x;
     }
     {int x;// illegal, x is multiply defined in function scope
     }
  }
 </code>

This ought to be legal, considering that they have disjoint scopes, and so the first x would be out of the current symbol table by the time the second one comes along. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on on the 'group where everyone may benefit.
Apr 03 2005
parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
++Stewart.opinion.votes;


Stewart Gordon wrote:
 Derek Parnell wrote:
 
 Either the documentation is wrong or DMD is wrong. The examples below
 compile and run successfully, but according to the docs they should fail.

 <code>
  void func2()
  {
     int x;

     {int x;// illegal, x is multiply defined in function scope
     }
  }

I'm not sure if this should be allowed. Does it really make sense for local variables to eclipse each other?
  void func3()
  {
     {int x;
     }
     {int x;// illegal, x is multiply defined in function scope
     }
  }
 </code>

<snip> This ought to be legal, considering that they have disjoint scopes, and so the first x would be out of the current symbol table by the time the second one comes along.

-- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Apr 03 2005