Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell: passing blocks as parameters to functions

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?

like image 354
TN. Avatar asked Dec 01 '09 17:12

TN.


People also ask

How do you pass parameter values in PowerShell?

You can pass the parameters in the PowerShell function and to catch those parameters, you need to use the arguments. Generally, when you use variables outside the function, you really don't need to pass the argument because the variable is itself a Public and can be accessible inside the function.

What does $() mean in PowerShell?

Subexpression operator $( ) For a single result, returns a scalar. For multiple results, returns an array. Use this when you want to use an expression within another expression. For example, to embed the results of command in a string expression. PowerShell Copy.

What does $_ in PowerShell mean?

The “$_” is said to be the pipeline variable in PowerShell. The “$_” variable is an alias to PowerShell's automatic variable named “$PSItem“. It has multiple use cases such as filtering an item or referring to any specific object.

What is param () in PowerShell?

The PowerShell parameter is a fundamental component of any script. A parameter is a way that developers enable script users to provide input at runtime. If a PowerShell script's behavior needs to change in some way, a parameter provides an opportunity to do so without changing the underlying code.


1 Answers

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}
like image 69
Keith Hill Avatar answered Oct 17 '22 03:10

Keith Hill