简体   繁体   中英

Difference between param and function syntax in PowerShell

In PowerShell I can pass a parameter if I create a closure with param syntax:

$hello = { param($name) "Hello $name"}
& $hello "World!"

>hello.ps1
Hello World!

When I try this with function syntax I get into trouble:

function hello($n) { { "Hello $n" }.GetNewClosure() }

$doit = hello

& $doit "World!"

>functionclosure.ps1
Hello 

I managed to fix this by giving the parameter earlier:

function hello($n) { {"Hello $n"}.GetNewClosure()  }

$doit = hello "World"

& $doit

>functionclosure2.ps1
Hello World

Is there a way to pass a parameter to a function from the & call operator line?

Is there a way to pass a parameter to a function from the & call operator line?

The call (also known as invocation or & ) operator is generally used to execute content in a string, which we do when there is a long file path or a path with spaces in the name, or when we are dynamically building a string to execute.

Now, in this case, Using GetNewClosure() alters a function to instead return a scriptblock as the output type. That Scriptblock must be invoked using the Call operator, so this is a valid usage of the Call operator .

Back to your question then, yes, you can control the order of execution using paranthesis and pass a parameter to a function which returns a closure from the call line like this:

& (hello stephen)

However, this is pretty confusing in action as closures maintain their own separate scope and in more than ten years of enterprise automation projects, I never saw them used. It might be more confusion than it's worth to go down this route.

Prehaps a simpler approach might be:

function hello($name) { "WithinFunction: Hello $name"}
$do = 'hello "world"'
PS> $do
hello "world"
#invoke
PS> invoke-expression $do
WithinFunction: Hello world

Additional reading on closures by the man himself who implemented it in PowerShell here. https://devblogs.microsoft.com/scripting/closures-in-powershell/

Jeroen Mostert wrote this as a comment:

You've written a function that takes a parameter and then creates a closure using that parameter. It seems like you want a function that returns a closure that takes a parameter -- but that's the same as your first example, and

function hello { { param($n) "Hello $n"} } 

would do that. You'd invoke that as

& (hello) "world"

On the other hand, if you want to have a function as a closure you can invoke,

${function:hello} 

would do that, ie

function hello($n) { "Hello $n" }; 
$doit = ${function:hello}; 
& $doit "World"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM