-
Notifications
You must be signed in to change notification settings - Fork 129
Null conditional operators for coalescing, assignment and member access #223
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
Changes from 1 commit
c4cb77d
8449c4b
6dfa2c3
e41f35b
7a8f5f7
c5eb257
177eaa2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -81,43 +81,6 @@ The `??` operator checks the left hand side to be null or undefined and returns | |
|
||
If the module `Pester` is not installed, then install the module. | ||
|
||
### Updates to operator precedence | ||
|
||
The operator precedence token flags will be updated to add gaps and place the null coalesce opeator at position 7, above comparison and below add/subtract. | ||
Currently, the binary operator mask is set at `0x07`, which will be updated to `0x0f`. | ||
This will ensure that `??` is evaluated before operators like `-eq`, `-and`, `-bor` etc, but after `+` and `-`. | ||
|
||
This enables scenarios like: | ||
```PowerShell | ||
'x' -eq $null ?? 'x' evaluates to 'x' -eq ($null ?? 'x') | ||
|
||
2 + $null ?? 3 evaluates to (2 + $null) ?? 3 | ||
``` | ||
|
||
### Additional considerations | ||
|
||
The `??=` and `??` operators are binary operators and check for the value of the left hand side to be null or an undefined variable. | ||
They can be used with a space between the variable name and the to operator. | ||
If the left hand side is null, then `??=` assigns the right hand side to the variable while, the `??` operator returns the right hand side. | ||
When they are used without a space between variable name and the operator, a `{}` must be used around the variable name. | ||
|
||
## Alternate Proposals and Considerations | ||
|
||
### Disallow `?` in variable names | ||
|
||
It was considered to disallow `?` in variable names, to avoid confusion whether the operator is a null conditional operator or the variable name has `?` in it. | ||
This proposal was rejected to maintain backward compatibility. | ||
|
||
### Prefer new operators when tokenizing variable names | ||
|
||
It was considered to look ahead when tokenizing the variable names and check for `??=`, `??`, `?.` or `?[]`. | ||
If the token is found the assume that it is a null conditional check and not a member access of a variable name ending in `?`. | ||
To maintain backward compatibility and this proposal was rejected. | ||
|
||
### Use a different sigil for null-conditional operators | ||
|
||
It was determined that the familiarity of `?.` and `??` operators to `C#` programmers will make usage of the new operators easier to understand than introducing new sigils. | ||
|
||
### Null conditional member access operators - `?.` and `?[]` | ||
|
||
Null member access operators can used on scalar types and array types. | ||
|
@@ -153,3 +116,40 @@ The `?.` and `?[]` operators are member access operators and do not allow a spac | |
PowerShell allows `?` as part of the variable name. | ||
Hence disambiguation is required when the operators are used without a space between the variable name and the operator. | ||
To disambiguate, the variables must use `{}` around the variable name like: `${x?}?.propertyName` or `${y}?[0]`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reading between the lines for the alternate proposal comments, it seems like the final decision is to always consider I think that's probably going to make for less usage of these operators in general, given that any use of them is going to complicate syntax an additional level here... What is the reason for rejecting the proposal to preferentially tokenize There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Me reading between the lines: I think there is concern that if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, yeah I guess I can see that, potentially. That's one of the reasons I'm in favour of Really, it seems like every solution here is kind of problematic in its own way, but I feel that the solution currently preferred by this RFC is the most problematic, because it creates a pattern for requiring more complex syntax that may be permanent. A one-time break is one thing, but requiring more complicated syntax in (probably) every future version of PowerShell seems like a worse change to me. 😕 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Agreed. I think that loses all familiarity that the syntax of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very confused by this statement: If the left hand side is null then return the right hand side, else return the right hand side. (Wouldn't that mean "always return the right-hand side"?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lots of operators: -match, -replace, -contains, -split, -join, -as, -is, -isnot, -f, +=, -=, *+, /=, ++, --, etc. etc. The arithmetic operators very C-family based; the others - not so much. Some supporting very odd syntax already (I'm looking at replace and join as I write that). If someone is willing to looking at something more verbose, then something like:
seems fairly obvious. Similarly,
also seems fairly obvious (with something shorter -ispropnull also reasonably verbose). I currently handle the first with an infix if statement, e.g.:
The second is more complex, which I would love to replace:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
But I think that is more in the right direction, yeah. I rather like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @SteveL-MSFT To respond to your question asking if anyone has other syntax suggestions that wouldn't result in breaking changes, I was tinkering a little today, and wondered what if we look at As far as I can tell, these are non-breaking changes: # This references the Length member, but only if $x -ne $null
# (no . required, since there's already one at the bottom of the !, but
# we could use !. here if we really felt it was necessary)
$x!Length
# This references the item at index 2, but only if $x -ne $null
$x![2] That would be non-breaking. I also like the visual relationship between the dot-reference operator ( When comparing this with the other C# operators (ternary, null-coalescing, etc.), there's no conflict in thought and they are all explainable:
There is one overlap with C#, which has what is referred to in online discussions as the damnit operator (a postfix Also just to make it clear, I prefer sticking with the |
||
|
||
### Updates to operator precedence | ||
|
||
The operator precedence token flags will be updated to add gaps and place the null coalesce opeator at position 7, above comparison and below add/subtract. | ||
Currently, the binary operator mask is set at `0x07`, which will be updated to `0x0f`. | ||
This will ensure that `??` is evaluated before operators like `-eq`, `-and`, `-bor` etc, but after `+` and `-`. | ||
|
||
This enables scenarios like: | ||
```PowerShell | ||
'x' -eq $null ?? 'x' evaluates to 'x' -eq ($null ?? 'x') | ||
|
||
2 + $null ?? 3 evaluates to (2 + $null) ?? 3 | ||
``` | ||
|
||
### Additional considerations | ||
|
||
The `??=` and `??` operators are binary operators and check for the value of the left hand side to be null or an undefined variable. | ||
They can be used with a space between the variable name and the to operator. | ||
If the left hand side is null, then `??=` assigns the right hand side to the variable while, the `??` operator returns the right hand side. | ||
When they are used without a space between variable name and the operator, a `{}` must be used around the variable name. | ||
|
||
## Alternate Proposals and Considerations | ||
|
||
### Disallow `?` in variable names | ||
|
||
It was considered to disallow `?` in variable names, to avoid confusion whether the operator is a null conditional operator or the variable name has `?` in it. | ||
This proposal was rejected to maintain backward compatibility. | ||
|
||
### Prefer new operators when tokenizing variable names | ||
|
||
It was considered to look ahead when tokenizing the variable names and check for `??=`, `??`, `?.` or `?[]`. | ||
If the token is found the assume that it is a null conditional check and not a member access of a variable name ending in `?`. | ||
To maintain backward compatibility and this proposal was rejected. | ||
|
||
### Use a different sigil for null-conditional operators | ||
|
||
It was determined that the familiarity of `?.` and `??` operators to `C#` programmers will make usage of the new operators easier to understand than introducing new sigils | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ExE-Boss which likely took inspiration from C# considering that syntax and feature existed 5-10 years prior. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not be put in the alternate proposal section. The null-conditional operator should be put in a separate RFC given that it's a experimental feature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved it to the "specification" section.