You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Note that with the change to allow assignments from statements, the need for a ternary operator is reduced. You can simply do $var = if ($x) { $x } else { $y }
It's not as concise as the ternary operator but is arguably more readable.
Reacted by eosfor, Christoph Bergmeister, Warren Frame, vemoo, Ivan Akcheurov, Sunil Mujumdar, Semicolon and Lemmingh
Reacted by Maximilian Orsley, Miodrag Milić, antiufo, Ikiru Yoshizaki, Kris Borowinski and Bryan Haro
Yes, though you still have to use $(...)in addition if the conditional is part of a larger expression:
'The current sec. is '+$(if ((get-date).tostring("ss") %2) { 'odd' } else { 'even' })
vs.
'The current sec. is '+ ((get-date).tostring("ss") %2?'odd' : 'even')
I know that readability is in the eye of the ... uh ... reader, but I personally find the latter visually easier to parse, and having to type less is always a bonus.
With such a frequently used feature, I think remembering the more abstract ternary syntax wouldn't be a problem (and, of course, people can continue to use if, if they prefer).
This is definitely on my top list to. Bruce Payette (@BrucePay), are there any reasons that this would be a bad idea? Or is it just about 'to ship is to choose' ?
Reacted by Keith Hill, Kris Borowinski, Michael Klement and Maximilian Orsley
In the past, this feature request was turned down as being harder for less experienced scripters to understand, and that the expression form of the if statement was a clearer, though more verbose alternative.
My personal perspective: if the language was just for me, I'd probably have added it a long time ago. But ... I find many developers don't use it, which actually suggests there is some truth to the hypothesis that less experienced folks will have trouble with the ternary operator.
It's worth distinguishing between active use of a feature vs. the ability to recognize and understand it.
Clearly, everyone gets to choose whether to use such a feature, but are you saying that "have trouble with" means that less experienced folks won't understand it when they see it in the code of others?
Michael Klement (@mklement0) - we introduced $psitem as an alias for $_ because of sufficient feedback that $_ was cryptic and confusing, so I do believe the ternary operator would be difficult for some less experienced people to understand.
On the other hand, there are many elements in PowerShell that are confusing to beginners, or even to quite experienced developers.
As with any other language, it takes some effort to learn the syntax and meaning of language constructs.
I don't know if I think the ternary operator is especially difficult to grasp.
Do you have data suggesting that it is?
Reacted by Michael Klement, Troy Campbell, Laurent Dardenne, Maximilian Orsley, Kris Borowinski, Miodrag Milić, Jos Krause and Mike Garvey
-then/-else fits well with PowerShell syntax - but, an operator (or operators if it's too confusing to think of as a single operator), you gain the benefit of not needing parens and braces.
Then again, this is asking for trouble similar to foreach vs. foreach-object. but maybe it's not as bad, I don't know.
PowerShell is commendably not cryptic overall, but in some cases offers cryptic syntax as a concise alternative (you still can be verbose if desired) for frequently used constructs, notably ? for Where-Object and % for ForEach-Object.
Providing $x ? $y : $z as a concise alternative to if ($x) then { $y } else { $z } to me is in the same spirit.
The cryptic aspect is ameliorated by ? being reminiscent of a question and therefore suggesting a conditional (albeit one preceding the ? in this case), and - more importantly - being a potentially familiar construct from several other languages, with the same fundamental semantics.
You don't get the same benefit with $x -then $y -else $z: it is not familiar.
Also, while many PS operators do have symbolic names, many do not: * / + % ...
These are inherently cryptic too, we just don't perceive them that way anymore, because they are so familiar and ubiquitous.
My sense is that $x ? $y : $z too is already familiar to many, and will become even more so once introduced into the language, given the frequent need for concise conditionals.
Reacted by Maximilian Orsley, Rain Sallow (/u/ta11ow), Miodrag Milić, Kris Borowinski, iRon7, Joey Aiello, Jos Krause and Mike Garvey
Note that you'll be pretty limited in what you can specify with this operator. In particular you won't be able to use commands unless you wrap them in parenthesis:
To my mind, there is little advantage in terms of brevity and a distinct disadvantage in readability. The ternary operator is far less interesting when you have an expression oriented language. When I started on the language 16 years ago, adding the ternary operator seemed obvious coming from a C background. Now I'm glad we never added it. It just feels like clutter.
Reacted by Bo Lingen, lukeb1961, Joel Bennett, Semicolon and Lemmingh
In particular you won't be able to use commands unless you wrap them in parentheses:
That applies to any PowerShell operator.
Not all PowerShell statements involve commands, and when they do, users already know that (...) is the price of admission for commands (in most cases).
In your own example, to me ((test-path foo.txt) ? "foo.txt" : "bar.txt") beats $(if (test-path foo.txt) {"foo.txt"} else {"bar.txt"}), both for the obscurity of needing $(...) and the noise introduced by the curly braces.
Reacted by Maximilian Orsley, Rain Sallow (/u/ta11ow) and Devyn Spencer
🤔 it might work, but it would be more awkward than any of the proposed alternatives. -replace works that way because it just accepts an actual array of arguments. .Replace() is not managed by the PS team -- it's a method on the .NET System.String class.
If we were to try to use either of those syntaxes it'd mean either an ETS method (which is OK, but tends to add a bit of performance overhead to creation of objects it needs to be attached to) or, with the operator version you propose, we wouldn't be able to easily have an array as an argument.
Without special-casing such an operator in the parser, we wouldn't be able to short-circuit. Ternary syntaxes in other languages generally exist because you don't want to actually evaluate both options; the compute time is quicker if only the correct branch needs to be evaluated, rather than having to full evaluate both options (which might come with some significant side effects).
And since that would already require special-casing, it would be more effective to introduce new syntax for it, to minimise confusion (it would be a bit misleading to have something that looks like an array but can't be used like one; it wouldn't support creating the "array" ahead of time and passing that as a variable, for example). The fact that method arguments already conflict a bit with array syntax is often already misleading. I don't think I'd want to add a third variant behaviour for commas to the mix.
Reacted by Iain Madder, Dongbo Wang, Patrick Meinecke, Michael Klement, Maximilian Orsley and Devyn Spencer
@PowerShell/powershell-committee discussed this at length, we don't all agree, but a majority agree that there is value in having this operator and to align with C# syntax keeping ?: as expectation is that most usage will be from C# developers. This feature will be Experimental pending real usage feedback.
Steve Lee (@SteveL-MSFT) So that means the feature is moving forward for 7.0? Will it break compatibility on variables being able to use ? in their symbol?
@TheIncorrigible1 yes, this feature is moving forward in PS7. It should not break compatibility with use of ? alias. There is a concern about the visual acuity of ? when glancing at a script trying to differentiate Where-Object and ternary, but we'll see what the user feedback is on this. In general, we don't expect most users to use this operator but that should not prevent it from moving forward.
Requiring whitespace between the first operand and the ? solves that problem, as previously suggested, and to me it is a perfectly reasonable solution:
The :also requires whitespace around it, because something like $true ? $number:42 wouldn't work, given that $number:42 would as a whole be interpreted as a single variable reference.
While C# does allow true?number:42, I don't think we need to - or, indeed, can - worry about compatibility at that level. I personally value concision, but not at the expense of readability; even if I could write $true?$number:42, I wouldn't.
(Backward compatibility will indeed be a problem when (hint, hint) we implement null-conditional access. PowerShell's permissiveness with respect to identifier names is generally problematic, as Kirk Munro (@KirkMunro) has recently argued, but that ship has sailed)
Reacted by Rain Sallow (/u/ta11ow), Maximilian Orsley and Steve Lee
The prototype tried pretty hard to parse numbers with ? and : in them differently in the context of ternary operator (where we know we are expecting an expression). So you can write things like ${isWindows}?12:47.
Numbers like 123? or 1:23 are tokenized as a generic token today, which is not useful at all in the case where we know we are expecting an expression.
For variables, no change at all to how ? or : can be used for the variable name, since variable is an expression.
Reacted by Michael Klement, Rain Sallow (/u/ta11ow) and Maximilian Orsley
Good point, Dongbo Wang (@daxian-dbw); I forgot that {...} can be used to resolve any variable-name boundary ambiguity, so I guess code golfers could use something like ${isWindows}?${number}:47
Activity
BrucePay commentedon Mar 2, 2017
Note that with the change to allow assignments from statements, the need for a ternary operator is reduced. You can simply do
$var = if ($x) { $x } else { $y }It's not as concise as the ternary operator but is arguably more readable.
mklement0 commentedon Mar 2, 2017
Yes, though you still have to use
$(...)in addition if the conditional is part of a larger expression:vs.
I know that readability is in the eye of the ... uh ... reader, but I personally find the latter visually easier to parse, and having to type less is always a bonus.
With such a frequently used feature, I think remembering the more abstract ternary syntax wouldn't be a problem (and, of course, people can continue to use
if, if they prefer).thezim commentedon Mar 2, 2017
Michael Klement (@mklement0) I have to agree later has less cognitive load.
powercode commentedon Feb 5, 2018
This is definitely on my top list to.
Bruce Payette (@BrucePay), are there any reasons that this would be a bad idea? Or is it just about 'to ship is to choose' ?
lzybkr commentedon Feb 5, 2018
In the past, this feature request was turned down as being harder for less experienced scripters to understand, and that the expression form of the if statement was a clearer, though more verbose alternative.
My personal perspective: if the language was just for me, I'd probably have added it a long time ago. But ... I find many developers don't use it, which actually suggests there is some truth to the hypothesis that less experienced folks will have trouble with the ternary operator.
mklement0 commentedon Feb 11, 2018
Jason Shirk (@lzybkr):
It's worth distinguishing between active use of a feature vs. the ability to recognize and understand it.
Clearly, everyone gets to choose whether to use such a feature, but are you saying that "have trouble with" means that less experienced folks won't understand it when they see it in the code of others?
lzybkr commentedon Feb 12, 2018
Michael Klement (@mklement0) - we introduced
$psitemas an alias for$_because of sufficient feedback that$_was cryptic and confusing, so I do believe the ternary operator would be difficult for some less experienced people to understand.powercode commentedon Feb 12, 2018
On the other hand, there are many elements in PowerShell that are confusing to beginners, or even to quite experienced developers.
As with any other language, it takes some effort to learn the syntax and meaning of language constructs.
I don't know if I think the ternary operator is especially difficult to grasp.
Do you have data suggesting that it is?
lzybkr commentedon Feb 12, 2018
I believe the only data is anecdotal, but the criticism applies to any cryptic language - bash, perl, etc.
And to be clear, I was providing the historical context. Maybe PowerShell is ubiquitous enough now that more cryptic syntax won't affect adoption.
Also keep in mind - some terse languages still use if/then as the ternary operator, e.g. F#.
That said, maybe it's possible to use fewer characters and not be too cryptic:
-then/-elsefits well with PowerShell syntax - but, an operator (or operators if it's too confusing to think of as a single operator), you gain the benefit of not needing parens and braces.Then again, this is asking for trouble similar to
foreachvs.foreach-object. but maybe it's not as bad, I don't know.mklement0 commentedon Feb 19, 2018
Jason Shirk (@lzybkr):
Cryptic in homeopathic doses is healthy:
PowerShell is commendably not cryptic overall, but in some cases offers cryptic syntax as a concise alternative (you still can be verbose if desired) for frequently used constructs, notably
?forWhere-Objectand%forForEach-Object.Providing
$x ? $y : $zas a concise alternative toif ($x) then { $y } else { $z }to me is in the same spirit.The cryptic aspect is ameliorated by
?being reminiscent of a question and therefore suggesting a conditional (albeit one preceding the?in this case), and - more importantly - being a potentially familiar construct from several other languages, with the same fundamental semantics.You don't get the same benefit with
$x -then $y -else $z: it is not familiar.Also, while many PS operators do have symbolic names, many do not:
* / + % ...These are inherently cryptic too, we just don't perceive them that way anymore, because they are so familiar and ubiquitous.
My sense is that
$x ? $y : $ztoo is already familiar to many, and will become even more so once introduced into the language, given the frequent need for concise conditionals.BrucePay commentedon Apr 24, 2018
Note that you'll be pretty limited in what you can specify with this operator. In particular you won't be able to use commands unless you wrap them in parenthesis:
compared with
or
vs
To my mind, there is little advantage in terms of brevity and a distinct disadvantage in readability. The ternary operator is far less interesting when you have an expression oriented language. When I started on the language 16 years ago, adding the ternary operator seemed obvious coming from a C background. Now I'm glad we never added it. It just feels like clutter.
mklement0 commentedon Apr 24, 2018
That applies to any PowerShell operator.
Not all PowerShell statements involve commands, and when they do, users already know that
(...)is the price of admission for commands (in most cases).In your own example, to me
((test-path foo.txt) ? "foo.txt" : "bar.txt")beats$(if (test-path foo.txt) {"foo.txt"} else {"bar.txt"}), both for the obscurity of needing$(...)and the noise introduced by the curly braces.35 remaining items
vexx32 commentedon Jul 17, 2019
🤔 it might work, but it would be more awkward than any of the proposed alternatives.
-replaceworks that way because it just accepts an actual array of arguments..Replace()is not managed by the PS team -- it's a method on the .NETSystem.Stringclass.If we were to try to use either of those syntaxes it'd mean either an ETS method (which is OK, but tends to add a bit of performance overhead to creation of objects it needs to be attached to) or, with the operator version you propose, we wouldn't be able to easily have an array as an argument.
Without special-casing such an operator in the parser, we wouldn't be able to short-circuit. Ternary syntaxes in other languages generally exist because you don't want to actually evaluate both options; the compute time is quicker if only the correct branch needs to be evaluated, rather than having to full evaluate both options (which might come with some significant side effects).
And since that would already require special-casing, it would be more effective to introduce new syntax for it, to minimise confusion (it would be a bit misleading to have something that looks like an array but can't be used like one; it wouldn't support creating the "array" ahead of time and passing that as a variable, for example). The fact that method arguments already conflict a bit with array syntax is often already misleading. I don't think I'd want to add a third variant behaviour for commas to the mix.
SteveL-MSFT commentedon Jul 31, 2019
@PowerShell/powershell-committee discussed this at length, we don't all agree, but a majority agree that there is value in having this operator and to align with C# syntax keeping
?:as expectation is that most usage will be from C# developers. This feature will be Experimental pending real usage feedback.morsley commentedon Aug 3, 2019
Steve Lee (@SteveL-MSFT) So that means the feature is moving forward for 7.0? Will it break compatibility on variables being able to use
?in their symbol?SteveL-MSFT commentedon Aug 4, 2019
@TheIncorrigible1 yes, this feature is moving forward in PS7. It should not break compatibility with use of
?alias. There is a concern about the visual acuity of?when glancing at a script trying to differentiateWhere-Objectandternary, but we'll see what the user feedback is on this. In general, we don't expect most users to use this operator but that should not prevent it from moving forward.morsley commentedon Aug 5, 2019
Steve Lee (@SteveL-MSFT) I mean variables with a name of
$isValid?or similar. These are valid tokens in the current iteration of PS.mklement0 commentedon Aug 5, 2019
@TheIncorrigible1:
Requiring whitespace between the first operand and the
?solves that problem, as previously suggested, and to me it is a perfectly reasonable solution:The
:also requires whitespace around it, because something like$true ? $number:42wouldn't work, given that$number:42would as a whole be interpreted as a single variable reference.While C# does allow
true?number:42, I don't think we need to - or, indeed, can - worry about compatibility at that level. I personally value concision, but not at the expense of readability; even if I could write$true?$number:42, I wouldn't.(Backward compatibility will indeed be a problem when (hint, hint) we implement null-conditional access. PowerShell's permissiveness with respect to identifier names is generally problematic, as Kirk Munro (@KirkMunro) has recently argued, but that ship has sailed)
vexx32 commentedon Aug 5, 2019
Yeah, I think leaving the whitespace requirement is sensible. It's terse enough as it is, after all. 😁
daxian-dbw commentedon Aug 5, 2019
The prototype tried pretty hard to parse numbers with
?and:in them differently in the context of ternary operator (where we know we are expecting an expression). So you can write things like${isWindows}?12:47.Numbers like
123?or1:23are tokenized as a generic token today, which is not useful at all in the case where we know we are expecting an expression.For variables, no change at all to how
?or:can be used for the variable name, since variable is an expression.mklement0 commentedon Aug 6, 2019
Good point, Dongbo Wang (@daxian-dbw); I forgot that
{...}can be used to resolve any variable-name boundary ambiguity, so I guess code golfers could use something like${isWindows}?${number}:47TylerLeonhardt commentedon Sep 14, 2019
Can we close this now?
daxian-dbw commentedon Sep 14, 2019
Close via #10367