Skip to content
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

Champion "slicing" / Range (16.3, Core 3) #185

Open
2 of 5 tasks
gafter opened this issue Feb 26, 2017 · 297 comments
Open
2 of 5 tasks

Champion "slicing" / Range (16.3, Core 3) #185

gafter opened this issue Feb 26, 2017 · 297 comments
Assignees
Labels
Implemented Needs ECMA Spec This feature has been implemented in C#, but still needs to be merged into the ECMA specification Proposal champion Proposal
Milestone

Comments

@gafter
Copy link
Member

gafter commented Feb 26, 2017

Introduce a .. syntax, such that x..y ends up creating a Range of x and y.

See also

@gafter gafter added this to the 7.2 candidate milestone Feb 26, 2017
@Thaina
Copy link

Thaina commented Feb 27, 2017

Do we still need this feature while we have return ref support?

We could just create readonly ref collection couldn't we?

struct ReadonlyRefCollection<T>
{
    T[] array;
    int slice,length;
    public ref T this[int i] { get => ref array[i] }
}

@gafter
Copy link
Member Author

gafter commented Feb 27, 2017

@Thaina Slicing may end up being just that, though it is possible we will want a special syntax for taking a slice, like e[a:b].

@Thaina
Copy link

Thaina commented Feb 27, 2017

@gafter Thanks for answer

but then I would disagree for adding syntax just for that

Extension method array.Slice(from,to);or array.Slice(from,count); would be sufficient and more familiar

@chrisaut
Copy link

Would the runtime be smart enough to know it can collect/free parts of eg. an underlying array that is not in a slice? In other words, if I have

var arr = new int[HUGE];
var slice = arr[500:1000];
// assume arr is no longer referenced anywhere except through slice, will it keep holding entire arr alive?

I assume there are huge complications with object headers that would make this very complicated. But it sure would be nice.

@iam3yal
Copy link
Contributor

iam3yal commented Feb 27, 2017

@chrisaut The way I read it is a slice is a view over an existing array so I think that arr must be alive in order to manipulate it; otherwise, you may need to make a copy of the slice.

@iam3yal
Copy link
Contributor

iam3yal commented Feb 27, 2017

@Thaina str[a:b] reads a lot nicer than str.Slice(a, b) but if you don't like that you could use the API directly. :)

@Thaina
Copy link

Thaina commented Feb 27, 2017

@eyalsk Sorry to say that I think completely opposite. It not intuitive at all to assume that array[10:100] means slice it out. It also not sure that what 100 mean count or endIndex. In C# we never use a:b to mean range of number before

On the contrary we had string.Slice to be familiar with

@Thaina
Copy link

Thaina commented Feb 27, 2017

@chrisaut I think it would be too hard to determined if resizing array, which involve copy and clearing memory, would yield performance when it really necessary. Too many scenario compiler need to do guesswork

such as, what if the sliced array will also dispose in the next minute? Then it no point to waste time dispose the old one anyway

Developer could just explicitly optimized by manually resize

@MovGP0
Copy link

MovGP0 commented Feb 27, 2017

In case special syntax is needed, I suggest to use the range operator from Pascal, which is .., because it is more closely to the operator in mathematics (unicode character 'horizontal ellipsis'). So instead of e[a:b] we would write e[a..b].

The a..b could map directly to Enumerable.Range(a, b-a).

@chrisaut
Copy link

@eyalsk @Thaina I'm not talking about making copies, slices should absolutely under no circumstance require copying of data, that's their entire point.

I'm talking about making the runtime smart enough to understand, that a given array only has ranges x-y reachable.

An array is basically a bunch of header info, followed by a block of memory.
A slice is a view over this bunch of memory, at a specific offset. If the slice's header itself contains header info such as underlying type, lengths etc., then the original array's header would no longer be needed.

If the GC understood that for arrays (and maybe other types later), before reclaiming it has to check some state somewhere to see if any slices are holing onto it, it could understand that only a small region is "alive" and free the rest.

This is just a rough idea.

@Thaina
Copy link

