I’m trying to get my head round this part $script:count += $increment.
The $script is a new variable but it seems to be attaching the $count variable…$script:count…
then passed to a new variable from the function…$increment
This is variable scoping. It changes the variable scope to script rather than it’s normal local scope inside of a function. Another one you will see occasionally is $global:variable. This changes the scope of the variable to global. Check out about_Scopes for more info.
This particular example is a bit tricker than that. It’s demonstrating the ScriptBlock.GetNewClosure() behavior. Because you’ve called GetNewClosure(), the script: scope modifier for each of the script block returned by New-Counter is not actually in your script’s script: scope. Here’s an example of what I mean:
Notice that I set $script:count to 14 before calling New-Counter. However, the output from this command is:
1
2
3
6
Each counter maintains its own increment and count, isolated from the other counters (and from the actual script itself.) This is a pretty advanced technique for most PowerShell scripters, and can easily become pretty confusing to keep track of what’s going on.
Thanks Curtis, but in trying to get my head around the scopes, I’m not looking for s solution, just an understanding. I was trying in my simple terms to learn how scopes work.
Here’s a good test to give you an idea of the differences between Global, Script and Local (read: only within a function)
Create a new ps1 script with the following content:
$Script:var = "I AM SCRIPT"
function test {
$var = "I AM FUNCTION"
"Testing `$Global:var = $Global:var"
"Testing `$script:var = $Script:var"
"Testing `$var = $var"
}
test
$var
And save as something like C:\test.ps1. Then open a powershell console and run the following:
$var = "I AM GLOBAL"
&C:\test.ps1
Your output should be:
Testing $Global:var = I AM GLOBAL
Testing $script:var = I AM SCRIPT
Testing $var = I AM FUNCTION
I AM SCRIPT
This is a very simple example, but I think you should get the gist of it.
A practical example: If for instance you wish to set $ErrorActionPreference within a script or function without modifying the $ErrorActionPreference of your console session. You can modify the value within any script or function, run that script or function in a console, and the value will ONLY be changed within the context of the script or function that has been executed.
If you wish to change the $ErrorActionPreference of your console session by running a function or script, you can reference $Global:ErrorActionPreference in your script or function, then when that script or function is executed in your console session it will update the Global ErrorActionPreference for that console session.
Extracted from about_scopes:
- An item you include in a scope is visible in the scope in which it
was created and in any child scope, unless you explicitly make it
private. You can place variables, aliases, functions, or Windows
PowerShell drives in one or more scopes.
An item that you created within a scope can be changed only in the
scope in which it was created, unless you explicitly specify a
different scope.