Champion "range patterns" #8783
Replies: 67 comments
-
Why use a new syntax here, |
Beta Was this translation helpful? Give feedback.
-
aren't range exclusive? (and they're a value, not a pattern). This wants to be inclusive right? |
Beta Was this translation helpful? Give feedback.
-
If we ever get inclusive ranges, I'd expect the same syntax for range patterns. |
Beta Was this translation helpful? Give feedback.
-
For floats, how would you match exclusively? |
Beta Was this translation helpful? Give feedback.
-
Wouldn't inclusive/exclusive always be about if you're doing |
Beta Was this translation helpful? Give feedback.
-
Yep, so it's useful to be able to pick. |
Beta Was this translation helpful? Give feedback.
-
The old dilemma double v = 1.0;
switch (v) {
case in 0 to 1.0: Good(); break;
case in 1.0 to 2.0: NotSoGood(); break;
default: break;
} |
Beta Was this translation helpful? Give feedback.
-
you'd probably get a subsumption error for that? |
Beta Was this translation helpful? Give feedback.
-
I think there should be both |
Beta Was this translation helpful? Give feedback.
-
@alrz but how would you avoid it? |
Beta Was this translation helpful? Give feedback.
-
Is there also a way to create a System.Range with this syntax? I really think that one of the overall goals of putting patterns into C# should be construction/deconstruction symmetry. I know that this is var r = 1 to 10; Because, currently, if I want the range of numbers from 1 to 10 I will have to write var r = 1..11; which makes me shudder. |
Beta Was this translation helpful? Give feedback.
-
Why not just be explicit about it:
This can play nicely with custom types as well. |
Beta Was this translation helpful? Give feedback.
-
@orthoxerox |
Beta Was this translation helpful? Give feedback.
-
I don't see any difference between But then again we actually could use case int i when i > min && i <= max:
break; |
Beta Was this translation helpful? Give feedback.
-
One advantage of the range pattern is it makes it easier for the compiler to verify that all cases have been dealt with. |
Beta Was this translation helpful? Give feedback.
-
So, assuming var letterGrade = gpa switch {
> 3.0 => "A",
> 2.0 and <= 3.0 => "B",
> 1.0 and <= 2.0 => "C",
> 0.0 and <= 1.0 => "D",
_ => "F"
};
I |
Beta Was this translation helpful? Give feedback.
-
@HaloFour I don't think we should complicate the most common use case (inclusive range) just to support any possible combinations of operators? In case you want to simplify multiple I'm not against relational patterns (although I expect less usefulness vs. say user-defined patterns) but I think range patterns would be still useful when you just want a simple range match. |
Beta Was this translation helpful? Give feedback.
-
@alrz I think simple range is not actually simple. We need to remember its half open behaviour and thus we could confuse sometimes. Relational patterns always make it obvious for everyone include newbie even it a little more verbose |
Beta Was this translation helpful? Give feedback.
-
@thania "range patterns" as originally proposed here are inclusive, and they are that way in every language I checked. there's nothing to be confused about when you say you can rewrite |
Beta Was this translation helpful? Give feedback.
-
@alrz Sure but as of we discussed so long. I think now we should drop the original |
Beta Was this translation helpful? Give feedback.
-
@alrz Sorry but ranges in matlab are inclusive but in python are exclusive (half open). |
Beta Was this translation helpful? Give feedback.
-
After I see a relational pattern. I have imagine that, what if we allow pattern as a shorthand for Today we write int[] items;
items.Where((item) => item >= 0 && item < 10); Maybe we could int[] items;
items.Where(>= 0 and < 10); More than that int?[] items;
items.Where({}); // not null pattern
SomeObject[] objs;
objs.Where({ value: >= 0 and < 10 }); // obj has field value and obj.value >= 0 && obj.value < 10 |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
@Joe4evr That's right. But only allowing pattern as items.Where(@ >= 0 && @ < 10);
// vs
items.Where(>= 0 and < 10); |
Beta Was this translation helpful? Give feedback.
-
It's a single character difference, and I disagree that it's the most common use case. I posit that LINQ/EF against POCOs are the most common use case. |
Beta Was this translation helpful? Give feedback.
-
I wrote This in #2268 static string Quadrant(Point p) => p switch
{
(0, 0) => "origin",
(var x, var y) when x > 0 && y > 0 => "Quadrant 1",
(var x, var y) when x < 0 && y > 0 => "Quadrant 2",
(var x, var y) when x < 0 && y < 0 => "Quadrant 3",
(var x, var y) when x > 0 && y < 0 => "Quadrant 4",
(var x, var y) => "on a border",
_ => "unknown"
}; I wondered if it can be shorter and more readable to achive the purpose of pattern matching, so I suggest this: static string Quadrant(Point p) => p switch
{
(0, 0) => "origin",
(> 0, > 0) => "Quadrant 1",
(< 0, > 0) => "Quadrant 2",
(< 0, < 0) => "Quadrant 3",
(> 0, < 0) => "Quadrant 4",
(_, _) => "on a border",
_ => "unknown"
}; @HaloFour siad this proposal would achieve this, so I am a fan :) |
Beta Was this translation helpful? Give feedback.
-
This is a special case of 'Active Patterns' (which we don't have and I can't find a proposal for them). I'd rather have active patterns in the language, and some helpers in the library. static string Quadrant(Point p) => p switch
{
(0, 0) => "origin",
(GT(0), GT(0)) => "Quadrant 1",
(LT(0), GT(0)) => "Quadrant 2",
(< 0, < 0) => "Quadrant 3", // With custom operators (orthogonal feature) [1]
(GT(var x, 0), LT(var y, 0)) => $"Quadrant 4: x: {x}, y: {y}", // `GT` et al. are (overloadable) patterns.
// the `pat(var x)` form lets the pattern expose a value/ref through a new name
// while other expressions are just passed as if arguments to a function.
(_, _) => "on a border",
_ => "unknown"
}; If we ever get custom operators, we get exactly the proposed syntax ([1]) for free. The features are then separate. |
Beta Was this translation helpful? Give feedback.
-
FWIW in asn.1 you can specify both inclusive, exclusive and half open ranges the syntax seem to work pretty good.
exclusive this way
half open excluding max
half open excluding min
|
Beta Was this translation helpful? Give feedback.
-
To keep the dots in order to make range-related syntax consistent, I'd propose the following options. Change Current Meaning and Extend With Colons
Change Current Meaning but Keep Dots
Keep Current Meaning and Extend With Dots
Keep Current Meaning and Extend With Colons
The formal mathematical equivalencies are displayed after the equal signs. The colons or extra dots essentially act as range endpoint augmenters, pulling the range endpoint in the metaphorical left or right direction for more strict or less strict on the left and less strict or more strict. Example with First OptionDefaultSyntax: Outer Left Pulled LeftSyntax: |
Beta Was this translation helpful? Give feedback.
-
I am withdrawing my championship of this issue in favor of #812 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
The idea is to have a pattern with a syntax like
Which matches input primitive values that are
>=
the first constant expression and<=
the second constant expression.An alternative is to have relational patterns, which would be a pattern like
<3
:I (@gafter) think I prefer the alternative of relational patterns, especially in conjunction with pattern combinators like
and
.Beta Was this translation helpful? Give feedback.
All reactions