Replies: 83 comments
-
In my opinion:
And my own suggestion: range operator should be applicable to all types that support |
Beta Was this translation helpful? Give feedback.
-
Previous discussion: dotnet/roslyn#7632. for (var i in 5..10) Should this have been |
Beta Was this translation helpful? Give feedback.
-
Taking a page from Rust, there could be also a syntax for "open" ranges, |
Beta Was this translation helpful? Give feedback.
-
There is very nice notation in mathematics for open and closed intervals.
Unfortunately square and round brackets are not suitable for C# syntax. |
Beta Was this translation helpful? Give feedback.
-
@alrz What happens when you iterate left-open range? If I understand it correctly, in Rust, both kinds of open ranges are separate types and left-open range is not iterable. |
Beta Was this translation helpful? Give feedback.
-
@svick I think so. That's particularly useful in slices and patterns. |
Beta Was this translation helpful? Give feedback.
-
Yes, thanks for catching that. Will fix. I tend to agree. What's more this |
Beta Was this translation helpful? Give feedback.
-
Do not think this is worthy feature. There is low demand for fixed integer ranges, and also for other types. Also, expanding such synetax for even less popular cases, is even more unjustified. Simply, too much resources for too small problems. |
Beta Was this translation helpful? Give feedback.
-
A range operator of sorts is likely given the championed proposal to add slicing to the language. Given such it is worthwhile to explore the syntax and capabilities of that operator both inside and outside of the context of slices. Fixed ranges of integers are still pretty common, and using a range operator to describe them makes sense. Apple even completely removed the classic C |
Beta Was this translation helpful? Give feedback.
-
For the case of variables (7), what should happen if |
Beta Was this translation helpful? Give feedback.
-
Good question. I added it to the list of questions above in the discussion. |
Beta Was this translation helpful? Give feedback.
-
I would argue that we don't need it to be operator. Just extension method is enough public static class Ext
{
public IEnumerable<int> To(this int start,int end)
{
var sign = Math.Sign(end - start);
while(start != end)
{
yield return start;
start += sign;
}
yield return start;
}
}
foreach(var i in 3.To(5)) // (3..5)
{
} (ported from previous issue) Also we could easily make similar function for exclusive
|
Beta Was this translation helpful? Give feedback.
-
An empty range, and a warning if it's known at the compile time i.e. via constant bounds. |
Beta Was this translation helpful? Give feedback.
-
Because the default step is 1, and in slices it doesn't make sense. |
Beta Was this translation helpful? Give feedback.
-
@jcouv The operator |
Beta Was this translation helpful? Give feedback.
-
@ufcpp Fantastic data points. Thanks! Glad to see the binary search approach does work. The code is harder to read than I expected though. I feel like code generation is probably a good fit in case the switch needs to be updated (I suspect that's what you did to test it out). Yes, such optimizations are more suitable for roslyn repo. Please do file an issue with the experiments you collected. As far as planning, there is a significant rework for patterns (to support recursive patterns) which is starting. Optimizations based on completeness and exclusivity would probably come after that. |
Beta Was this translation helpful? Give feedback.
-
Debug (
Release (
|
Beta Was this translation helpful? Give feedback.
-
@jcouv Yes, these codes are code-generated. The generator is here: https://github.com/ufcpp/GraphemeSplitter/blob/master/GraphemeBreakPropertyCodeGenerator/Program.cs |
Beta Was this translation helpful? Give feedback.
-
In addition, it requires 50 seconds to compile the 20 thousand-line switch-case. (My PC is Core i7-4790 3.60GHz.) |
Beta Was this translation helpful? Give feedback.
-
My vote... I pretty much agree with @orthoxerox.
Agree: Let's not reuse the
Agree again: Perl-style is clear and doesn't conflict with any existing C# notation.
Partly agree: I'm not too enthousiastic about the exclusive operator. Maybe again something hard to handle in optimization.
Agree: That makes the syntax more fishy...but we can make this Range constructor accept a step or stride:
This time: Not for me. Again a performance issue. In case the range is not constant, we must check if the boundaries values are positive, yield perfomance impact.
This syntax would be nice: // exit the awkward C-stype for-loop:
foreach (int i in 0..10) { ... }
// Let's keep it consistent in if:
if (myvar in 0..10) { ... }
// Let make it in switch/case:
switch (myvar) {
case 0..10: {...}
break;
}
Yes. definitly
Would be nice. Although I don't think we could map it to the same Range type then as defined as in 1. (performance, again).
This should result in an empty range. Again, this choice is driven for a performance concern. for (int i=start; i <= end; i++) { ... }
foreach (int i in start..end) { ... } Why do I care so much about performance ? I really want the lazy/readable/sweet code to be as efficient as the verbose ancestral way to do it. Otherwise... It will just be a feature for dummies... IMHO, I think the ultimate goal of this is to be able to write such a code, with the help of var myvar = new mytype[10];
...
myvar[2..4] = othervar[1..3]; |
Beta Was this translation helpful? Give feedback.
-
Should this be true even for
be an infinite loop? |
Beta Was this translation helpful? Give feedback.
-
@vladd: I agree it's not ideal, but I still prefer that solution than adding a boundary-safe condition that would grow with a O(n) complexity with the loop, just in case we hit the int.MaxValue. We already accept that the arithmetic around the corners requires user-awareness for the even simpler expressions like: You seem to have this awareness. So honestly, if you would know that the use of |
Beta Was this translation helpful? Give feedback.
-
The best way is to have upper bound exclusive. var a = new int[] {/*1,2,3,4,5*/}
var len = a.Length
var al = a[ .. len/2]
var ah = a[ len/2 .. ] // al.Concat(ah) = a
var aWithoutLast = a [ .. len-1 ] inclusive (you need to substract 1 all the time) var a = new int[] { }
var len = a.Length
var al = a[ .. len/2-1 ]
var ah = a[ len/2 .. len-1 ] // al.Concat(ah) = a
var aWithoutLast = a [..len-2] |
Beta Was this translation helpful? Give feedback.
-
Regarding using ranges in patterns, I think I'd prefer an explicit 'in' pattern:
All our other patterns (const pattern, type pattern, var pattern) are all things which are the same type as the input, and we're doing an 'is' check on those. Using a bare range makes it look superficially like a const pattern, but it acts like a completely new type of pattern (doing an 'in' check instead of an 'is' check). (I think this would also be clearer if we ever wanted to extend the switch pattern in future, to use any (non-const) collection object, instead of just a range literal:
whereas I think just Also, using a bare range could make switching on a range confusing:
since there presumably the case pattern should be interpreted as a const pattern, rather than a range pattern? Seeing how patterns can be used in if statements too, this would give us |
Beta Was this translation helpful? Give feedback.
-
I understand the benefits that go with the upper bound being exclusive but the syntax throws me off every time. Expanding, e.g, 3..6 in my head leads to 3, 4, 5, 6. |
Beta Was this translation helpful? Give feedback.
-
I'll never understand the decision to make the range exclusive of the upper bound... I mean, the off-by-one issue is the very reason for introducing a "from end" index. I think it's a pretty narrow view to look at ranges as applying to slicing only (which, let's be honest, is the only place where exclusive ranges make sense). What other language out there has only exclusive ranges? |
Beta Was this translation helpful? Give feedback.
-
My understanding is that the |
Beta Was this translation helpful? Give feedback.
-
@HaloFour If it would be a language feature, especially syntax, then it should be generalize and synergize with similar purpose. Or at least the same pattern. So we would not have similar feature with very difference syntax |
Beta Was this translation helpful? Give feedback.
-
And they still messed this up, IMO. 🙄 |
Beta Was this translation helpful? Give feedback.
-
[Editor's note: this is a discussion regarding championed proposal #185. -@gafter]
Summary
I propose a general purpose range operator which can be used to obtain a range a integral values. This range can then be used in loops, patterns or slices:
Questions
Updates:
foreach
loop exampleBeta Was this translation helpful? Give feedback.
All reactions