PowerShell: 将代码块作为参数传递给函数

10

我将通过一个例子来解释我的问题。让我们看一下以下C#代码:

void A(Action block)
{
 B(() =>
 {
  Console.WriteLine(2);
  block();
 });
}

void B(Action block)
{
 Console.WriteLine(1);
 block();
}

void Main()
{
 A(() =>
 {
  Console.WriteLine(3);
 });
}
这段代码的输出结果是什么?
1
2
3
现在,我想在PowerShell中编写此代码:
function A($block) {
    B {
        2
        . $block
    }
}

function B($block) {
    1
    . $block
}

A {
    3
}

然而,这段代码会导致调用深度溢出:

由于调用深度达到了1001,超过了函数的最大调用深度1000,因此脚本失败了。

我发现,如果我更改函数B的参数名称,它将起作用。

这是一个特性还是一个bug(或两者兼有)?如何在PowerShell中做到不需要在不同函数之间使用唯一的参数名呢?

1个回答

16

由于脚本块传递给函数B的脚本块中的$block引用在函数B的上下文中计算,并因此评估为B的$block参数的值,所以你会发生递归。

如果你不想更改参数名称(不怪你),你可以强制PowerShell在A函数内创建一个新的闭包来捕获$block的值,例如:

function A($block) 
{    
     B {Write-Host 2; &$block}.GetNewClosure()
}

function B($block) 
{
    Write-Host 1
    &$block
}

A {Write-Host 3}

谢谢。有没有创建闭包的标准快捷方式,例如从块(例如${})中创建? - TN.
不是。我所知道的唯一方法是使用GetNewClosure()方法。 - Keith Hill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接