A question of scope
Posted by: Richard Siddaway
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/




