In powershell you can make functions with function name {commands} and make those functions take arguments with this:
function myFunction {
    param($var1, $var2)
}
but you can also accomplish this with
function myFunction($var1, $var2) {}
and they would be the same.
For example, if I made a function func1 be:
function func1 {
    param($var1, $var2)
    echo "$var1 $var2"
}
I would call it by using func1 1 2 where $var1 would be equal to 1 and $var2 would be equal to 2.
Input:
PS C:\Users\Neko> func1 1 2
Output:
1 2
However, if I do the same thing but instead I did the other method of passing arguments to functions:
function func2($var1, $var2) {
    echo "$var1 $var2"
}
I would also call it the same exact way, calling it by using func2 1 2 where $var1 would be equal to 1 and $var2 would be equal to 2 like the previous function.
Input:
PS C:\Users\Neko> func2 1 2
Output:
1 2
So everything seems the same and constant between the two renditions of the function, so my question is, is there a difference between the two methods of passing arguments to functions or are they both actually the same? Even if it is the most minor of details, or just a parsing difference, I would like to know any differences between the two in functions specifically since param has other uses as well.
UPDATE: The arguments you can do in param like [parameter(Mandatory=$true, ValueFromPipeline=$true)] and [String[]] are not unique to param. You can also accomplish this in the other 'non-param' example by doing:
function func2(
    [parameter(Mandatory=$true, ValueFromPipeline=$true, etc)] 
    [String[]]
    $var1, $var2
) {
    echo "$var1 $var2" 
}
                To complement 7cc's helpful answer:
While the two syntax forms are mostly interchangeable when you define a function's parameters, only the param(...) block syntax works in the following circumstances:
If you want to use a [CmdletBinding()] attribute and its properties to (explicitly) make your function or script an advanced function or script.[1]
If you're writing a script file(*.ps1) or script block ({ ... }): the only way to declare parameters for them is is by placing a param(...) block at the beginning.
Therefore, you may opt to always use the param(...) block syntax, for consistency across function and script parameter definitions.
If a [CmdletBinding(...)])  attribute is used, it must directly precede the param(...) block.
As for:
I would call it by using
func1(1)(2)
No, you would call it as follows:
func1 1 2
That is, PowerShell functions are called like shell commands: without parentheses, separated by whitespace; while your invocation happens to work too, the use of (...) around the arguments can change their interpretation:
without the enclosing (...) the arguments are parsed in argument mode, where, notably, strings needn't be quoted
with the enclosing (...), are parsed in expression mode, where strings do need to be quoted.
See this answer for more information.
[1] While you can place a [CmdletBinding(...)] attribute inside the parentheses with the function Foo (...) { ... } syntax without provoking an error, doing so is effectively ignored. Separately, in the absence of an (effective) explicit [CmdletBinding(...)] attribute, with either syntax, if you happen to decorate at least one parameter with a [Parameter()] attribute, you get the default behaviors of an advanced function (e.g., support for automatic common parameters such as -Verbose), because using [Parameter()] implicitly makes a function an advanced one (as if a [CmdletBinding()] attribute - without explicit property values - were in effect). However, if you need an explicit [CmdletBinding(...)] attribute, so as to opt into non-default advanced-function behaviors, via property values such as PositionalBinding=$false or SupportsShouldProcess=$true, use of a param(...) block is your only option.
One thing is that the CmdletBinding attribute requires Param
function Echo-Confirm
{
    # Here
    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    Param ($val=1)
    if ($PSCmdlet.ShouldProcess($val) -eq $true) {
        Write-Output "Confirmed $val"
    }
}
Edit after this comment
The syntax is fine, but CmdletBinding has no effect
Function foo (
    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    [Parameter()]$val=1
) {
    # never confirm
    if ($PSCmdlet.ShouldProcess($val) -eq $true) {
        Write-Output "always here"
    }
    else {
       Write-Output "never here"
    }
}
foo -Confirm
# throws an error
foo: A parameter cannot be found that matches parameter name 'confirm'.
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With