Skip to content

Add enhanced splatting RFC draft #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

jborean93
Copy link
Owner

@jborean93 jborean93 commented May 27, 2025

This is a draft RFC of an enhanced splatting proposal. While I have my own recommendations there is no final choice as of yet to open with the real RFC.

This RFC aims to enhance the existing splatting mechanism in PowerShell to support

  • Splatting variable members
  • Splatting inline hashtable and and arrays
  • Splatting expression values, like a cmdlet output

It is not aiming to:

  • Fix any existing splatting problems, e.g. no support for PSCustomObject, string splatting, etc
  • .NET method splatting
  • Filtering hashtable options inline

So far my gut choice would be Option 4 - the -@ parameter with support for using multiple instances of -@ to splat with.

# Inline hashtable
Test-Function -@ @{
   Path = 'C:\path'
}

# Multiple -@ with var and var member access
$var = @{
    Path = 'C:\path'
}
$obj = [PSCustomObject]@{
    Prop = @{
        Force = $true
    }
}
Copy-Item -@ $var -@ $obj.Prop

# Expression splat
Function Get-SplatValue {
    @{
        Path = 'C:\path'
    }
 }

Test-Function -@ (Get-SplatValue)

This option offers the most flexibility around its use, consistency with all the splatting scenarios, and only a small risk of being a breaking change but I can agree that people may not expect this syntax. Happy to be convinced otherwise!

Using Option 1 Test-Function @@{...} is a strong contender and most likely what people's gut reaction will be. My thoughts are that it doesn't have a consistent syntax and made even more problematic when attempting to support expressions. For example inline literals need another @ and an expression is even more complicated if you are trying to avoid breaking changes:

ht = @{} # hashtable
Test-Function @{}  # Passes hashtable positionally
Test-Function @ht  # Splats hashtable var to parameters
Test-Function @@{}  # Splats inline hashtable to parameters

$ar = @() # array
Test-Function @()  # Passes array positionally
Test-Function @ar  # Splats array var positionally
Test-Function @@()  # By convention this should be splat inline array positionally

# This would be nice for an expression but would be
# a breaking change to existing scripts
Test-Function @$(Get-SplatValue)

# This is the proposed expression syntax but it just seems inconsistent with
# the other options and seems overly verbose/symbol heavy
Test-Function @&{Get-SplatValue}

Any suggestions around formatting or edits to this to make it concise or alternatives formats are more than welcome. Would love to see people's thoughts around what is shown here before moving onto the next step.

If you wish to convey your desired option please react with 1 of these 5 reactions

  • 😄 Option 1 @@<expr>
  • 🎉 Option 2 ..<expr>
  • ❤️ Option 3 @[<expr>]
  • 🚀 Option 4 -@ param
  • 👀 Option 5 -splat operator

@mklement0

This comment was marked as outdated.

@jborean93
Copy link
Owner Author

jborean93 commented May 27, 2025

-@ is technically also a breaking change, because something like Write-Host -@ currently works.

Yep, the text does point this out but there are a few things to clarify

I agree that @$(...) is weird and unexpected behaviour and I would by far prefer that to be used over @&{...} if option 1 is the ultimate choice.

By contrast, -@ (a) breaks comparatively more useful current behavior.

Unless my searching is subpar I've never seen this anywhere and I'm not sure whether it is actually useful.

While I agree there is a risk I think like @$(...) there is a very minute chance this will actually affect people and is worth taking if that's the chosen scenario. Still something to be aware off when making the ultimate choice.

Option 5 is better characterized as a -splat common parameter (not operator), as proposed in #25574

Not sure what you mean here, it's a unary operator hence the reason why it's inside an expression

  • Option 4 - Test-Function -@ $paramValueToSplat
  • Option 5 - Test-Function (-splat $fooToSplatOnOperator)

Based on your latest edit, your -@ suggestion is, in effect, an alias of the proposed -splat parameter (though you're not framing it as a common parameter).

Yep the PR does point out that another name could be used but I went with -@ because

  • it is easier to type
  • it still gives some link back to splatting with the @
  • you have to go out of your way to define as a parameter $VarName vs ${@}
  • outside of non-advanced functions or things collecting unbound args, you cannot use -@ foo to bind to the "@" parameter

The same option could be substituted with another name if that's desired but after weighing up the options, and the precedence that -? has for Get-Help being a parameter but not really a parameter I found -@ fit in nicely with this option.

@mklement0
Copy link

My bad: I based my previous comment solely on your summary of the RFC here, neglecting to look at the actual RFC (which is thorough and well-written, kudos).

Thus, I mistakenly assumed that -splat referred to @iRon7's common-parameter proposal in PowerShell/PowerShell#25574
Personally, I think that an operator is the wrong solution here, due to the mixing of parsing modes and the ceremony of (...) enclosure.

At the end of the day, I agree that -@ <expression> may be the best solution. I've hidden my previous comment, and I've changed my vote.

@jborean93
Copy link
Owner Author

I've opened PowerShell#397 which is an official RFC submission with option 4 -@ as the recommended approach. I'll close this PR but feel free to comment here or on the RFC PR with anything you wish to share.

Thanks everyone for looking through this all and commenting/voting!

@jborean93 jborean93 closed this Aug 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants