PowerShell ScriptBlock 等效于一流的匿名函数。我看到的大多数混淆不是与 ScriptBlocks 相关,而是与function关键字相关。
- PowerShell 确实支持函数闭包,但function关键字不支持。
例子
功能:
PS> function Hello {
>> param ([string] $thing)
>>
>> return ("Hello " + $thing)
>> }
PS> Hello "World"
"Hello World"
脚本块:
PS> $HelloSB = {
>> param ([string] $thing)
>>
>> return ("Hello " + $thing)
>> }
PS> & $HelloSB "World"
"Hello World"
PS> $HelloRef = $HelloSB
PS> & $HelloRef "Universe"
"Hello Universe"
关闭:
PS> $Greeter = {
>> param ([string] $Greeting)
>>
>> return ( {
>> param ([string] $thing)
>>
>> return ($Greeting + " " + $thing)
>> }.GetNewClosure() )
>> }
PS> $Ahoy = (& $Greeter "Ahoy")
PS> & $Ahoy "World"
"Ahoy World"
PS> $Hola = (& $Greeter "Hola")
PS> & $Hola "Mundo"
"Hola Mundo"
尽管您可以使用“Set-Item”cmdlet绕过function关键字的限制:
PS> function Greeter = { ... } # ✕ Error
PS> function Greeter { ... }.GetNewClosure() # ✕ Error
PS> Set-Item -Path "Function:Greeter" -Value $Greeter # (defined above) ✓ OK
PS> $Hola = Greeter "Hola"
PS> & $Hola "Mundo"
"Hola Mundo"
“Set-Item” cmdlet的Value参数可以是任何 ScriptBlock,甚至是另一个函数返回的。(例如,“Greeter”函数返回一个闭包,如上所示。)
PS> Set-Item -Path "Function:Aloha" -Value (Greeter "Aloha")
PS> Aloha "World"
"Aloha World"
另外两个重要的点:
PowerShell 使用动态作用域,而不是词法作用域。
词法闭包在其源代码环境中关闭,而动态闭包基于调用 GetNewClosure() 时存在的活动/动态环境而关闭。(这更适合脚本语言。)
PowerShell 可能有“函数”和“返回”语句,但实际上它的输入/输出是基于流和管道的。将返回使用“Write-Output”或“write”cmdlet 从 ScriptBlock 中写入的任何内容。