Thaina commented Feb 27, 2017

@chrisaut Slice itself never need to copy, unless it trying to do what you want, resize it

To have the mechanism you said, partially return memory to the pool, involve CLR optimization. Not about language or compiler

@iam3yal
Copy link
Contributor

iam3yal commented Feb 27, 2017

@chrisaut Where did I say that slices are about making copies? please reread what I wrote.

@iam3yal
Copy link
Contributor

iam3yal commented Feb 27, 2017

@Thaina

In C# we never use a:b to mean range of number before

There's always first time...

We didn't have many things in C# and now we have them so it isn't really an argument, if you don't find the syntax pleasant to read then that's a different story. :)

@MovGP0
Copy link

MovGP0 commented Feb 27, 2017

I am also wondering what happens when the b in e[a:b] becomes b<a. Will the slice be counted backwards or will there be an exception?

Version 0
When b<a an exception is thrown.

int[] primes = new int[] { 2, 3, 5, 7, 9, 11, 13 };
int[:] a = primes[5:2]; // throws an exception
int[:] b = primes[1:0]; // throws an exception
int[:] c = primes[0:-1]; // throws an exception

Version 1
When b<a, it counts backward from element e[a] by b elements. This maps to primes.Slice(int from, int count).

int[] primes = new int[] { 2, 3, 5, 7, 9, 11, 13 };
int[:] a = primes[5:-3]; // A slice with elements {11, 9, 7} 
int[:] b = primes[1:-2]; // A slice with elements {3, 2} 
int[:] c = primes[0:-1]; // A slice that yields {2} and then throws an exception

Version 2
When b<a, it counts backward from element e[a] to element e[b]. This maps to primes.Slice(int from, int to).

int[] primes = new int[] { 2, 3, 5, 7, 9, 11, 13 };
int[:] a = primes[5:2]; // A slice with elements {11, 9, 7} 
int[:] b = primes[1:0]; // A slice with elements {3, 2} 
int[:] c = primes[0:-1]; // A slice that yields {2} and then throws an exception

@Thaina
Copy link

Thaina commented Feb 27, 2017

@eyalsk Well, that's why most of the time I would like to recycle keyword more than add new

And as I said, it's not that we can't. I just argue that it not intuitive because we never have it. Compare to what we already have, a slice function

@iam3yal
Copy link
Contributor

iam3yal commented Feb 27, 2017

@chrisaut Just to make it crystal clear, what I meant is that if you no longer need a reference to the array but you still want to have the slice around then I think that you will need to make a copy of the slice, just a hunch based on my understanding, I could be wrong.

@chrisaut
Copy link

@eyalsk I understand what you said to mean that for what I want, slices would need to copy. I don't think it does. Apologies if that's not what you want.
I agree with you that in the normal/straight forward approach you need to copy if you no longer want the array, but only the slice. I'm actively questioning if we can make it so that that is not needed.

@Thaina yes of course it would require clr/gc work, but many new features would require that. I'd guess slices in general will need runtime support (regarless of the partial freeing) as slices are not just a new Type.

@iam3yal
Copy link
Contributor

iam3yal commented Feb 27, 2017

@Thaina async/await is intuitive? pattern matching is intuitive?

@Thaina
Copy link

Thaina commented Feb 27, 2017

@eyalsk Well, intuitive relative to what? I was talking slice comparing between string.Slice and that f:t syntax

Actually I would argue that many feature of pattern matching is also really not intuitive. I was propose alternative many times but I am not contributor so my voice is not important

But still many feature of pattern matching are intuitive. such as case. But if it me I would use switch instead of introducing match

But the point is many feature in pattern matching have nothing to comparing to. So add new one is not necessary to be intuitive

But async/await is good example. It is really more intuitive to write code than callback. You can write a loop intuitively just add await

I would also argue that we should not need await and should only have async keyword in Task, like yield can be used in IEnumerable without special syntax

But as I said, intuitive is relative. async/await still more intuitive than callback. But f:t is less intuitive than Slice in my opinion

