openlang

What the unary comma does

While reading Powershell in Action, I got stuck on a passage in Chapter 5. I follow the result here, but could someone explain the purpose and the reason behind it?

$nested = 4, (5, 6)
$flattened = $nested | foreach { $_ }

$flattened.length

That gives $flattened.length as 3. Fair enough.

$nested = 4, (5, 6)
$flattened = $nested | foreach { ,$_ }

$flattened.length

This time $flattened.length gives 2.

Running $flattened[0]; $flattened[1] -join "," explains those 2 objects, but what precisely does the comma inside that second ForEach accomplish?

Does it mean, roughly, “Keep 4 as an object and (5,6) as its seperate object. Leave them intact.”

The conversation continues 3

Follow the reasoning
  1. Permalink

    The Powershell pipeline “unwraps” collections for convenience and, amusingly, for user “consistency”. That unary operator stops powershell from performing that unwrapping. Those examples aren't ideal, so I'll try another approach.

    Look at what these two snippets produce

    (4, 5, 6) | ForEach-Object {
        Write-Host "Pipeline element now: $_"
    }
    
    Pipeline element now: 4
    Pipeline element now: 5
    Pipeline element now: 6
    ,(4, 5, 6) | ForEach-Object {
        Write-Host "Pipeline element now: $_"
    }
    
    Pipeline element now: 4 5 6

    The latter sends the complete collection through as a single object, so it never gets unwrapped. It's an array, and the spaces you see, rather than commas, come from the space used as the default output field separator (held in $ofs). Here's a way to observe that

    "$(4, 5, 6)"
    
    4 5 6

    Embedding that array in a string makes powershell join its elements using the default OFS. Changing it is possible, although seldom necessary.

    $ofs = '/~/'
    
    "$(4, 5, 6)"
    
    4/~/5/~/6

    One fairly frequent use for that unary operator in my own work is splitting values while keeping every element together in a single object.

    ,(-split 'Tavin enjoys powershell') | ForEach-Object {
        [PSCustomObject]@{
            Who   = $_[0]
            Does  = $_[1]
            Topic = $_[2]
        }
    }
    
    Who   Does   Topic
    ---   ----   -----
    Tavin enjoys powershell

Other sides of the same question

  1. Choosing enum entries randomly with GDScript in Godot 3.3 without listing each one?

    Here's the enum declaration I'm using in GDScript: I'd like to choose an enum variant randomly without listing every possible…

    Replies 2Latest activity gdscript
  2. Nim remainder syntax

    How is modulus expressed in Nim? cell % 7 == 0 gives undeclared identifier: '%' Neither a Google search nor looking through S…

    Replies 2Latest activity nim
  3. Returning results from an APL function

    How do I make my function return something once execution has finished? For instance, I have: ROUTINE N ? N ⍴ 12 //That gener…

    Replies 2Latest activity apl