A question of scope

I had a question left on my blog regarding scope.  The following is a simplified version of the problem

            
function level1 {            
 $iterations++            
 Write-Host '$iterations in level 1 = ' $iterations             
 level2            
}            
            
function level2 {            
 $iterations++            
 Write-Host '$iterations in level 2 =' $iterations            
}            
            
$iterations = 0            
            
Write-Host '$iterations at start =' $iterations            
level1            
            
Write-Host '$iterations at end =' $iterations


Start with a variable $iterations. Call a function and increment the variable. Call a nested function and increment the variable and then display the result



The output is



$iterations at start = 0

$iterations in level 1 =  1


$iterations in level 2 = 2


$iterations at end = 0



Start with zero, increment in level1 and level 2 – all OK. Show the final result & its zero.



The reason is scope.  Each of the functions has its own scope. Those scopes are destroyed – along with any variables & their contents when the functions finish.



If you want to keep the results then change to this



function level1 {            
 $global:iterations++            
 Write-Host '$global:iterations in level 1 = ' $global:iterations             
 level2            
}            
            
function level2 {            
 $global:iterations++            
 Write-Host '$global:iterations in level 2 =' $global:iterations            
}            
            
$global:iterations = 0            
            
Write-Host '$global:iterations at start =' $global:iterations            
level1            
            
Write-Host '$global:iterations at end =' $global:iterations


The output becomes



$global:iterations at start = 0

$global:iterations in level 1 =  1


$global:iterations in level 2 = 2


$global:iterations at end = 2



It is recommended not to use scopes in scripts if you can possibly avoid it – it can become very confusing in cases that are more complicated than this. The issue is better handled by passing parameters



function level1 {            
 param ($l1iterations)            
 $l1iterations++            
 Write-Host '$iterations in level 1 = ' $l1iterations            
 $l1iterations = level2 $l1iterations            
 $l1iterations            
}            
            
function level2 {            
param ($l2iterations)            
  $l2iterations++            
 Write-Host '$iterations in level 2 =' $l2iterations            
 $l2iterations            
}            
            
$iterations = 0            
            
Write-Host '$iterations at start =' $iterations            
$iterations = level1 $iterations            
            
Write-Host '$iterations at end =' $iterations


Much more on scope can be found in chapter 22 of my latest book PowerShell in Depth coauthored with Don Jones and Jeff Hicks -  http://www.manning.com/jones2/

Leave a Reply