@iam3yal
Copy link
Contributor

iam3yal commented Feb 27, 2017

@chrisaut

I'm actively questioning if we can make it so that that is not needed.

Just to cite the relevant part from the proposal:

As demonstrated in this code example, slicing wouldn’t make a copy of the original data; rather, it would simply create an alias for a particular region of the larger range. This allows for efficient referencing and handing around of a sub-portion of an array without necessitating inefficient copying of data. However, if a copy is required, the ToArray method of Slice could be used to forcibly introduce such a copy, which could then be stored as either an array or as a slice (since arrays implicitly convert to slices):

Therefor, I wouldn't expect any clever tricks here but I could be wrong. :)

@Thaina
Copy link

Thaina commented Feb 27, 2017

@eyalsk I think what @chrisaut means is.

If we have alloc memory for array, suppose from ptr0 to ptr50

Then we slice it at ptr20 to ptr30 and then stop using the original array

CLR could dealloc ptr0 to ptr18 and ptr31 to ptr50. And maybe the implementation of slicing array could force CRL to check that

But I don't think CLR can do thing like this

@iam3yal
Copy link
Contributor

iam3yal commented Feb 27, 2017

@Thaina

intuitive relative to what?

Intuitive relative to the person, many language constructs require some learning so this wouldn't be any different, especially when the person has no prior knowledge.

Actually I would argue that many feature of pattern matching is also really not intuitive. I was propose alternative many times but I am not contributor so my voice is not important

Thaina being a Contributor doesn't mean "anything" and your voice is as important as mine.

But async/await is good example. It is really more intuitive to write code than callback. You can write a loop intuitively just add await

It's straightforward to create asynchronous methods but it isn't straightforward to understand how asynchronous code works and what it means, especially for people that never did such work before.

My point being is that there's a bit of learning to do before you can use a feature and not so much about how it can be more intuitive...

@Joe4evr
Copy link
Contributor

Joe4evr commented Feb 27, 2017

I am also wondering what happens when the b in e[a:b] becomes b<a.

Existing methods in the BCL that have similar behavior (such as string.Substring()) have the arguments startIndex, length. I would hope that this convention carries forward to slices as well.

@Thaina
Copy link

Thaina commented Feb 27, 2017

@eyalsk

Intuitive relative to the person

Not at all. Relative is objectively compare with existing things. Even leaning curve is also relative to what exist and what newly introduced

being a Contributor doesn't mean "anything" and your voice is as important as mine

Disagree. people who not being contributor might be important but I never see it will be the same importance as contributor

It's straightforward to create asynchronous methods but it isn't straightforward to understand how asynchronous code works and what it means, especially for people that never did such work before.

Still the same word, relative. If there are newbie learning C# there are callback function and async/await we can present to let them learn how to do asynchronous. async/await has less learning curve compare to callback function that not straightforward

My point is comparing learning curve with similar feature is necessary. And I would vote that we should better use array.Slice more than array[f:t] because it more intuitive and familiarity

@iam3yal
Copy link
Contributor

iam3yal commented Feb 27, 2017

@Thaina

Not at all. Relative is objectively compare with existing things. Even leaning curve is also relative to what exist and what newly introduced

And a person isn't a thing?

Disagree. people who not being contributor might be important but I never see it will be the same importance as contributor

Thaina... let's not get into the meaning of a Contributor when it's pretty well defined and has absolutely nothing with the subject.

And I would vote that we should better use array.Slice more than array[f:t] because it more intuitive and familiarity

Thaina you would still have the ability to use the API directly.

I understand that you don't like the syntax but what do you think about the syntax that was proposed by @MovGP0? personally I find the proposed syntax : pretty nice.

@MovGP0
Copy link

MovGP0 commented Feb 27, 2017

i am totally happy with the : syntax. Just would argue that the .. syntax can be used more universally like in

foreach(var item in 3..5){ /* 3,4,5 */ }

foreach(var item in a[3..5]){ /* a[3], a[4], a[5] */ }

@Thaina
Copy link

Thaina commented Feb 27, 2017

