Lably
Skip to content

Variable shadowing

  • 8 min read
  • 1 chapter

Related on Lably

Through Computer programming, Scope (computer programming) and Identifier (computer languages)

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.

Some languages disallow variable shadowing completely such as CoffeeScript and V (Vlang).

Example

Lua

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

<span id="mwKA"></span><span class="n" id="mwKQ">v</span> <span class="o" id="mwKg">=</span> <span class="mi" id="mwKw">1</span> <span class="c1" id="mwLA">-- a global variable</span> <span class="kr" id="mwLQ">do</span> <span class="kd" id="mwLg">local</span> <span class="n" id="mwLw">v</span> <span class="o" id="mwMA">=</span> <span class="n" id="mwMQ">v</span> <span class="o" id="mwMg">+</span> <span class="mi" id="mwMw">1</span> <span class="c1" id="mwNA">-- a new local that shadows global v</span> <span class="nb" id="mwNQ">print</span><span class="p" id="mwNg">(</span><span class="n" id="mwNw">v</span><span class="p" id="mwOA">)</span> <span class="c1" id="mwOQ">-- prints 2</span> <span class="kr" id="mwOg">do</span> <span class="kd" id="mwOw">local</span> <span class="n" id="mwPA">v</span> <span class="o" id="mwPQ">=</span> <span class="n" id="mwPg">v</span> <span class="o" id="mwPw">*</span> <span class="mi" id="mwQA">2</span> <span class="c1" id="mwQQ">-- another local that shadows outer local v</span> <span class="nb" id="mwQg">print</span><span class="p" id="mwQw">(</span><span class="n" id="mwRA">v</span><span class="p" id="mwRQ">)</span> <span class="c1" id="mwRg">-- prints 4</span> <span class="kr" id="mwRw">end</span> <span class="nb" id="mwSA">print</span><span class="p" id="mwSQ">(</span><span class="n" id="mwSg">v</span><span class="p" id="mwSw">)</span> <span class="c1" id="mwTA">-- prints 2</span> <span class="kr" id="mwTQ">end</span> <span class="nb" id="mwTg">print</span><span class="p" id="mwTw">(</span><span class="n" id="mwUA">v</span><span class="p" id="mwUQ">)</span> <span class="c1" id="mwUg">-- prints 1</span>

Python

The following Python code provides another example of variable shadowing:

<span id="mwWA"></span><span class="n" id="mwWQ">x</span> <span class="o" id="mwWg">=</span> <span class="mi" id="mwWw">0</span> <span class="k" id="mwXA">def</span> <span class="nf" id="mwXQ">outer</span><span class="p" id="mwXg">():</span> <span class="n" id="mwXw">x</span> <span class="o" id="mwYA">=</span> <span class="mi" id="mwYQ">1</span> <span class="k" id="mwYg">def</span> <span class="nf" id="mwYw">inner</span><span class="p" id="mwZA">():</span> <span class="n" id="mwZQ">x</span> <span class="o" id="mwZg">=</span> <span class="mi" id="mwZw">2</span> <span class="nb" id="mwaA">print</span><span class="p" id="mwaQ">(</span><span class="s2" id="mwag">"inner:"</span><span class="p" id="mwaw">,</span> <span class="n" id="mwbA">x</span><span class="p" id="mwbQ">)</span> <span class="n" id="mwbg">inner</span><span class="p" id="mwbw">()</span> <span class="nb" id="mwcA">print</span><span class="p" id="mwcQ">(</span><span class="s2" id="mwcg">"outer:"</span><span class="p" id="mwcw">,</span> <span class="n" id="mwdA">x</span><span class="p" id="mwdQ">)</span> <span class="n" id="mwdg">outer</span><span class="p" id="mwdw">()</span> <span class="nb" id="mweA">print</span><span class="p" id="mweQ">(</span><span class="s2" id="mweg">"global:"</span><span class="p" id="mwew">,</span> <span class="n" id="mwfA">x</span><span class="p" id="mwfQ">)</span> <span class="c1" id="mwfg"># prints</span> <span class="c1" id="mwfw"># inner: 2</span> <span class="c1" id="mwgA"># outer: 1</span> <span class="c1" id="mwgQ"># global: 0</span>

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:

