28

Given that this works:

$ar = @()
$ar -is [Array]
  True

Why doesn't this work?

function test {
    $arr = @()
    return $arr
}

$ar = test
$ar -is [Array]
  False

That is, why isn't an empty array returned from the test function?

34

Your function doesn't work because PowerShell returns all non-captured stream output, not just the argument of the return statement. An empty array is mangled into $null in the process. However, you can preserve an array on return by prepending it with the array construction operator (,):

function test {
  $arr = @()
  return ,$arr
}
| improve this answer | |
  • 1
    soooooo frustrating. If you return @(/*some filtered expression that has zero elements*/) you also encounter the same behaviour. return ,@(/*expr*/) is a fix... but it's hacky as hell. So easy to overlook. – Steven Evers Mar 28 '14 at 23:18
  • This stupid workings cost me about a day in freaking time. I could not figure out how my script was double the values in the array. Thank you for posting that. Why would they even think that was a good idea for functions! So frustrating! The worst part is, I had an $arr.add(1) which was outputting the count of the array after. Doing $x = $arr.add(1) fixed the issue. Hacky. – Jim W. Jul 3 '14 at 15:14
  • @BradFJacobs: You could also use ... | Out-Null or ... >$null to suppress undesired output. I wouldn't consider returning all non-captured output a bad idea per se, though, it's just unexpected for most people with a background in other programming languages. When used properly it can actually simplify returning data from a function, because you don't have to collect all desired output in a variable before returning it. – Ansgar Wiechers Jul 5 '14 at 20:50
  • 2
    @BradFJacobs, while this is normally true, I think return was just a mistake. According to Bruce Payette (one of PowerShell's designers) the return statement was added for control flow, and return $x is just shorthand for Write-Output $x; return. Clearly the keyword should be ExitSub and it shouldn't accept an argument. – Sam Porch May 20 '15 at 1:21
  • 1
    Actually it behaves differently if returned from a function vs locally, locally it does create an array of size 1 containing an empty array, but when returned from a function PS seems to be unwrapping the outer layer and giving an empty array – illegal-immigrant Jun 22 '17 at 18:57
0

write-output $arr is as afaik the same as just writing $arr. So the function will still return $null.

But write-output has the option -NoEnumerate. That means the empty Array will not be enumerated (and therefore ignored - because it's empty). The result is an empty array.

admittedly the above answer is much shorter, ...

 function test {
     $arr = @()
     write-output $arr -NoEnumerate 
 }
 (test) -is [array]  ## $True
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.