Shadowing Variables

How bad is redefining/shadowing a local variable?


I noticed there were a lot of errors where a local variable was redefined inside a function for example.

You are not demonstrating redefining here. You show an example of variable shadowing.

Variable shadowing is not an error syntactically. It is valid and well defined. However, if your intention was to use the variable from the outer scope, then you could consider it a logical error.

but can the compiler really mess things up

No.

The problem with shadowing is that it can be hard to keep track of for the programmer. It is trivial for the compiler. You can find plenty of questions on this very site, stemming from confusion caused by shadowed variables.

It is not too difficult to grok which expression uses which variable in this small function, but imagine the function being dozens of lines and several nested and sequential blocks. If the function is long enough that you cannot see all the different definitions in different scopes at a glance, you are likely to make a misinterpretation.

declaration of 'count' hides previous local declaration 

This is a somewhat useful compiler warning. You haven't run out of names, so why not give a unique name for all local variables in the function? However, there is no need to treat this warning as an error. It is merely a suggestion to improve the readability of your program.

In this particular example, you don't need the count in the outer scope after the inner scope opens, so you might as well reuse one variable for both counts.

Is it worth it to change and fix the variable names

Depends on whether you value more short term workload versus long term. Changing the code to use unique, descriptive local variable names is "extra" work now, but every time someone has to understand the program later, unnecessary shadowing will increase the mental challenge.

Trying to understand better variable shadowing

Firstly, you need to understand that you have 2 scopes here one is global and other is functional.
Imagine scope as a object to which each variable defined within it, is attached as a property. Here function scope is nested within global.

Now variable lookup starts from running scope(context). If variable is not present over there it will keep on looking into outer scopes (not inner) until it finds variable or reach global scope

Now case 1:

let a = 10;             //[[globalScope]] = {a: 10}
function increase1(a){ //[[increase1Scope]] = {a : 10} as parameters are local variable to function
a++; } //[[increase1Scope]] = {a: 11}
increase1(a); //here u have passed 10 as a **value** to increase1 param a(you havent passed global variable **"a"** but its value)
console.log('a = ',a); //takes value from its running scope i.e [[globalScope]] which is 10

case 2:

let a = 10;            //[[globalScope]] = {a: 10}
function increase2(){ //no parameters so [[increase2Scope]] = {}
a++;} //[[increase2Scope]] don't have a, so look into next outerscope i.e. [[globalScope]] and alter its value to [[globalScope]] = {a: 11}
increase2(a); //as increase2() has no defined parameter so this argument of 10 wont do anything
console.log('a = ',a); //same from [[globalScope]] = {a: 11}

case 3:

let a = 10;             //[[globalScope]] = {a: 10}
function increase3(x){ //[[increase1Scope]] = {x: 10}
x++; } //[[increase1Scope]] = {x: 11}
increase3(a); //value 10 get passed to increase3 -> x
console.log('a = ',a); //this time [[globalScope]] = {a: 10}, so 10

Now, As increase3() function is not returning anything, so you are getting undefined

console.log('a = ',increase3(a));  //undefined

To get the desired result, include a return statement in function definition:

function increase3(x){  
x++;
return x;
}

Hope it will help. I tried to put something into perspective.
I highly recommend you to go through below online JS book. It will certainly help.

https://javascript.info/closure

What is the pythonic way to avoid shadowing variables?

The fact that the local variable (and function parameter) age happens to have the same name as a variable somewhere else in your program is irrelevant. The whole point of local variables is that they only live within the local scope of the function they're defined in.

The fact that the local variable has the same name as the variable used elsewhere as an argument is especially not a problem. In fact, it's very common in real-life code. For example, picking a random stdlib module, the 3.3 version of cmd, the Cmd.onecmd method has a variable named line, and it passes it as an argument to the self.default method, which binds it to a parameter that's also named line.

The fact that the variable used for the argument happens to be a global variable that you could have accessed, if you didn't have a local variable of the same name, is not a problem unless you actually wanted to access that global variable. Which you didn't want to in your existing code, and almost never should want to. In this case, and in most real-world cases, it's simply a coincidence that means nothing and affects nothing, not a problem you have to solve.


The problem you're having is that PyCharm can't guess whether you wanted the global age to be accessible in whenadult. Is it possible (if not in this trivial case, maybe in more complex cases) that a human might be similarly confused, slowing down his comprehension of your code? Or that you'll one day have to write code in some environment where your code reviewers or teacher or whatever will reject your code because it doesn't pass some linter with no warnings? Maybe.

But really, in any such environment, they'd probably complain about you using global variables in the first place. And you really don't need to here. The only reason age is a global is that it has to be accessible to the top-level code. If you move that code into a function, age can become a local in that function. For example:

def whenadult(age):
return 18 - age

def main():
age = 5
needtowait = whenadult(age)

main() # possibly with an if __name__ == '__main__' guard

This will make PyCharm happy, and any linter tools, and any easily-confused or rigidly-minded human readers. It'll even make your code a tiny bit faster. On the other hand, it's more code to read—only three lines and one indent, but then the whole program is only eight lines long. So, it's a tradeoff that you can make on a case-by-case basis.

Variables shadowing in Kotlin for inner classes: how variables are resolved?

When you do var a = 2 inside the class A, you're not actually shadowing any variable. You're declaring that a is a field of class A, and it defaults to 2.

When you reference a variable in front of a class, Kotlin will add an implicit this (e.g. a becomes this.a) if there is a field with that name but not an upper-level variable with that name. So, the outer a takes precedence over the field, and you'd have to use this.a to access the inner a.

What are Shadow Variables in Java?

Instead of providing my own description i may ask you to read about it for example here: http://en.wikipedia.org/wiki/Variable_shadowing. Once you understood the shadowing of variables i recommend you proceed reading about overlaying/ shadowed methods and visibility in general to get a full understanding of such terms.

Actually since the question was asked in Terms of Java here is a mini-example:

    public class Shadow {

private int myIntVar = 0;

public void shadowTheVar(){

// since it has the same name as above object instance field, it shadows above
// field inside this method
int myIntVar = 5;

// If we simply refer to 'myIntVar' the one of this method is found
// (shadowing a seond one with the same name)
System.out.println(myIntVar);

// If we want to refer to the shadowed myIntVar from this class we need to
// refer to it like this:
System.out.println(this.myIntVar);
}

public static void main(String[] args){
new Shadow().shadowTheVar();
}
}


Related Topics



Leave a reply



Submit