<span id="mwhg"></span><span class="n" id="mwhw">x</span> <span class="o" id="mwiA">=</span> <span class="mi" id="mwiQ">0</span> <span class="k" id="mwig">def</span> <span class="nf" id="mwiw">outer</span><span class="p" id="mwjA">():</span> <span class="n" id="mwjQ">x</span> <span class="o" id="mwjg">=</span> <span class="mi" id="mwjw">1</span> <span class="k" id="mwkA">def</span> <span class="nf" id="mwkQ">inner</span><span class="p" id="mwkg">():</span> <span class="k" id="mwkw">nonlocal</span> <span class="n" id="mwlA">x</span> <span class="n" id="mwlQ">x</span> <span class="o" id="mwlg">=</span> <span class="mi" id="mwlw">2</span> <span class="nb" id="mwmA">print</span><span class="p" id="mwmQ">(</span><span class="s2" id="mwmg">"inner:"</span><span class="p" id="mwmw">,</span> <span class="n" id="mwnA">x</span><span class="p" id="mwnQ">)</span> <span class="n" id="mwng">inner</span><span class="p" id="mwnw">()</span> <span class="nb" id="mwoA">print</span><span class="p" id="mwoQ">(</span><span class="s2" id="mwog">"outer:"</span><span class="p" id="mwow">,</span> <span class="n" id="mwpA">x</span><span class="p" id="mwpQ">)</span> <span class="n" id="mwpg">outer</span><span class="p" id="mwpw">()</span> <span class="nb" id="mwqA">print</span><span class="p" id="mwqQ">(</span><span class="s2" id="mwqg">"global:"</span><span class="p" id="mwqw">,</span> <span class="n" id="mwrA">x</span><span class="p" id="mwrQ">)</span> <span class="c1" id="mwrg"># prints</span> <span class="c1" id="mwrw"># inner: 2</span> <span class="c1" id="mwsA"># outer: 2</span> <span class="c1" id="mwsQ"># global: 0</span>

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

<span id="mwtg"></span><span class="n" id="mwtw">x</span> <span class="o" id="mwuA">=</span> <span class="mi" id="mwuQ">0</span> <span class="k" id="mwug">def</span> <span class="nf" id="mwuw">outer</span><span class="p" id="mwvA">():</span> <span class="n" id="mwvQ">x</span> <span class="o" id="mwvg">=</span> <span class="mi" id="mwvw">1</span> <span class="k" id="mwwA">def</span> <span class="nf" id="mwwQ">inner</span><span class="p" id="mwwg">():</span> <span class="k" id="mwww">global</span> <span class="n" id="mwxA">x</span> <span class="n" id="mwxQ">x</span> <span class="o" id="mwxg">=</span> <span class="mi" id="mwxw">2</span> <span class="nb" id="mwyA">print</span><span class="p" id="mwyQ">(</span><span class="s2" id="mwyg">"inner:"</span><span class="p" id="mwyw">,</span> <span class="n" id="mwzA">x</span><span class="p" id="mwzQ">)</span> <span class="n" id="mwzg">inner</span><span class="p" id="mwzw">()</span> <span class="nb" id="mw0A">print</span><span class="p" id="mw0Q">(</span><span class="s2" id="mw0g">"outer:"</span><span class="p" id="mw0w">,</span> <span class="n" id="mw1A">x</span><span class="p" id="mw1Q">)</span> <span class="n" id="mw1g">outer</span><span class="p" id="mw1w">()</span> <span class="nb" id="mw2A">print</span><span class="p" id="mw2Q">(</span><span class="s2" id="mw2g">"global:"</span><span class="p" id="mw2w">,</span> <span class="n" id="mw3A">x</span><span class="p" id="mw3Q">)</span> <span class="c1" id="mw3g"># prints</span> <span class="c1" id="mw3w"># inner: 2</span> <span class="c1" id="mw4A"># outer: 1</span> <span class="c1" id="mw4Q"># global: 2</span>

Rust

