tags:

views:

90

answers:

1

Given this function:

> function Get-ArrayOfArrays() {
    (1,2),(3,4) | % { $_ }
}

I'd expect the return type to be an array of arrays. However, it appears that the inner arrays are being expanded into the pipe:

> Get-ArrayOfArrays | % { $_.GetType().Name }
Int32
Int32
Int32
Int32

In fact, running the pipe inline will produce these results:

> (1,2),(3,4) | % { $_ }
Object[]
Object[]

I've found that if I use the return keyword inside the foreach, I can achieve the desired result:

> function Get-ArrayOfArraysWithReturn() {
    (1,2),(3,4) | % { return $_ }
}

> Get-ArrayOfArraysWithReturn | % { $_.GetType().Name }
Object[]
Object[]

This behavior seems to be "If returning from a function with uncaptured objects, and those objects happen to be arrays, then expand them". Is this one of those "do-what-is-useful-most-of-the-time" design decisions? Or am I missing something else?

+3  A: 
(1,2),(3,4) | % {$_}

results in your function outputting (1,2) and (3,4) - the same as this function would:

function foo { 
    1,2
    3,4 
}

The kicker is that each of these arrays have their content's unrolled (flattened) again as part of the process of a function outputting objects e.g.:

PS> foo | %{$_.GetType().Name}
Int32
Int32
Int32
Int32

This is similar to what you see on the host when you execute this:

PS> 1,2
1
2

The array is unrolled such that each element of the array is displayed. The following should do what you want:

function Get-ArrayOfArrays() { 
    (1,2),(3,4)
}

When (1,2),(3,4) hits the function output it is unrolled once, outputting (1,2) and (3,4). Another technique you can use to work-around collection unrolling is to wrap a collection within another single element collection using the , operator to preserve the shape of the original collection e.g.:

PS> function foo { ,((1,2),(3,4)) }
PS> foo | gtn
Object[]
Keith Hill
The array flattening is sometimes a little bit tricky but very helpful.
stej
Yeah, most of the time you don't think about it (good for the Powershell team) but when dealing with arrays of arrays and maintaining that shape, you have to jump through a hoop or two.
Keith Hill
Ah, there are two function boundaries being hit, so it's unrolled twice. Makes sense - thanks for the great explanation.
James Kolpack