gpt4 book ai didi

function - PowerShell 闭包中的捕获函数

转载 作者:行者123 更新时间:2023-12-02 19:58:05 25 4
gpt4 key购买 nike

PowerShell 闭包似乎没有捕获函数的定义:

PS C:\> function x() { Write-Host 'original x' }
PS C:\> function x-caller-generator() { return { Write-host 'Calling x!'; x }.GetNewClosure() }
PS C:\> $y = x-caller-generator
PS C:\> & $y
Calling x!
original x
PS C:\> function x() { Write-Host 'new x' }
PS C:\> & $y
Calling x!
new x

有什么方法可以捕获函数的定义吗?

我实际遇到的是我创建了一个闭包,但是当我的闭包执行时,该函数不知何故超出了范围。 (构建脚本的 psake 模块正在做的事情有点奇怪。)像这样的事情:

PS C:\> function closure-maker () {
>> function x() { Write-Host 'x!' }
>>
>> return { Write-host 'Calling x'; x }.GetNewClosure()
>> }
>>
PS C:\> $y = closure-maker
PS C:\> & $y
Calling x
The term 'x' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:3 char:39
+ return { Write-host 'Calling x'; x <<<< }.GetNewClosure()
+ CategoryInfo : ObjectNotFound: (x:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

注意:使用 PowerShell 2.0,但对 3.0 答案感兴趣(如果有新内容)。

最佳答案

嗯,我发现了一些至少适用于简单功能的东西。我们可以使用 Get-Item 来获取描述该函数的对象,然后从中提取原始脚本。像这样:

function x-caller-generator() {
$xFunc = [ScriptBlock]::Create((Get-Item function:x).Definition)
return { Write-host 'Calling x!'; & $xFunc }.GetNewClosure()
}

如果函数从未被重新定义(就像在我的示例中,我的函数超出了范围),我们可以避免取消定义,而直接使用函数对象:

function closure-maker () {
function x() { Write-Host 'x!' }

$xFunc = Get-Item function:x
return { Write-host 'Calling x'; & $xFunc }.GetNewClosure()
}

如果在执行闭包之前重新定义函数(至少在与原始函数相同的范围内),则第二种方法将不起作用。该物体显然是动态的;它跟踪当前的定义。

我严重怀疑这是否适用于引用其他可能超出范围的用户定义函数的函数,但我的用例不需要这样做。

示例输出:

创建脚本 block

PS C:\> function x() { Write-Host 'original x' }
PS C:\> function x-caller-generator() { $xFunc = [ScriptBlock]::Create((Get-Item function:x).Definition); return { Write-host 'Calling x!'; & $xFunc }.GetNewClosure() }
PS C:\> $y = x-caller-generator
PS C:\> & $y
Calling x!
original x
PS C:\> function x() { Write-Host 'new x' }
PS C:\> & $y
Calling x!
original x

使用函数对象

PS C:\> function closure-maker () {
>> function x() { Write-Host 'x!' }
>>
>> $xFunc = Get-Item function:x
>> return { Write-host 'Calling x'; & $xFunc }.GetNewClosure()
>> }
>>
PS C:\> $y = closure-maker
PS C:\> & $y
Calling x
x!

尝试在第一个示例中使用对象不起作用:

PS C:\> function x() { Write-Host 'original x' }
PS C:\> function x-caller-generator() { $xFunc = Get-Item function:x; return { Write-host 'Calling x!'; & $xFunc }.GetNewClosure() }
PS C:\> $y = x-caller-generator
PS C:\> & $y
Calling x!
original x
PS C:\> function x() { Write-Host 'new x' }
PS C:\> & $y
Calling x!
new x

关于function - PowerShell 闭包中的捕获函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16745880/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com