Thursday, September 25, 2014

Confusing Errors for a Confusing Feature? I disagree.

I follow Eric Lippert's blog "Fabulous adventures in coding" and his post today (Confusing errors for a confusing feature, part one) talks about a "confusing feature" and it's "confusing errors" of which I disagree.

I don't think that these errors are confusing at all, let me give you a little background of the issue before we begin.

Eric speaks about a feature in C# that requires unique meaning of variables throughout a block of code, something that means that you can't create a variable with the same name twice in the same block of code(scope), and you can't create a variable of the same name in a child scope either because it would make the variable ambiguous.

Eric says that he has a love/hate relationship with this feature, it keeps him from coding bugs into his applications occasionally.

What Eric doesn't like about this is the error that occurs when you try to declare a variable twice in the same scope.


 class C
 {
     static void M1()
     {
         int x2;
         {
             int x2;
         }
     }
 }


Gives an Error on the Inner x2:

error CS0136: A local variable named 'x2' cannot be declared in
this scope because it would give a different meaning to 'x2', which is
already used in a 'parent or current' scope to denote something else
Here is the direct quote from Eric after he says this,
It is no wonder I get mail from confused programmers when they see that crazy error message! 
What is crazy about that error?  It's in plain English, if you declare a second variable named the same as a previous variable it will overwrite the previous variable.  If this was something that the coder did intentionally then they should know that they don't need to declare the variable a second time and that they should just reassign the variable, on the other hand, if it was unintentional then it is probably bad naming on the part of the programmer.

I can see this being an issue when looking at some of the bad naming schemes that come across Code Review.  I know that the example code is just example code, but we come across code where the variables are listed nearly in alphabetical order

 class C  
 {  
     static void M1()  
     {  
         int a;  
         int b;  
         int c;  
         // ...  
         int x2;  
         {  
             int x2;  
         }  
     }  
 }  

and the meaning behind the variable is a lucky guess or only known to the original coder, kind of like Magic Numbers, but this is straying from the point of both posts.

The second thing (and third thing) that Eric says about this error is

And while we’re looking at this, why is 'parent or current' in quotes, and why doesn’t the compiler differentiate between whether it is the parent scope or the current scope?
In which I reply, the variable exists in both scopes, parent and child, meaning that where the error occurs the variable is in the current scope as well as in the parent scope, it already exists in scope.

This all points to naming, why should you need two variables named the exact same thing in the same scope?  You shouldn't it points flaws in the logic of the code you are trying to write.

RubberDuck from Code Review has from time to time pointed to one of Joel Spolsky's post titled "Making Wrong Code Look Wrong" and I think that trying to declare the same variable twice in the same scope falls under things that look wrong, because it is wrong and is a bad programming habit that C# didn't want invading from C++.

After those two statements Eric continues on to the next point and doesn't explain why doing this is a bad thing or how to keep from making this error in the future.

If we flip things around and try to declare the variable after one has been declared inside of a child scope the error message is a bit different.


 static void M3()  
 {  
     {  
         int x4;  
     }  
     int x4;  
 }  

Produces the following error:

error CS0136: A local variable named 'x4' cannot be declared in
this scope because it would give a different meaning to 'x4', which is
already used in a 'child' scope to denote something else
The compiler creates locations for all the variables ahead of time, scope is a means of use, or a map. If we have two cities right next to each other, with the same name in the same state, but in different counties it would be confusing regardless of which one is seen first, so why is this concept so confusing?

--------------------------------------------------------------------------------------------------------------------

I am sure that there is method to his madness in this post seeing that it is "part one" in the series of posts.

This post is more me thinking out loud about the whole thing and I should note also as a disclaimer that I didn't follow the directions and read the post he linked to before writing this post, for everyone's sake here is the link

Simple names are not so simple, part one

I look forward to the life long journey of learning, and the next post (whoever's it may be)

CodeReview User: Malachi

7 comments:

  1. One problem I think is that many languages have no concept of "throwaway variables", i.e. variables which are used within such a small area of the code that it would take less time for someone to read a short name and find where the variable is set, than to try to read and comprehend a longer name. Presently, language designs often push programmers to either assign different names to all their throwaway variables, creating the risk that they might refer to an earlier throwaway variable at a place where they meant to use the most recent, or else declare the throwaway variables once at the start of a method and then reuse them, creating the risk that new code might reuse a variable whose value is still needed. I would posit that it would be better for languages to have a means of declaring particular variables as "throwaways' and dividing methods into regions whose throwaway variables were independent, while retaining the possibility of declaring and assigning "real" variables within those regions.

    Of course, any such proposal is apt to meet the same sort of reaction as telescoping sections within a method. While it is certainly true that most methods which would be so large as to be unmanageable without telescoping sections should have a lot of code moved out into other methods, and the same is true in cases where compiler-recognized throwaway variables would be helpful, there is considerable value in having code appear in source code within the context where it will be executed. If a method is devoting a substantial portion of its code to testing preconditions, moving that code into a separate method may not be particularly helpful, but that doesn't mean everyone reading the method should always have to devote screen space to such code.

    ReplyDelete
    Replies
    1. I see your point, but in object oriented programming if you have some things that only need to be used for a short time, chances are that you really need a helper method or a complete class for something in your code. compartmentalizing the code makes it cleaner and optimizes it for the compiler.

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. If a method call would require the same value to be used two or more times in its parameter list, and computation of that value is either syntactically bulky or time consuming, but the method call is not otherwise particularly complicated, factoring out the code into a helper method might not really help much. If `Foo.Bar` is a property, then given `gr.LineTo(Foo.Bar.X, Foo.Bar.Y)` the compiler is required to generate two calls to `Foo.Bar`. Changing the code to `var it=Foo.Bar; gr.LineTo(it.X, it.Y)` [two lines] eliminates that redundancy.

      While it would be possible to define a method which would draw the necessary line given `gr` and `Foo.Bar`, I would consider `LineTo(gr, Foo.Bar)`; to be less clear than the version using "it", and an extension might not be much better [since it would look like the graphic context is supposed to know how to get the X and Y coordinates from Foo.Bar]. The version with "it" would be just about perfect, except that there's no way to indicate that "it" should be considered a throwaway variable.

      Delete
    2. You are creating a variable to hold an object temporarily in which you want to throw it away, why not create the object with the correct Property Accessors in the first place? am I in complete understanding of what you are saying?

      Delete
    3. The variable `it` is used just long enough to read the X once and the Y once. After that, code doesn't need `it` anymore. I use the term "throwaway variable" to refer to a variable whose value will be used very soon after it is set (in many cases only in the immediate following statement) and never used after that. The value isn't copied to `it` for the purpose of being thrown away, but it will be needed for such a short period of time after which the variable might as well be "thrown away" because it won't be needed anymore.

      Delete
  3. Do you understand what I mean by "throwaway"? What do you think of the concept? One possible implementation in a language might be to allow the use of variables $A-$Z, with the proviso that some sort of "separator line" would cause all such variables to become undefined. Another approach would be to allow a variable declaration within a scope to be preceded by the word "out", thus allowing code which needs to use some temporary variables when determining the value for a variable that will be set once and never modified to create a scope for those temporary variables, but make the variable thus declared available to outside code in cases where either the block was used for scoping only, or was in part of the controlled section of a "do-while" loop that was going to execute unconditionally.

    ReplyDelete