Search code examples
functionpowershelloperator-precedence

Expressions as PowerShell function parameters


I have little experience using PowerShell so I was attempting to do some bitwise operations while inputting in binary (purely for readability). I used the following functions to convert to and from binary and they seem to work.

function bin($a){
    return [convert]::ToString($a,2)
}
function unbin($a){
    return [convert]::ToInt64($a,2)
}

Then I attempted to run the following:

bin(unbin('11001101') -bxor unbin('10110110'))

expecting the output 1111011.

To my surprise I instead get the result 11001101 (the result of bin(unbin('11001101'))).

In order to get my code to work I needed to wrap the unbin calls in further parentheses and I can't understand why:

bin((unbin('11001101')) -bxor (unbin('10110110')))

Why are these extra parentheses needed?


Solution

  • Note that function invocation in PowerShell is more akin to invoking cmdlets, not .NET methods. So you have a lot of unnecessary parentheses in there and missing a few relevant ones. The following code

    bin(unbin('11001101') -bxor unbin('10110110'))
    

    passes one argument to bin (the complete contents of the parentheses), but three to the first unbin invocation. It's equivalent to

    unbin '11001101' -bxor "unbin('10110110')"
    

    (if I'm not mistaken; details may vary (could be four), but that's the gist of it).

    When invoking a PowerShell function, arguments don't get passed in parentheses. And the operands to -bxor must be expressions themselves, so any pipelines have to be parenthesized:

    bin ((unbin '11001101') -bxor (unbin '10110110'))