Variable shadowing

Last updated

In computer programming, variable shadowing occurs when a variable declared within a certain scope (decision block, method, or inner class) has the same name as a variable declared in an outer scope. At the level of identifiers (names, rather than variables), this is known as name masking. This outer variable is said to be shadowed by the inner variable, while the inner identifier is said to mask the outer identifier. This can lead to confusion, as it may be unclear which variable subsequent uses of the shadowed variable name refer to, which depends on the name resolution rules of the language

Contents

One of the first languages to introduce variable shadowing was ALGOL, which first introduced blocks to establish scopes. It was also permitted by many of the derivative programming languages including C, C++ and Java.

The C# language breaks this tradition, allowing variable shadowing between an inner and an outer class, and between a method and its containing class, but not between an if-block and its containing method, or between case statements in a switch block.

Some languages allow variable shadowing in more cases than others. For example Kotlin allows an inner variable in a function to shadow a passed argument and a variable in an inner block to shadow another in an outer block, while Java does not allow these. Both languages allow a passed argument to a function/Method to shadow a Class Field. [1]

Some languages disallow variable shadowing completely such as CoffeeScript. [2]

Example

Lua

The following Lua code provides an example of variable shadowing, in multiple blocks.

v=1-- a global variabledolocalv=v+1-- a new local that shadows global vprint(v)-- prints 2dolocalv=v*2-- another local that shadows outer local vprint(v)-- prints 4endprint(v)-- prints 2endprint(v)-- prints 1

Python

The following Python code provides another example of variable shadowing:

x=0defouter():x=1definner():x=2print("inner:",x)inner()print("outer:",x)outer()print("global:",x)# prints# inner: 2# outer: 1# global: 0

As there is no variable declaration but only variable assignment in Python, the keyword nonlocal introduced in Python 3 is used to avoid variable shadowing and assign to non-local variables:

x=0defouter():x=1definner():nonlocalxx=2print("inner:",x)inner()print("outer:",x)outer()print("global:",x)# prints# inner: 2# outer: 2# global: 0

The keyword global is used to avoid variable shadowing and assign to global variables:

x=0defouter():x=1definner():globalxx=2print("inner:",x)inner()print("outer:",x)outer()print("global:",x)# prints# inner: 2# outer: 1# global: 2

Rust

