Search code examples
arraysstringfunctionpowershellreturn

How to force a custom Powershell function to behave like [System.String] method Split while referencing an individual element in the array


example:

"a b c d e f g".Split(" ")[0]

a

when I try to do this same with a function

function MyReturnArray
{
    $array = @('a','b','c','d','e','f','g')
    return $array
}

MyReturnArray[0] : The term 'MyReturnArray[0]' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the 
name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ MyReturnArray[0]
+ ~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (MyReturnArray[0]:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

however, this works:

(MyReturnArray)[0]

a

So the question is, why does the .Split() from a [System.String] Method type not require a grouping () or parenthesise to access the individual element? But with my own function, I must do so. How do I force it to act the same way like with .Split()?


Solution

  • "How do I force it to act the same way like with .Split()?"

    The (disappointing) answer is: you don't

    Why? Because that's simply not how the language works :)


    More complete explanation:

    The element access operator [] works on what we might call syntactically bounded expressions (referred to as primary expressions in the PowerShell 3.0 Language Specification, the only official document I know of attempting to document the full grammar of PowerShell).

    "a b c d e f".Split() is what we call a member access expression - itself consisting of:

    • Another bounded expression "a b c d e"
    • The instance member access operator ., and
    • A member argument with an argument list Split and ().

    Member access expressions are bounded expression - the closing ) is the last possible token the member access operator (the . in the middle) could possibly accept, so we know that the expression ends there.

    What makes the string literal "a b c d e f" a bounded expression? Same principle as above, the parser can independently determine the boundaries of the string by looking at the " in front and at the end.

    MyReturnArray, however, is not a bounded expression. It's a command expression_, and there are separate parsing rules for command expressions, in order to allow for parameter binding to work the way it does in PowerShell, but also to allow command names to be anything - if you wanted to create a function literally named MyReturnArray[0] then that's absolutely valid.

    As you've found, you can enclose it in () parentheses, creating a syntactical boundary for the call to MyReturnArray, the resulting expression of which [] can operate on.