# encoding: ascii # api: powershell # title: Variable capture # description: Powershell really needs lexical variables and automatic lexical closures. ScriptBlock.GetNewClosure is a heavyweight hack (it captures the entire scope chain every time you call it) around lexical variable capture so here is a lighter weight hack. # version: 0.1 # type: function # author: Public Domain # license: CC0 # function: New-Closure # x-poshcode-id: 4694 # x-archived: 2013-12-16T12:32:22 # x-published: 2013-12-13T00:59:00 # # function New-Closure { #.SYNOPSIS # A more fine grained approach to capturing variables than GetNewClosure #.EXAMPLE # $acc = New-Closure @{t = 0} {param($v = 1) $t += $v; $t} ; & $acc 10 ; & $acc # 10 # 11 [OutputType([scriptblock])] [CmdletBinding()] param( [Parameter(Mandatory)] [System.Collections.IDictionary]$Variable , [Parameter(Mandatory)] [scriptblock]$Script ) try { $private:m = New-Object System.Management.Automation.PSModuleInfo $true $Script = $m.NewBoundScriptBlock($Script) foreach ($v in $Variable.GetEnumerator()) { & $m { Set-Variable -Name $args[0] -Value $args[1] -Scope script -Option AllScope } $v.Key $v.Value } $Script } catch { throw } }