views:

293

answers:

1

I will explain my question on an example. Let's have following code in C#:

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

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

void Main()
{
 A(() =>
 {
  Console.WriteLine(3);
 });
}

The output of this code is:

1
2
3

Now, I want to write this code in PowerShell:

function A($block) {
    B {
        2
        . $block
    }
}

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

A {
    3
}

However, this code causes a call depth overflow:

The script failed due to call depth overflow. The call depth reached 1001 and the maximum is 1000.

I found that if I change the name of the parameter of the function B, it will work.

Is it a feature or a bug (or both)? How can I make that work in PowerShell without having parameters unique across functions?

+1  A: 

Yeah, you're going recursive because the $block reference in the scriptblock passed into function B gets evaluated in the context of function B and as a result, evaluates to the value of B's $block parameter.

If you don't want to change the parameter name (don't blame you) you can force PowerShell to create a new closure in A to capture the value of $block within function A e.g.:

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

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

A {Write-Host 3}
Keith Hill
Thx. Is there any standard shortcut for creating closures from blocks (e.g. ${})?
TN
No. The GetNewClosure() method is the only way I'm aware of.
Keith Hill