Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a named function as a parameter (scriptblock)

Let's take the classic first-order functions example:

function Get-MyName { "George" }

function Say-Hi([scriptblock]$to) {
  Write-Host ("Hi "+(& $to))
}

This works just fine:

Say-Hi { "Fred Flintstone" }

this does not:

Say-Hi Get-MyName

because Get-MyName is evaluated, not passed as a value itself. How do I pass Get-MyName as a value?

like image 803
George Mauer Avatar asked Dec 07 '22 08:12

George Mauer


2 Answers

You have to pass Get-Myname as a scriptblock, because that's how you've defined the variable type.

Say-Hi ${function:Get-MyName}
like image 127
mjolinor Avatar answered Dec 15 '22 00:12

mjolinor


If you are ready to sacrifice the [scriptblock] parameter type declaration then there is one more way, arguably the simplest to use and effective. Just remove [scriptblock] from the parameter (or replace it with [object]):

function Get-MyName { "George" }

function Say-Hi($to) {
  Write-Host ("Hi "+(& $to))
}

Say-Hi Get-MyName
Say-Hi { "George" }

So now $to can be a script block or a command name (not just a function but also alias, cmdlet, and script).

The only disadvantage is that the declaration of Say-Hi is not so self describing. And, of course, if you do not own the code and cannot change it then this is not applicable at all.

I wish PowerShell has a special type for this, see this suggestion. In that case function Say-Hi([command]$to) would be ideal.

like image 29
Roman Kuzmin Avatar answered Dec 15 '22 00:12

Roman Kuzmin