@eyalsk

Thaina... let's not get into the meaning of a Contributor when it's pretty well defined and has absolutely nothing with the subject.

As always you are the one who pick the word to argue with me. So you stop yourself not telling me to stop what I don't start

Thaina you would still have the ability to use the API directly.

If that's your argument then you would never ever come mess with my threads in the past. Remember when you annoyingly mock me when I try to introduce delete keyword? Why you not just think that you could still use dictionary.Remove?

To introduce new syntax have many cost and drawback or else we would have all syntax we could imagine already. Same here that you like this syntax so you want it and I'm against it because it make code more weird and cost too much for little benefit

I know why you try to argue with me in the past even you make fun of me in every aspect and make our argument become silly. You should understand yourself too

@verelpode
Copy link

How would you indicate a range of all elements, then? With the current proposal it's array[0..^0].

The current proposal already supports Range.All:

Range r = Range.All;
Span<char> s = ...;
Span<char> s2 = s[r];

I'd find it wildly unconvincing if anyone claims that the obscure sequence of symbols [0..^0] is superior to the completely unambiguous, descriptive, non-controversial Range.All. Is anyone genuinely claiming in all seriousness that those obscure symbols are better than Range.All? Not speaking about you in particular; just speaking generally here, there is a big difference between a desire to find the best solution versus an extreme fanatical wish to justify one-and-only-one particular design. In my case, it's evident that I'm not fanatically trying to justify one particular design because I acknowledged @Thaina's insight and acknowledged that a logical negative indexing design is within the realm of possibility, just not with the ^ operator. This proposal should be guided by the desire to find the best solution, whatever that may be, and not to jump through hoops to find and latch onto any excuse to avoid acknowledging that the proposal is not yet ready to be set in concrete forever in C# 8.0.

Surprisingly multiple people already turned this ordinal topic into a heated religious-style debate, which suggests that more time and more research is needed to clarify the situation. I do completely understand that it's frustrating to delay it to C# 8.1, but even more frustrating would be if a mistake is set in concrete forever in C# 8.0, especially if it triggers years and years of never-ending heated religious-style debate.

It may well be possible to alter the design in a way that satisfies both camps, so it'd be a pity if this feature is released too early to allow that to happen.

XOR is a binary operator.

oops, re arity, I mixed up ~ with ^, but ofcourse you're right, ^ is arity 2 whereas ~ and - are arity 1. This wasn't mentioned at all in the info I read. It also doesn't solve the problem that ^ intuitively means reverse-0-based rather than Pascal-reverse.

@HaloFour
Copy link
Contributor

HaloFour commented May 6, 2019

@verelpode

The current proposal already supports Range.All:

Yes it does, but that assumes you know at that point that you need a full range. You can construct a range from arbitrary indexes and another part of the program may be determining that the end index is ^0, which makes the use of Range.All impossible, and still leaves you requiring a way to specify an end that includes the last element.

there is a big difference between a desire to find the best solution versus an extreme fanatical wish to justify one-and-only-one particular design.

The team has posted their meeting notes and discussed at some length how and why they came to the decision that they did. Framing it as some dichotomy between "best solution" vs. "extreme fanatical wish" demonstrates that you're not interested in a practical solution and is not at all a constructive avenue of dialog. The team didn't rush in with "oh it must be ^ and it must end at 1!"

@verelpode
Copy link

@HaloFour

Framing it as some dichotomy between "best solution" vs. "extreme fanatical wish" demonstrates

Well I'm sorry that my message came across like that, because that wasn't my intended meaning. I was trying to say in general that fanaticism is a problem that pops up sometimes, but I wasn't intending to say that it happened in this case, and I wasn't speaking about you. Maybe I failed to sufficiently clarify the part where I wrote "just speaking generally here".

another part of the program may be determining that the end index is ^0, which makes the use of Range.All impossible, and still leaves you requiring a way to specify an end that includes the last element.

Unfortunately I don't understand your point because you seem to be saying there is a lack of a way to specify an end, whereas I see that the proposal already includes Range.End. If I didn't misunderstand you, then here is an example of doing what you described using the current version of the proposal:

