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/