fnmain(){letx=0;{// Shadowletx=1;println!("Inner x: {}",x);// prints 1}println!("Outer x: {}",x);// prints 0letx="Rust";println!("Outer x: {}",x);// prints 'Rust'}//# Inner x: 1//# Outer x: 0//# Outer x: Rust

C++

#include<iostream>intmain(){intx=42;intsum=0;for(inti=0;i<10;i++){intx=i;std::cout<<"x: "<<x<<'\n';// prints values of i from 0 to 9sum+=x;}std::cout<<"sum: "<<sum<<'\n';std::cout<<"x:   "<<x<<'\n';// prints out 42return0;}

Java

publicclassShadow{privateintmyIntVar=0;publicvoidshadowTheVar(){// Since it has the same name as above object instance field, it shadows above // field inside this method.intmyIntVar=5;// If we simply refer to 'myIntVar' the one of this method is found // (shadowing a second one with the same name)System.out.println(myIntVar);// prints 5// 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);// prints 0}publicstaticvoidmain(String[]args){newShadow().shadowTheVar();}}

JavaScript

ECMAScript 6 introduction of let and const with block scoping allow variable shadowing.

functionmyFunc(){letmy_var='test';if(true){letmy_var='new test';console.log(my_var);// new test}console.log(my_var);// test}myFunc();

See also

Related Research Articles

<span class="mw-page-title-main">Quine (computing)</span> Self-replicating program

A quine is a computer program that takes no input and produces a copy of its own source code as its only output. The standard terms for these programs in the computability theory and computer science literature are "self-replicating programs", "self-reproducing programs", and "self-copying programs".

In computer programming, the scope of a name binding is the part of a program where the name binding is valid; that is, where the name can be used to refer to the entity. In other parts of the program, the name may refer to a different entity, or to nothing at all. Scope helps prevent name collisions by allowing the same name to refer to different objects – as long as the names have separate scopes. The scope of a name binding is also known as the visibility of an entity, particularly in older or more technical literature—this is in relation to the referenced entity, not the referencing name.

In programming languages, a closure, also lexical closure or function closure, is a technique for implementing lexically scoped name binding in a language with first-class functions. Operationally, a closure is a record storing a function together with an environment. The environment is a mapping associating each free variable of the function with the value or reference to which the name was bound when the closure was created. Unlike a plain function, a closure allows the function to access those captured variables through the closure's copies of their values or references, even when the function is invoked outside their scope.

In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, dynamically, without affecting the behavior of other instances of the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern as well as to the Open-Closed Principle, by allowing the functionality of a class to be extended without being modified. Decorator use can be more efficient than subclassing, because an object's behavior can be augmented without defining an entirely new object.

In mathematics and computer science, a higher-order function (HOF) is a function that does at least one of the following:

In computer programming, a default argument is an argument to a function that a programmer is not required to specify. In most programming languages, functions may take one or more arguments. Usually, each argument must be specified in full. Later languages allow the programmer to specify default arguments that always have a value, even if one is not specified when calling the function.

In computer programming, a function object is a construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax. In some languages, particularly C++, function objects are often called functors.

<span class="mw-page-title-main">Foreach loop</span> Control flow statement for traversing items in a collection

In computer programming, foreach loop is a control flow statement for traversing items in a collection. foreach is usually used in place of a standard for loop statement. Unlike other for loop constructs, however, foreach loops usually maintain no explicit counter: they essentially say "do this to everything in this set", rather than "do this x times". This avoids potential off-by-one errors and makes code simpler to read. In object-oriented languages, an iterator, even if implicit, is often used as the means of traversal.

In the C++ programming language, a reference is a simple reference datatype that is less powerful but safer than the pointer type inherited from C. The name C++ reference may cause confusion, as in computer science a reference is a general concept datatype, with pointers and C++ references being specific reference datatype implementations. The definition of a reference in C++ is such that it does not need to exist. It can be implemented as a new name for an existing object.

<span class="mw-page-title-main">Method overriding</span> Language feature in object-oriented programming

Method overriding, in object-oriented programming, is a language feature that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its superclasses or parent classes. In addition to providing data-driven algorithm-determined parameters across virtual network interfaces, it also allows for a specific type of polymorphism (subtyping). The implementation in the subclass overrides (replaces) the implementation in the superclass by providing a method that has same name, same parameters or signature, and same return type as the method in the parent class. The version of a method that is executed will be determined by the object that is used to invoke it. If an object of a parent class is used to invoke the method, then the version in the parent class will be executed, but if an object of the subclass is used to invoke the method, then the version in the child class will be executed. This helps in preventing problems associated with differential relay analytics which would otherwise rely on a framework in which method overriding might be obviated. Some languages allow a programmer to prevent a method from being overridden.

In the Perl programming language, autovivification is the automatic creation of new arrays and hashes as required every time an undefined value is dereferenced. Perl autovivification allows a programmer to refer to a structured variable, and arbitrary sub-elements of that structured variable, without expressly declaring the existence of the variable and its complete structure beforehand.

In mathematics and in computer programming, a variadic function is a function of indefinite arity, i.e., one which accepts a variable number of arguments. Support for variadic functions differs widely among programming languages.

In number theory, a narcissistic number in a given number base is a number that is the sum of its own digits each raised to the power of the number of digits.

In computer programming, an anonymous function is a function definition that is not bound to an identifier. Anonymous functions are often arguments being passed to higher-order functions or used for constructing the result of a higher-order function that needs to return a function. If the function is only used once, or a limited number of times, an anonymous function may be syntactically lighter than using a named function. Anonymous functions are ubiquitous in functional programming languages and other languages with first-class functions, where they fulfil the same role for the function type as literals do for other data types.

In programming languages and type theory, an option type or maybe type is a polymorphic type that represents encapsulation of an optional value; e.g., it is used as the return type of functions which may or may not return a meaningful value when they are applied. It consists of a constructor which either is empty, or which encapsulates the original data type A.

Different command-line argument parsing methods are used by different programming languages to parse command-line arguments.

In computer programming, the async/await pattern is a syntactic feature of many programming languages that allows an asynchronous, non-blocking function to be structured in a way similar to an ordinary synchronous function. It is semantically related to the concept of a coroutine and is often implemented using similar techniques, and is primarily intended to provide opportunities for the program to execute other code while waiting for a long-running, asynchronous task to complete, usually represented by promises or similar data structures. The feature is found in C#, C++, Python, F#, Hack, Julia, Dart, Kotlin, Rust, Nim, JavaScript, Swift and Zig.

Swift is a high-level general-purpose, multi-paradigm, compiled programming language developed by Apple Inc. and the open-source community. Swift compiles to machine code, as it is an LLVM-based compiler. Swift was first released in June 2014, and the Swift toolchain has shipped in Xcode since version 6, released in 2014.

<span class="mw-page-title-main">Nim (programming language)</span> Programming language

Nim is a general-purpose, multi-paradigm, statically typed, compiled high-level systems programming language, designed and developed by a team around Andreas Rumpf. Nim is designed to be "efficient, expressive, and elegant", supporting metaprogramming, functional, message passing, procedural, and object-oriented programming styles by providing several features such as compile time code generation, algebraic data types, a foreign function interface (FFI) with C, C++, Objective-C, and JavaScript, and supporting compiling to those same languages as intermediate representations.

A callable object, in computer programming, is any object that can be called like a function.

References

  1. "From Java to Kotlin and Back Again". Archived from the original on 2020-11-28. Retrieved 2021-10-04.
  2. "Please introduce explicit shadowing · Issue #2697 · jashkenas/Coffeescript". GitHub . Archived from the original on 2021-10-04. Retrieved 2021-10-04.