Question

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?

Was it helpful?

Solution

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

Say-Hi ${function:Get-MyName}

OTHER TIPS

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.

This might be a better example to illustrate the question, and details of execution scope. @mjolinor's answer appears to work nicely for this use case:

function Get-MyName($name) { $name; throw "Meh" }

function Say-Hi([scriptblock]$to) {
  try {
      Write-Host ("Hi "+(& $to $args)) # pass all other args to scriptblock
  } catch {
      Write-Host "Well hello, $_ exception!"
  }
}

The command and its output:

PS C:\> Say-Hi ${function:Get-MyName} 'George'
Well hello, Meh exception

In particular, I'm using this pattern for wrapping functions that work with a flaky remote SQL Server database connection, which sleep, then retry several times before finally succeeding or throwing a higher exception.

Strictly based on your code, the correct answer is this:

Say-Hi {(Get-MyName)}

This will produce "Hi George"

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top