Range r;
Index startOffset;
if (CalculateSomething(out startOffset))
    r = new Range(startOffset, Range.End);
else
    r = Range.All;
Span<char> s = ...;
Span<char> s2 = s[r];

@HaloFour
Copy link
Contributor

HaloFour commented May 6, 2019

@verelpode

Unfortunately I don't understand your point because you seem to be saying there is a lack of a way to specify an end, whereas I see that the proposal already includes Range.End.

Range.End is a property of an existing Range and it returns the index used for the end of the range. It doesn't return some sentinel meaning the end of a range. The Index value still needs to be something that can be specified and assigned to a variable and passed around independently of its use in a range.

@verelpode
Copy link

True, there is a mistake in my previous message. I incorrectly wrote Range.End instead of Index.End. Here is the corrected code:

Range r;
Index startOffset;
if (CalculateSomething(out startOffset))
    r = new Range(startOffset, Index.End);
else
    r = Range.All;
Span<char> s = ...;
Span<char> s2 = s[r];

I shouldn't be trying to multitask, trying to discuss Range when actually I'm supposed to be working on something else this week. This multitasking leads to mistakes such as exchanging Range.End and Index.End.

@HaloFour
Copy link
Contributor

HaloFour commented May 6, 2019

@verelpode

Index.End is a synonym for ^0. You're free to use it if you prefer. But given that ranges are end exclusive there still needs to be a mechanism to refer to beyond the end of the array. That is what Index.End and ^0 do now, and when you use either the last element would be included in such a range.

When you get some free time you can feel free to engage the Gitter community, which is better suited for a conversation on the subject.

@verelpode
Copy link

Index.End is a synonym for ^0

Yes so re syntax, my point is that Index.End is better than ^0 and Range.All is much better than 0..^0. The ^ idea appears to be falling into the same mistake as what Perl did, although not as extremely as Perl. This mistake is also made by mathematicians unrelated to Perl. Wikipedia's Perl article says:

Criticism: Perl has been referred to as "line noise" by some programmers who claim its syntax makes it a write-only language.

Overuse of symbols and overloaded context-sensitive meanings of preexisting symbols aren't good techniques in the design of a language. It is not a credible argument to claim that 0..^0 etc are better than Range.All etc.

I really appreciated the improvements made in C# 7.x but this Range proposal bucks the trend. I'm sorry but the Range proposal really appears to be half-baked and not yet ready for C# 8.0. With some more work, it could become a great proposal, but it's not there yet. Major problems in the proposal include:

  • Treats ranges as if ranges are better than extents/spans but usually the reverse is the truth (some exceptions exist).
  • Could be revised to support BOTH extents/spans and ranges equally well, but this has not yet been done.
  • Pascal-style ordinals in reverse. Mix of 0-based and 1-based schemes.
  • Could be designed to support "Length minus i" ordinals in a clear manner but is currently designed in a confusing, inconsistent, and controversial manner.
  • Could support BOTH of reverse-ordinals and "Length minus i".
  • Inconsistent use of zero because zero refers to an existing element whereas ^0 does not refer to any existing element at all.
  • Confusing choice of symbol that suggests it means "reverse-0-based" but actually means something completely different.
  • Overloaded use of a preexisting symbol (XOR) in a context-sensitive manner.
  • Use of symbols in a case where English words are better, such as Range.All being better than 0..^0.
  • Some of the provided design justifications are not credible because they seem to be emotional decisions.
  • The documentation/descriptions are insufficient to allow people to properly evaluate the proposal. I see various struct members that have zero words of description, not even a single short sentence.

Thanks for suggesting Gitter and thanks for your replies. Overall the C# team has been doing a fantastic job, much appreciated, but nobody is capable of achieving 100% success rate, except for Superman, but he doesn't exist.

@HaloFour
Copy link
Contributor

HaloFour commented May 6, 2019

@verelpode

I'm sorry but the Range proposal really appears to be half-baked and not yet ready for C# 8.0.

