-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Description
Summary of the new feature / enhancement
This request is an extent on the enhancement request #13772 and might be a better alternative as it is universal (not limited to a single variable name), consistent and probably less expensive.
PowerShell has a nice feature which regards to scope rules:
- When code running in a runspace references an item, PowerShell searches the scope hierarchy, starting with the current scope and proceeding through each parent scope.
- If the item isn't found, a new item is created in the current scope.
- If it finds a match, the value of the item is retrieved from the scope where is was found.
- If you change the value, the item is copied to the current scope so that the change only affects the current scope.
As with several other PowerShell features, it has its advantage, but it also has its disadvantages (and pitfalls) as this actually means that you do not have to define your variable but should make absolutely sure you variable is initiated 🤔(otherwise it might take it from a parent scope).
In other words, a common use case is keeping track of an (zero or one based) index in a foreach loop:
function MyFunction {
$Table = @{}
'Zero', 'One', 'Two', 'Three' | ForEach-Object { $Table[$Index++] = $_ }
$Table | Format-Table
}
MyFunctionThis works fine until you use the variable $i in one of the parent functions (where the action "If the item isn't found, a new item is created in the current scope" will take place):
for ($Index = 0; $Index -lt 5; $Index++) { <# do something #> }
MyFunctionTo resolve this I need to make sure that the concerned variable ($Index) is (re)set:
function MyFunction {
$Table = @{}
$Index = 0
'Zero', 'One', 'Two', 'Three' | ForEach-Object { $Table[$Index++] = $_ }
$Table | Format-Table
}
But that the $Index sequence is ment to be zero based ($Index = 0) is quiet obvious and would be clearer when described in the ScriptBlock ({ $Table[$Index++] = $_ }) itself.
Proposed technical implementation details (optional)
Wishful thinking:
A scope modifier (I was thinking of $this:) that acts like the default rules with one exception that doesn't search the scope hierarchy, starting with the current scope and proceeding through each parent scope but initializes the variable with its default value (basically: New-Variable -Name <Name>) whenever the current item ($_) is initialized:
A zero based iteration:
'Zero', 'One', 'Two', 'Three' | ForEach-Object { $Table[$this:Index++] = $_ }A one based iteration:
'One', 'Two', 'Three' | ForEach-Object { $Table[++$this:Index] = $_ }#13769 Skip certain indices
'A'..'E' | Where-Object { $this:Index++ -notin 1, 3 }Select odd rows
'A'..'E' | Where-Object { $this.Index++ % 2 }Combine single arrays into columns
$A1= 1..3
$A2= 4..6
$A3= 7..9
$A1 | Foreach-Object {
[pscustomobject]@{ A1 = $_; A2= $A2[$this:i++]; A3 = $A3[$this:j++] }
}