Jump to page: 1 2
Thread overview
Block Scope Rules
Mar 30, 2005
Derek Parnell
Apr 03, 2005
Walter
Apr 03, 2005
Derek Parnell
Apr 03, 2005
Regan Heath
Apr 03, 2005
Derek Parnell
Apr 04, 2005
Regan Heath
Apr 04, 2005
Derek Parnell
Apr 04, 2005
Regan Heath
Apr 04, 2005
Regan Heath
Apr 04, 2005
Derek Parnell
Apr 04, 2005
Regan Heath
Apr 04, 2005
Derek Parnell
Apr 04, 2005
Thomas Kuehne
Apr 04, 2005
Regan Heath
Apr 04, 2005
Thomas Kuehne
Apr 04, 2005
Regan Heath
Apr 03, 2005
Stewart Gordon
Apr 03, 2005
Tom S
March 30, 2005
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
April 03, 2005
"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?


April 03, 2005
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.

Stewart.

-- 
My e-mail is valid but not my primary mailbox.  Please keep replies on on the 'group where everyone may benefit.
April 03, 2005
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
April 03, 2005
++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 +/
April 03, 2005
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
April 03, 2005
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.
(Ahhhh..yep. I did mean function definition.)

  void myFunc(int x) ...

-- 
Derek
Melbourne, Australia
4/04/2005 9:00:32 AM
April 04, 2005
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
April 04, 2005
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
April 04, 2005
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
« First   ‹ Prev
1 2