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

回眸只為那壹抹淺笑 提交于 2019-12-22 10:51:06

问题


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?


回答1:


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

Say-Hi ${function:Get-MyName}



回答2:


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.




回答3:


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.




回答4:


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

Say-Hi {(Get-MyName)}

This will produce "Hi George"



来源:https://stackoverflow.com/questions/15977178/how-to-pass-a-named-function-as-a-parameter-scriptblock

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!