|
1 | 1 | --- |
2 | | -RFC: 0002 |
3 | | -Author: Jason Shirk |
| 2 | +RFC: |
| 3 | +Author: Jody Whitlock |
4 | 4 | Status: Draft |
5 | | -Area: Splatting |
6 | | -Comments Due: 3/31/2016 |
| 5 | +Area: Commands |
| 6 | +Comments Due: |
7 | 7 | --- |
8 | 8 |
|
9 | | -# Generalized Splatting |
| 9 | +# Get-TestConnection cmdlet for non-Windows Systems |
10 | 10 |
|
11 | | -Splatting was introduced in PowerShell v2 |
12 | | -as a way of passing named arguments to a command |
13 | | -using an expression (e.g. `@PSBoundParameters`) |
14 | | -instead of explicit parameter syntax (e.g. `-Param1 $value`). |
15 | | -The expression syntax introduced was limited |
16 | | -to variable references and is more restrictive than necessary. |
| 11 | +Test-Connection, introduced in PowerShell 2.0 under the Microsoft.PowerShell.Management class provided a mechanism for sending ICMP echo requests within the PowerShell language and have the results returned as a PowerShell object that could be manipulated as such. |
17 | 12 |
|
18 | | -Proxy functions are much easier to write using splatting. |
19 | | -A proxy function might add or remove parameters to another command, |
20 | | -but might not care about all of the parameters to the proxied command. |
21 | | -The proxy still needs to pass those parameters through to the proxy, |
22 | | -and it does this with splatting. |
23 | | - |
24 | | -Scripters have found splatting useful beyond proxy functions, |
25 | | -but the current syntax limits broader use of splatting. |
| 13 | +While it's true that Test-Connection has evolved very little over the years and versions of PowerShell, on only need to look at the legacy that this cmdlet builds on, the ping command. This simple command has mostly remained unchanged for as long as the ICMP protocol has existed. It's a very simplistic function that while simplistic fills a massive void in network troubleshooting and validation of communication capabilities. |
26 | 14 |
|
27 | 15 | ## Motivation |
28 | 16 |
|
29 | | -One common use of splatting is to provide an alternate syntax for calling a command with many parameters. |
30 | | -For example, consider a command like the following |
31 | | - |
32 | | -```PowerShell |
33 | | -Update-TypeData -TypeName MyCustomType ` |
34 | | - -MemberName MyCustomProperty ` |
35 | | - -MemberType NoteProperty ` |
36 | | - -Value 42 |
37 | | -``` |
38 | | - |
39 | | -In the above example, note the use of backticks at the end of every line. |
40 | | -Those backticks are difficult to read and easy to forget. |
41 | | -Splatting can help some here: |
| 17 | +The motivation for this RFC is as simple as the ping command itself; provide a Test-Connection cmdlet that can run on any platform that PowerShell can. This means stripping out some of the WSMan specific remoting capabilities that have been added to allow for distributed execution and removing WMI based methods and classes in favor of pure C# code. |
42 | 18 |
|
43 | | -```PowerShell |
44 | | -$addTypeParams = @{ |
45 | | - TypeName = 'MyCustomType' |
46 | | - MemberName = 'MyCustomProperty' |
47 | | - MemberType = 'NoteProperty' |
48 | | - Value = 42 |
49 | | -} |
50 | | -Update-TypeData @addTypeParams |
51 | | -``` |
| 19 | +This could also be back-ported into the Windows implementation, which while immediately removing the remoting capability would increase the performance of the cmdlet by not requiring WMI accessors and allow for tighter integration between multiple platforms that this cmdlet could run on. |
52 | 20 |
|
53 | | -This works, but feels a bit messy because of the need for a variable, |
54 | | -when the hashtable could start on the same line as the command name. |
| 21 | +It would also serve as a framework for further enhancement, such as using SSHRemoting to enable the distributed approach to performing a distributed ping, while allowing for some built in governor mechanism to prevent abuse of the distributed nature. |
55 | 22 |
|
56 | | -Another common use of splatting is to remove a specific parameter when splatting: |
57 | | - |
58 | | -```PowerShell |
59 | | -$PSBoundParameters.Remove('SomeExtraParam') |
60 | | -Command @PSBoundParameters |
61 | | -``` |
62 | | - |
63 | | -This proposal suggesst a syntax that improves this scenario as well. |
| 23 | +Lastly, and most importantly, while the current Test-Connection cmdlet in the Windows invocation of PowerShell is limited, it is used extensively to check for the existence and responsiveness of remote systems. By not providing a non-Windows specific implementation that is as close in parameter set and return types then existing code must be re-written to overcome this limitation, or adoption of PowerShell on non-Windows platforms may be barred by the lack of this simple but widely used functionality. |
64 | 24 |
|
65 | 25 | ## Specification |
66 | 26 |
|
67 | | -This RFC proposes a more generalized syntax for splatting to support: |
68 | | - |
69 | | -- Splatting general expressions (as opposed to simple variables) |
70 | | -- Splatting in method invocations |
71 | | -- Splatting in switch cases |
72 | | - |
73 | | -Today, the syntax for splatting is a sigil used on a variable name. |
74 | | -This proposal expands the use of the sigil to be allowed on an expression. |
75 | | -For example: |
76 | | - |
77 | | -```PowerShell |
78 | | -# Existing usage: |
79 | | -command @PSBoundParameters |
80 | | -
|
81 | | -# Equivalent - but splatting an expression (the value of a variable) |
82 | | -command @$PSBoundParameters |
83 | | -
|
84 | | -# Splat another expression - a hashtable |
85 | | -Update-TypeData @@{ |
86 | | - TypeName = 'MyCustomType' |
87 | | - MemberName = 'MyCustomProperty' |
88 | | - MemberType = 'NoteProperty' |
89 | | - Value = 42 |
90 | | -} |
91 | | -``` |
92 | | - |
93 | | -Note the two '@' characters in the hashtable example above. |
94 | | -If the second '@' was omitted, the example would pass a hashtable (no splatting) |
95 | | -in all versions of PowerShell, even V1, which means splatting without the second '@' |
96 | | -would be a breaking change. |
97 | | - |
98 | | -We can use more general expressions as well: |
99 | | - |
100 | | -```PowerShell |
101 | | -# Call a command that returns a hashtable or array to splat |
102 | | -Get-ChildItem @$(Get-ChildItemArgs) |
103 | | -
|
104 | | -# a method that returns a hashtable or array to splat |
105 | | -Invoke-Something @$($obj.GetInvokerArgs()) |
106 | | -``` |
107 | | - |
108 | | -### Relaxed splatting |
109 | | - |
110 | | -In some cases, it is desirable to splat only the arguments that are available, |
111 | | -and ignore the others. |
112 | | -We will call this relaxed splatting. |
113 | | -For example: |
114 | | - |
115 | | -```PowerShell |
116 | | -$myArgs = @{ Path = $pwd; ExtraStuff = 1234 } |
117 | | -Get-ChildItem @$myArgs |
118 | | -``` |
119 | | - |
120 | | -The above example would fail with a "parameter not found" because of the 'ExtraStuff' key. |
121 | | -Here is a possible syntax to allow the above without resulting in an error: |
122 | | - |
123 | | -```PowerShell |
124 | | -$myArgs = @{ Path = $pwd; ExtraStuff = 1234 } |
125 | | -Get-ChildItem @?$myArgs |
126 | | -``` |
127 | | - |
128 | | -We can think of '@?' as the 'relaxed splatting' operator. |
129 | | -If '@' is the splatting operator, |
130 | | -adding the '?' is suggestive of being more permissive, |
131 | | -much like the C# '?.' member access operator. |
132 | | - |
133 | | -### Splatting in method invocations |
134 | | - |
135 | | -Today, named arguments are only supported when calling commands, |
136 | | -named arguments do not work when calling methods. |
137 | | -PowerShell could adopt a C# like syntax to name arguments, |
138 | | -but splatting provides a similar capability with some additional flexibility. |
139 | | -The obvious syntax would mirror command invocation: |
140 | | - |
141 | | -```PowerShell |
142 | | -# Splat a hashtable defined outside the method call |
143 | | -$subStringArgs = @{startIndex = 2} |
144 | | -$str.SubString(@$subStringArgs) |
145 | | -
|
146 | | -# Splat a hashtable defined inline in the method call |
147 | | -$str.SubString(@@{startIndex = 2; length=2}) |
148 | | -``` |
149 | | - |
150 | | -Mixing splatting and positional arguments is supported. |
151 | | - |
152 | | -```PowerShell |
153 | | -$str.SubString(2, @@{length=2}) |
154 | | -``` |
155 | | - |
156 | | -A runtime check (or parse time if possible) is necessary to make sure an argument is not specified positionally |
157 | | -and via splatting in the same invocation: |
158 | | - |
159 | | -```PowerShell |
160 | | -# Must be an error, parse time or runtime, because startIndex |
161 | | -# is specified positionally and via splatting. |
162 | | -$subStringArgs = @{startIndex = 2} |
163 | | -$str.SubString(2, @$subStringArgs) |
164 | | -``` |
165 | | - |
166 | | -Multiple splatted arguments are not allowed: |
167 | | - |
168 | | -```PowerShell |
169 | | -# Error, multiple splatted arguments |
170 | | -$str.SubString(@@{startIndex = 2}, @@{length=2}) |
171 | | -``` |
172 | | - |
173 | | -The splatted argument must be last. |
174 | | - |
175 | | -```PowerShell |
176 | | -# Error, splatted argument is not last |
177 | | -$str.SubString(@@{length=2}, 2) |
178 | | -``` |
179 | | - |
180 | | -### Splatting in switch cases |
181 | | - |
182 | | -It can be awkward to match multiple conditions with a single switch statement. |
183 | | -For example: |
184 | | - |
185 | | -```PowerShell |
186 | | -switch ($color) { |
187 | | - { $_ -eq 'Red' -or $_ -eq 'Blue' -or $_ -eq 'Green' } { $true } |
188 | | - default { $false } |
189 | | -} |
190 | | -``` |
191 | | - |
192 | | -With splatting, this can be simplified: |
193 | | - |
194 | | -```PowerShell |
195 | | -switch ($color) { |
196 | | - @@('Red','Blue','Green') { $true } |
197 | | - default { $false } |
198 | | -} |
199 | | -``` |
200 | | - |
201 | | -### Modifying hashtables for splatting |
202 | | - |
203 | | -Sometimes it is useful to provide a 'slice' of a hashtable, |
204 | | -e.g. you want to remove or include specific keys. |
205 | | -The Add/Remove methods on a hashtable work, but can be verbose. |
206 | | -This proposal suggests overloading the '+' and '-' operators to provide a hashtable 'slice': |
207 | | - |
208 | | -```PowerShell |
209 | | -Get-ChildItem @$($PSBoundParameters - 'Force') # Splat all parameters but 'Force' |
210 | | -Get-ChildItem @$($PSBoundParameters - 'Force','WhatIf') # Splat all parameters but 'Force' and 'WhatIf' |
211 | | -Get-ChildItem @$($PSBOundParameters + 'LiteralPath','Path') # Only splat 'LiteralPath' and 'Path' |
212 | | -``` |
213 | | - |
214 | | -Today, PowerShell supports "adding" two hashtables with the '+' operator, |
215 | | -the result is a new hashtable with all of the key value pairs from both hashtables. |
216 | | -It is an error for a key to be specified in both operands. |
217 | | - |
218 | | -This proposal adds semantics for adding and subtracting other values. |
219 | | -If the value is enumerable, the effect is to treat each value in the collection as a key, |
220 | | -otherwise the value is treated as a single key. |
221 | | -The result is always a new hashtable, |
222 | | -the left hashtable operand is unmodified. |
223 | | - |
224 | | -When using '+', the result will only include keys found in the right hand side. |
225 | | -When using '-', the result will exclude all keys from the right hand side. |
226 | | - |
227 | | -In either case, |
228 | | -it is not an error to specify a key in the right hand side operand that is not present in the left hand side. |
229 | | - |
230 | 27 | ## Alternate Proposals and Considerations |
231 | 28 |
|
232 | | -### Slicing operators |
233 | | - |
234 | | -The suggested use of '+' and '-' is perhaps surprising |
235 | | -even though they correspond to Add and Remove, respectively. |
236 | | -The actual operation is also similar to a union or intersection, |
237 | | -so other operators should be considered, perhaps bitwise operators |
238 | | -like '-bnot' and '-bor', or maybe new general purpose set operators. |
239 | | - |
240 | | -### Postfix operator |
241 | | - |
242 | | -The use of a sigil is not always well received. |
243 | | -This proposal nearly considers '@' a prefix unary operator, |
244 | | -but it doesn't quite specify it as such. |
| 29 | +An alternate proposal is to not implement Test-Connection but rather build a new cmdlet from the ground up to replace Test-Connection entirely. This would be similar in impact to not implementing Test-Connection cross-platform by requiring an unknown amount of code changes to occur before adoption on non-Windows platforms can occur. |
245 | 30 |
|
246 | | -A postfix operator is another possiblity and would look less like a sigil. |
247 | | -This idea was rejected because, when reading a command invocation from left to right, |
248 | | -it's important to understand how a hash literal is to be used. |
249 | | -The sigil makes it clear a hash literal is really specifying command arguments. |
250 | | -Furthermore, the sigil simplifies the analysis required for good parameter completion, |
251 | | -and does not require a complete expression to begin providing parameter name completion. |
| 31 | +This may also lend to those that require this functionality to create seperate code-bases and modules to fill the gap, leading to many custom solutions and suffering from the lack of standards and community collaboration. |
0 commit comments