<span id="mw5Q"></span><span class="k" id="mw5g">fn</span> <span class="nf" id="mw5w">main</span><span class="p" id="mw6A">()</span><span class="w" id="mw6Q"> </span><span class="p" id="mw6g">{</span> <span class="w" id="mw6w"> </span><span class="kd" id="mw7A">let</span><span class="w" id="mw7Q"> </span><span class="n" id="mw7g">x</span><span class="w" id="mw7w"> </span><span class="o" id="mw8A">=</span><span class="w" id="mw8Q"> </span><span class="mi" id="mw8g">0</span><span class="p" id="mw8w">;</span> <span class="w" id="mw9A"> </span> <span class="w" id="mw9Q"> </span><span class="p" id="mw9g">{</span> <span class="w" id="mw9w"> </span><span class="c1" id="mw-A">// Shadow</span> <span class="w" id="mw-Q"> </span><span class="kd" id="mw-g">let</span><span class="w" id="mw-w"> </span><span class="n" id="mw_A">x</span><span class="w" id="mw_Q"> </span><span class="o" id="mw_g">=</span><span class="w" id="mw_w"> </span><span class="mi" id="mwAQA">1</span><span class="p" id="mwAQE">;</span> <span class="w" id="mwAQI"> </span><span class="fm" id="mwAQM">println!</span><span class="p" id="mwAQQ">(</span><span class="s" id="mwAQU">"Inner x: {}"</span><span class="p" id="mwAQY">,</span><span class="w" id="mwAQc"> </span><span class="n" id="mwAQg">x</span><span class="p" id="mwAQk">);</span><span class="w" id="mwAQo"> </span><span class="c1" id="mwAQs">// prints 1</span> <span class="w" id="mwAQw"> </span><span class="p" id="mwAQ0">}</span> <span class="w" id="mwAQ4"> </span> <span class="w" id="mwAQ8"> </span><span class="fm" id="mwARA">println!</span><span class="p" id="mwARE">(</span><span class="s" id="mwARI">"Outer x: {}"</span><span class="p" id="mwARM">,</span><span class="w" id="mwARQ"> </span><span class="n" id="mwARU">x</span><span class="p" id="mwARY">);</span><span class="w" id="mwARc"> </span><span class="c1" id="mwARg">// prints 0</span> <span class="w" id="mwARk"> </span> <span class="w" id="mwARo"> </span><span class="kd" id="mwARs">let</span><span class="w" id="mwARw"> </span><span class="n" id="mwAR0">x</span><span class="w" id="mwAR4"> </span><span class="o" id="mwAR8">=</span><span class="w" id="mwASA"> </span><span class="s" id="mwASE">"Rust"</span><span class="p" id="mwASI">;</span> <span class="w" id="mwASM"> </span><span class="fm" id="mwASQ">println!</span><span class="p" id="mwASU">(</span><span class="s" id="mwASY">"Outer x: {}"</span><span class="p" id="mwASc">,</span><span class="w" id="mwASg"> </span><span class="n" id="mwASk">x</span><span class="p" id="mwASo">);</span><span class="w" id="mwASs"> </span><span class="c1" id="mwASw">// prints 'Rust'</span> <span class="p" id="mwAS0">}</span> <span class="c1" id="mwAS4">//# Inner x: 1</span> <span class="c1" id="mwAS8">//# Outer x: 0</span> <span class="c1" id="mwATA">//# Outer x: Rust</span>

C++

<span id="mwATQ"></span><span class="cp" id="mwATU">#include</span><span class="w" id="mwATY"> </span><span class="cpf" id="mwATc"><iostream></span> <span class="kt" id="mwATg">int</span><span class="w" id="mwATk"> </span><span class="nf" id="mwATo">main</span><span class="p" id="mwATs">()</span> <span class="p" id="mwATw">{</span> <span class="w" id="mwAT0"> </span><span class="kt" id="mwAT4">int</span><span class="w" id="mwAT8"> </span><span class="n" id="mwAUA">x</span><span class="w" id="mwAUE"> </span><span class="o" id="mwAUI">=</span><span class="w" id="mwAUM"> </span><span class="mi" id="mwAUQ">42</span><span class="p" id="mwAUU">;</span> <span class="w" id="mwAUY"> </span><span class="kt" id="mwAUc">int</span><span class="w" id="mwAUg"> </span><span class="n" id="mwAUk">sum</span><span class="w" id="mwAUo"> </span><span class="o" id="mwAUs">=</span><span class="w" id="mwAUw"> </span><span class="mi" id="mwAU0">0</span><span class="p" id="mwAU4">;</span> <span class="w" id="mwAU8"> </span><span class="k" id="mwAVA">for</span><span class="w" id="mwAVE"> </span><span class="p" id="mwAVI">(</span><span class="kt" id="mwAVM">int</span><span class="w" id="mwAVQ"> </span><span class="n" id="mwAVU">i</span><span class="w" id="mwAVY"> </span><span class="o" id="mwAVc">=</span><span class="w" id="mwAVg"> </span><span class="mi" id="mwAVk">0</span><span class="p" id="mwAVo">;</span><span class="w" id="mwAVs"> </span><span class="n" id="mwAVw">i</span><span class="w" id="mwAV0"> </span><span class="o" id="mwAV4"><</span><span class="w" id="mwAV8"> </span><span class="mi" id="mwAWA">10</span><span class="p" id="mwAWE">;</span><span class="w" id="mwAWI"> </span><span class="n" id="mwAWM">i</span><span class="o" id="mwAWQ">++</span><span class="p" id="mwAWU">)</span><span class="w" id="mwAWY"> </span><span class="p" id="mwAWc">{</span> <span class="w" id="mwAWg"> </span><span class="kt" id="mwAWk">int</span><span class="w" id="mwAWo"> </span><span class="n" id="mwAWs">x</span><span class="w" id="mwAWw"> </span><span class="o" id="mwAW0">=</span><span class="w" id="mwAW4"> </span><span class="n" id="mwAW8">i</span><span class="p" id="mwAXA">;</span> <span class="w" id="mwAXE"> </span><span class="n" id="mwAXI">std</span><span class="o" id="mwAXM">::</span><span class="n" id="mwAXQ">cout</span><span class="w" id="mwAXU"> </span><span class="o" id="mwAXY"><<</span><span class="w" id="mwAXc"> </span><span class="s" id="mwAXg">"x: "</span><span class="w" id="mwAXk"> </span><span class="o" id="mwAXo"><<</span><span class="w" id="mwAXs"> </span><span class="n" id="mwAXw">x</span><span class="w" id="mwAX0"> </span><span class="o" id="mwAX4"><<</span><span class="w" id="mwAX8"> </span><span class="sc" id="mwAYA">'\n'</span><span class="p" id="mwAYE">;</span><span class="w" id="mwAYI"> </span><span class="c1" id="mwAYM">// prints values of i from 0 to 9</span> <span class="w" id="mwAYQ"> </span><span class="n" id="mwAYU">sum</span><span class="w" id="mwAYY"> </span><span class="o" id="mwAYc">+=</span><span class="w" id="mwAYg"> </span><span class="n" id="mwAYk">x</span><span class="p" id="mwAYo">;</span> <span class="w" id="mwAYs"> </span><span class="p" id="mwAYw">}</span> <span class="w" id="mwAY0"> </span><span class="n" id="mwAY4">std</span><span class="o" id="mwAY8">::</span><span class="n" id="mwAZA">cout</span><span class="w" id="mwAZE"> </span><span class="o" id="mwAZI"><<</span><span class="w" id="mwAZM"> </span><span class="s" id="mwAZQ">"sum: "</span><span class="w" id="mwAZU"> </span><span class="o" id="mwAZY"><<</span><span class="w" id="mwAZc"> </span><span class="n" id="mwAZg">sum</span><span class="w" id="mwAZk"> </span><span class="o" id="mwAZo"><<</span><span class="w" id="mwAZs"> </span><span class="sc" id="mwAZw">'\n'</span><span class="p" id="mwAZ0">;</span><span class="w" id="mwAZ4"> </span><span class="c1" id="mwAZ8">// prints 45</span> <span class="w" id="mwAaA"> </span><span class="n" id="mwAaE">std</span><span class="o" id="mwAaI">::</span><span class="n" id="mwAaM">cout</span><span class="w" id="mwAaQ"> </span><span class="o" id="mwAaU"><<</span><span class="w" id="mwAaY"> </span><span class="s" id="mwAac">"x: "</span><span class="w" id="mwAag"> </span><span class="o" id="mwAak"><<</span><span class="w" id="mwAao"> </span><span class="n" id="mwAas">x</span><span class="w" id="mwAaw"> </span><span class="o" id="mwAa0"><<</span><span class="w" id="mwAa4"> </span><span class="sc" id="mwAa8">'\n'</span><span class="p" id="mwAbA">;</span><span class="w" id="mwAbE"> </span><span class="c1" id="mwAbI">// prints 42</span> <span class="w" id="mwAbM"> </span><span class="k" id="mwAbQ">return</span><span class="w" id="mwAbU"> </span><span class="mi" id="mwAbY">0</span><span class="p" id="mwAbc">;</span> <span class="p" id="mwAbg">}</span>

Java

<span id="mwAbw"></span><span class="kd" id="mwAb0">public</span><span class="w" id="mwAb4"> </span><span class="kd" id="mwAb8">class</span> <span class="nc" id="mwAcA">Shadow</span><span class="w" id="mwAcE"> </span><span class="p" id="mwAcI">{</span> <span class="w" id="mwAcM"> </span><span class="kd" id="mwAcQ">private</span><span class="w" id="mwAcU"> </span><span class="kt" id="mwAcY">int</span><span class="w" id="mwAcc"> </span><span class="n" id="mwAcg">myIntVar</span><span class="w" id="mwAck"> </span><span class="o" id="mwAco">=</span><span class="w" id="mwAcs"> </span><span class="mi" id="mwAcw">0</span><span class="p" id="mwAc0">;</span> <span class="w" id="mwAc4"> </span><span class="kd" id="mwAc8">public</span><span class="w" id="mwAdA"> </span><span class="kt" id="mwAdE">void</span><span class="w" id="mwAdI"> </span><span class="nf" id="mwAdM">shadowTheVar</span><span class="p" id="mwAdQ">()</span><span class="w" id="mwAdU"> </span><span class="p" id="mwAdY">{</span> <span class="w" id="mwAdc"> </span><span class="c1" id="mwAdg">// Since it has the same name as above object instance field, it shadows above </span> <span class="w" id="mwAdk"> </span><span class="c1" id="mwAdo">// field inside this method.</span> <span class="w" id="mwAds"> </span><span class="kt" id="mwAdw">int</span><span class="w" id="mwAd0"> </span><span class="n" id="mwAd4">myIntVar</span><span class="w" id="mwAd8"> </span><span class="o" id="mwAeA">=</span><span class="w" id="mwAeE"> </span><span class="mi" id="mwAeI">5</span><span class="p" id="mwAeM">;</span> <span class="w" id="mwAeQ"> </span><span class="c1" id="mwAeU">// If we simply refer to 'myIntVar' the one of this method is found </span> <span class="w" id="mwAeY"> </span><span class="c1" id="mwAec">// (shadowing a second one with the same name)</span> <span class="w" id="mwAeg"> </span><span class="n" id="mwAek">System</span><span class="p" id="mwAeo">.</span><span class="na" id="mwAes">out</span><span class="p" id="mwAew">.</span><span class="na" id="mwAe0">println</span><span class="p" id="mwAe4">(</span><span class="n" id="mwAe8">myIntVar</span><span class="p" id="mwAfA">);</span><span class="w" id="mwAfE"> </span><span class="c1" id="mwAfI">// prints 5</span> <span class="w" id="mwAfM"> </span><span class="c1" id="mwAfQ">// If we want to refer to the shadowed myIntVar from this class we need to </span> <span class="w" id="mwAfU"> </span><span class="c1" id="mwAfY">// refer to it like this:</span> <span class="w" id="mwAfc"> </span><span class="n" id="mwAfg">System</span><span class="p" id="mwAfk">.</span><span class="na" id="mwAfo">out</span><span class="p" id="mwAfs">.</span><span class="na" id="mwAfw">println</span><span class="p" id="mwAf0">(</span><span class="k" id="mwAf4">this</span><span class="p" id="mwAf8">.</span><span class="na" id="mwAgA">myIntVar</span><span class="p" id="mwAgE">);</span><span class="w" id="mwAgI"> </span><span class="c1" id="mwAgM">// prints 0</span> <span class="w" id="mwAgQ"> </span><span class="p" id="mwAgU">}</span> <span class="w" id="mwAgY"> </span><span class="kd" id="mwAgc">public</span><span class="w" id="mwAgg"> </span><span class="kd" id="mwAgk">static</span><span class="w" id="mwAgo"> </span><span class="kt" id="mwAgs">void</span><span class="w" id="mwAgw"> </span><span class="nf" id="mwAg0">main</span><span class="p" id="mwAg4">(</span><span class="n" id="mwAg8">String</span><span class="o" id="mwAhA">[]</span><span class="w" id="mwAhE"> </span><span class="n" id="mwAhI">args</span><span class="p" id="mwAhM">){</span> <span class="w" id="mwAhQ"> </span><span class="k" id="mwAhU">new</span><span class="w" id="mwAhY"> </span><span class="n" id="mwAhc">Shadow</span><span class="p" id="mwAhg">().</span><span class="na" id="mwAhk">shadowTheVar</span><span class="p" id="mwAho">();</span> <span class="w" id="mwAhs"> </span><span class="p" id="mwAhw">}</span> <span class="p" id="mwAh0">}</span>

JavaScript

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

<span id="mwAiU"></span><span class="kd" id="mwAiY">function</span><span class="w" id="mwAic"> </span><span class="nx" id="mwAig">myFunc</span><span class="p" id="mwAik">()</span><span class="w" id="mwAio"> </span><span class="p" id="mwAis">{</span> <span class="w" id="mwAiw"> </span><span class="kd" id="mwAi0">let</span><span class="w" id="mwAi4"> </span><span class="nx" id="mwAi8">my_var</span><span class="w" id="mwAjA"> </span><span class="o" id="mwAjE">=</span><span class="w" id="mwAjI"> </span><span class="s1" id="mwAjM">'test'</span><span class="p" id="mwAjQ">;</span> <span class="w" id="mwAjU"> </span><span class="k" id="mwAjY">if</span><span class="w" id="mwAjc"> </span><span class="p" id="mwAjg">(</span><span class="kc" id="mwAjk">true</span><span class="p" id="mwAjo">)</span><span class="w" id="mwAjs"> </span><span class="p" id="mwAjw">{</span> <span class="w" id="mwAj0"> </span><span class="kd" id="mwAj4">let</span><span class="w" id="mwAj8"> </span><span class="nx" id="mwAkA">my_var</span><span class="w" id="mwAkE"> </span><span class="o" id="mwAkI">=</span><span class="w" id="mwAkM"> </span><span class="s1" id="mwAkQ">'new test'</span><span class="p" id="mwAkU">;</span> <span class="w" id="mwAkY"> </span><span class="nx" id="mwAkc">console</span><span class="p" id="mwAkg">.</span><span class="nx" id="mwAkk">log</span><span class="p" id="mwAko">(</span><span class="nx" id="mwAks">my_var</span><span class="p" id="mwAkw">);</span><span class="w" id="mwAk0"> </span><span class="c1" id="mwAk4">// new test</span> <span class="w" id="mwAk8"> </span><span class="p" id="mwAlA">}</span> <span class="w" id="mwAlE"> </span><span class="nx" id="mwAlI">console</span><span class="p" id="mwAlM">.</span><span class="nx" id="mwAlQ">log</span><span class="p" id="mwAlU">(</span><span class="nx" id="mwAlY">my_var</span><span class="p" id="mwAlc">);</span><span class="w" id="mwAlg"> </span><span class="c1" id="mwAlk">// test</span> <span class="p" id="mwAlo">}</span> <span class="nx" id="mwAls">myFunc</span><span class="p" id="mwAlw">();</span>

More in Computing and communication