Some of the provided design justifications are not credible because they seem to be emotional decisions.

You disagreeing with the proposal does not mean it's "half-baked" or not ready. Again, approaching the conversation like this is not productive. If you've already reached your conclusion without reading the relevant notes and are unwilling to consider other views then there's really nothing to discuss.

Ranges have been a topic of discussion for years and the team has posted their notes which includes all sorts of variations on syntax and behavior, much of which was cut. The primary motivation for indexes and ranges is to facilitate slicing, and the behavior is oriented towards that motivation. That does not preclude further additions to the feature to come in the future.

Treats ranges as if ranges are better than extents/spans but usually the reverse is the truth (some exceptions exist).
Could be revised to support BOTH extents/spans and ranges equally well, but this has not yet been done.

The existing APIs already support extents just fine, and if you consider Span<T> then quite a bit of language and runtime changes have been made recently specifically to facilitate them efficiently. If you have a specific language proposal then feel free to open an issue here. But whatever it is would certainly be orthogonal to supporting ranges.

Inconsistent use of zero because zero refers to an existing element whereas ^0 does not refer to any existing element at all.

Neither does .Length - 0. But if you need to stop before you reach a specific point you need a way to reference beyond the end.

Overloaded use of a preexisting symbol (XOR) in a context-sensitive manner.

Lots of symbols and syntax in C# have multiple meanings based on context. As mentioned by the team, they chose ^ arbitrarily due to not immediately seeing better options. If you feel you have a better option then feel free to post it. But the reasoning needs to be better than "I don't like that other choice," because I guarantee you someone also won't like your choice. The last time the team put the syntax for something up for a vote the feature was pointlessly delayed for a couple of years because the community couldn't even approach a consensus.

Pascal-style ordinals in reverse. Mix of 0-based and 1-based schemes.

This is consistent with from-end or negative indexing in other languages. It's also the easiest way to handle the clusivity and directionality concerns that are inherent with ranges. I'd be very interested in seeing other languages that went a different direction, I've yet to find one.

Use of symbols in a case where English words are better, such as Range.All being better than 0..^0

I personally don't find new Range(Index.FromStart(x), Index.FromEnd(y)) to be better than x..^y, but to each their own. There are people that argue that arithmetic operator overloading are too cryptic and terse too but I miss them everytime I have to write .plus(foo).minus(bar).times(baz) in Java.

but nobody is capable of achieving 100% success rate,

If every feature required unanimous support then the C# team would be currently achieving a 0% success rate. But their goal isn't to please everybody, it is to make pragmatic and long-term decisions that benefit the larger community.

@CyrusNajmabadi
Copy link
Member

Could be designed to support "Length minus i" ordinals in a clear manner but is currently designed in a confusing, inconsistent, and controversial manner.

There are no 100% solutions here. We know this because we tried several approaches, and there was confusion with some groups with any particular approach.

Furthermore, the approaches you seem to be suggesting would be inconsistent with the surrounding programming language ecosystem, which would be controversial in its own right.

You need to distinguish between choices that you believe would be optimal for you, versus choices that are desirable for the entire ecosystem.

@CyrusNajmabadi
Copy link
Member

Some of the provided design justifications are not credible because they seem to be emotional decisions.

Tough. The way the language is designed is not some: Feed inputs into Spock, and a logical result pops out.

Instead, it's a group of humans with tons of combined experience under their belts designing, implementing and using a whole host of languages. They consider lots of options, debate for ages, and finally settle on a result they collectively feel provides the best combination of Pros/Cons. This assessment is ultimately personal and comes down to individual beliefs of relative value. You wanting that personal approach to not be here is not going to happen.

@CyrusNajmabadi
Copy link
Member

Could support BOTH of reverse-ordinals and "Length minus i".

Yes. It could. And that was considered and rejected for the initial release. What you seem to not be understanding is that in no way is this release consider the end-all-and-be-all for Ranges. This is what was felt to be a good initial foray into this space. We made it with complete awareness of the limitations and concerns here, and we designed it to be something we could improve upon in the future if it was felt to be important enough to do.

This very topic was debated, and the LDM accepted that as a reaosnable starting point for 8.0. It won't be re-litigated. Maybe after 8.0 releases there will be enough feedback and use cases to make it so that they feel that handling both of these in-language is warranted.

@CyrusNajmabadi
Copy link
Member

but nobody is capable of achieving 100% success rate

The C# team (and LDM) has never attempted to reach any sort of 100% success rate. That's not how languages work. Not only are there straight up mistakes in the language, but any particular feature added is known to not be sufficient for the entirety of our current (and our desired future) ecosystem and community. The goal is to add value and to provide features that are overall net positives. Not to hit any sort of arbitrary 100% success (however you would even measure that).

@verelpode
Copy link

@HaloFour

If you've already reached your conclusion without reading the relevant notes and are unwilling to consider other views then there's really nothing to discuss.

Now that's unfair. I already changed my view in response to @Thaina's comment in a thread that you mentioned. I also expressed belief that a design exists that can make both camps happy.

If you have a specific language proposal then feel free to open an issue here. But whatever it is would certainly be orthogonal to supporting ranges.

I'd gladly write up a specific proposal and I have a design already in mind, but you guys are saying the issue is already closed, aren't you? @CyrusNajmabadi said "It won't be re-litigated" and @jnm2 said "very late". If you want the specific proposal from me, then I'd gladly do the work to write it up properly, but it sounds like you don't want it, or it won't make any difference because it's too late and you're all exhausted from debating the issue and the plan for C# 8.0 is already decided and won't be changed.

The response that I've received here seems to be that the C# team is unwilling to consider other views at the current time because it's too late, therefore there's really nothing that I could write in my proposal that has any chance of acceptance, right?

I'll do it if you want it, but please don't make me expend a big effort to write up a proper design document that will be immediately discarded.

@HaloFour
Copy link
Contributor

HaloFour commented May 6, 2019

@verelpode

I'd gladly write up a specific proposal and I have a design already in mind, but you guys are saying the issue is already closed, aren't you?

It's not closed until it's released. You mentioned language features around extents, and I want to see what specifically you mean. I feel that would be orthogonal to ranges as they are proposed here. If you have a different proposal for ranges you can feel free to open it, but you'll need to provide seriously compelling reasons for the C# team to reverse their decisions.

@verelpode
Copy link

If you have a different proposal for ranges you can feel free to open it,

Yes I have in mind a different design for the range feature, including the aim to support both extents and ranges equally well, considering that they're both useful in different circumstances. I cannot deliver a design document completely free of mistakes, but if people here take it seriously and develop the design further, then it could end up being a great proposal for ranges+extents as a team effort. Roughly how much time do I have remaining? The difficulty is that I would be unprofessional and irresponsible if I spend excessive time during weekdays to work on "X" when I already agreed to work on "Q", and I'm paid to work on Q not X. Unpaid work during the weekend is a possibility but won't succeed if it must be completed urgently.

@CyrusNajmabadi
Copy link
Member

Yes I have in mind a different design for the range feature, including the aim to support both extents and ranges equally well, considering that they're both useful in different circumstances. I cannot deliver a design document completely free of mistakes

Can you give a rough sketch? What this would look like from the consumption perspective. How someone would use it in an API. And what the general semantics would be. It doesn't have to be perfect, but it would be helpful to have a better defined view of what you're thinking about.

@CyrusNajmabadi
Copy link
Member

Roughly how much time do I have remaining?

Very little. The team is heads down on getting 8.0 into a final shippable state. And most of the efforts are in very high risk, very high complexity areas (like Nullable). Given that the LDM is satisfied with both the expected shipping for for Ranges, as well as feeling that improvements could come in the future, it would be very challenging to change anything. That said, if your proposal was amazingly compelling, and went a direction that wasn't previously considered, and really solves a whole host of issues in a simple and effective way, it's always possible it woudl get attention.

That's why i'd like to at least see a sketch of what you're thinking about. I could then say if it was something that had been considered during teh main design time for this feature.

@verelpode
Copy link

A rough sketch would be effective in the form of a .cs file that I upload somewhere, with the proposed language/syntax details in comments in corresponding places within the .cs file. Some people here have the luxury of being able to concentrate solely on the C# language design and get paid for it, but I do not have this luxury and unfortunately this timing conflicts with my obligations currently, thus uploading this proposal very quickly is impossible. As you guys have already indicated, it is irritating to receive vague critique without a concrete alternative proposal, and that's fair enough, but it also means that if I upload it too quickly, if I upload a sketch that is too rough, then it'll just be an irritating proposal containing too many mistakes on account on the rushed timeframe and conflicting work obligations.

@CyrusNajmabadi
Copy link
Member

CyrusNajmabadi commented May 6, 2019

A rough sketch would be effective in the form of a .cs file that I upload somewhere, with the proposed language/syntax details in comments in corresponding places within the .cs file.

Sounds good.

Some people here have the luxury of being able to concentrate solely on the C# language design and get paid for it,

I don't think either @HaloFour or I have that luxury. i don't think most of hte commenters here have that luxury. We all have day jobs that we have to focus on. But we do what we can to fit this sort of thing in. One thing you could consider would be taking this to gitter.im to have a better venue to explore your ideas (and potentially get people filling in gaps for you).

As you guys have already indicated, it is irritating to receive vague critique without a concrete alternative proposal, and that's fair enough, but it also means that if I upload it too quickly, if I upload a sketch that is too rough, then it'll just be an irritating proposal containing too many mistakes on account on the rushed timeframe and conflicting work obligations.

I'm really just trying to get a basic idea of what you're suggesting. THere's been a lot of talk about extents, and very little explanation of what that means at a language level, or how it would be affect the user programming model.

@verelpode
Copy link

as well as feeling that improvements could come in the future,

I think if the current version of the Range feature is released as-is, then my design is dead forever because it is too different/incompatible to be implemented as an extension in future. Currently I don't see how the various kinds of slicing operations can be retrofitted into the current version of the proposal without much breaking of compatibility.

@CyrusNajmabadi
Copy link
Member

Currently I don't see how the various kinds of slicing operations can be retrofitted into the current version of the proposal without much breaking of compatibility.

Easy: just use different syntax. Now you have no chance of stepping on what's currently shipped and what teh semantics of it are.

@verelpode
Copy link

Sure, if it was only syntax, but I propose a different design for https://docs.microsoft.com/en-us/dotnet/api/system.range
I'll try to do it quickly but no guarantee -- this timing is terrible for me. The timing is nobody's fault, it's just unfortunate.

@CyrusNajmabadi
Copy link
Member

Sure, if it was only syntax, but I propose a different design for https://docs.microsoft.com/en-us/dotnet/api/system.range

Why can't you have both these designs? IMO, it's akin to how Roslyn's TextSpan has a start + lenth variant, as well as as start + end variant. Both are useful from the end user perspective, but both are isomorphic to each other.

@verelpode
Copy link

As requested, here's the rough sketch. I hope you all like it. With some teamwork, it can be further improved to make a really great extents/ranges/slicing/segments feature for C#.

Advanced Extents & Segments Proposal re C# 8.0 Ranges #2510

@hez2010
Copy link

hez2010 commented Jun 4, 2019

Any consideration for stepping? #2562

@jcouv jcouv changed the title Champion "slicing" / Range Champion "slicing" / Range (16.3, Core 3) Jul 18, 2019
@solvingproblemswithtechnology

As I though all over this discussion, Range will be an IEnumerable. So you can have:

foreach(int year in 2015..2019) { }

@333fred 333fred added the Implemented Needs ECMA Spec This feature has been implemented in C#, but still needs to be merged into the ECMA specification label Oct 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Implemented Needs ECMA Spec This feature has been implemented in C#, but still needs to be merged into the ECMA specification Proposal champion Proposal
Projects
None yet
Development

No branches or pull requests