-
Notifications
You must be signed in to change notification settings - Fork 1k
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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
Proposal: Ternary comparison operator #4108
Comments
It was noted that there is a NuGet package which uses an extension method and some overloaded operator chicanery to mimic this language feature: dotnet/roslyn#136 (comment) However, if the compiler will only treat this expression as a range comparison if it wouldn't otherwise compile then I would imagine any existing code that might rely on this package would continue to compile and work as expected. But it should probably be included as a part of the test suite to ensure no unintended breaks. |
Good to know. This would fall under the portion of the design of: we will existing semantics and always interpret that way if it succeeds. We only use the new semantics if it doesn't. That example is also interesting in that it's trying to provide these semantics. So a great part about this is that once we have this feature, you can stop using that lib :) |
How would this be defined to avoid making further changes to binding not overly complex? For example if C# adds increases the number of places implicit operators can be used in the future, or changes lookup, or improves overload resolution, we would need to make sure all those things run only after we check if it matches this new ternary comparison operator. This might force the binding code to become very contorted to allow this. |
honestly, i would say: given an tree of the form
We have the existing rules. We then have a clause htat says that if that produces an error (which we use terminology for in lambda-resolution) then rebind with such-and-such expected semantic rewrite. In general we discuss validity, and binding-time errors. This would apply here. If the normal interpretation results in an invalid (or binding-time-error), we try the new interpretation. I'm not sure any of the cases mentioned so far necessary matter. Or, if they do, they are starting to get to the cornerest corner of all corners :) |
Linking back to my comment here #4106 (reply in thread) Since you're going to deal with some semantic ambiguities anyways, the postfix pattern does seem to be a viable alternative, except that there will be syntax ambiguities instead (but not in any useful scenarios mentioned here). Opened a new discussion: #4110 |
很好 |
Can there be a warning wave when bindinh to the old behavior? |
I don't see any point in doing that |
There may be some ambiguities need to be resolved, such as |
Wouldn't this potentially break compatibility? Those operators are not guaranteed to represent comparisons. the user is free to give them different semantics. |
This would have to be under a feature flag, so that the change in semantic doesn't change errors in previous version. Can work just via the binder and lowering.
I wrote that nuget package. Note it use |
Compatibility concerns are fully addressed in the OP, no? |
No. The specification can effectively be read to say: If this has legal semantics under C# 9. The use those semantics. Othewise, try the new semantics. So nothing can break. |
OP doesn't mention if |
Your package will retain its semantics. |
It can operator on different types as per the rewrite rule i've specified. The rule is agnostic to that. |
@CyrusNajmabadi Are you restricting to the "comparison" operator only if it returns
|
No |
Any existing semantics would be preserved. the general intuition for the algorithm is:
|
With C# 9 it can be written |
No, because, Pattern Matching works only with constant, and with this proposal, it could works with any value (variables, properties, …) |
We have <= and => today, tell me they are the same thing. |
What ambiguity is in that fragment? Creating the parse tree for that is not ambiguous so far as I can see. |
It would need appropriate lookahead to ensure that generics, variables, and comparisons were properly handled. It's likely not a full ambiguity, but a local one. |
Is it |
Yes I see that when there's no context, but in the case of an A declaration isn't legal (well I can't see it myself) inside the expression that's part of an C# seems to already parse this correctly too: int A = 0;
int B = 0;
int C = 0;
int D = 0;
int F = 0;
if (A<B<C>D>F)
{
;
} The diagnostic it reports is not about syntax but a semantic problem, the types that are used either side of the operator This too suggests that if the semantic checking were replaced, the expression interpreted as a chained compare, it would work. |
As far as I can test, the compiler is already happy with that syntax |
Yes. This is an example of us addressing the potential issue. The situations brought up are there so we ensure we think through it and make sure the language is spec'ed such that it is not an issue and so that the compiler operates as expected with appropriate tests. |
I really don't understand this. There is also ambiguity with another ternary operator |
What ambiguity are you referring to?
No one said we are not fine with ambiguities... As i said in the post above yours, we would just need to be cognizant so we can spec hte language out properly, and ensure the compiler does the right thing. |
what does a? b? c: d: do and what does a < b < c < d do. both ambiguous . () needed to fix this |
The code is incomplete and will be a failure to parse. Did you miss a Assuming it's accidental, and you meant: Can you please clarify? |
Currently it is syntactically legal, and may have semantic meaning in esoteric cases. This proposal discusses giving it legal meaning in the case where it is illegal today. |
Random concerns:
|
My thought here is that this is shorthand for
Looks like the space for an optimization pass, or an analyzer message. Not really in scope for the language itself.
That seems reasonable. We already do constant analysis and requisite flow control for similar htings today: So this could similarly evaluate to always being false (if 'a' is an integer of course). |
C++ is also looking to add this; albeit with disallowing the potentially ambiguous forms like |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Ternary comparison operator
Summary
This would allow users to write a simplified
x < y < z
test as shorthand forx < y && y < z
.Detailed design
This code is already parseable today and already has meaning. Indeed, here is a (albeit pathological) case where this would compile today:
In order for this type of code to compile today, you'd need to do very strange operator overloading which would not be expected in practice. However, because of back compat, we would likely have to support this.
As such, when processing a binary expression of hte form
expr1 op expr2 op expr3
we would have to bind in the same fashion as today. However, if that form failed to bind the operators successfully, we would now reinterpre the above as:expr1 op1 expr2 op2 expr3
, whereop1
andop2
are one of>
,<
,>=
,<=
is reinterpretted as:This should match intuition here and would mean code executes (including order of evaluation and short-circuiting) as expected.
Drawbacks
Potential confusion over a piece of code potentially having two different meanings. However, this is so unlikey as no real codebases should ever have been using
a < b < c
. It just isn't a reasonable code pattern today, so no one uses it or expects it to work the way it does today. Practically all users looking at this would expect it to have the semantics this proposal is suggesting.Design meetings
The text was updated successfully, but these errors were encountered: