dotnet / csharplang

The official repo for the design of the C# programming language
11.38k stars 1.02k forks source link

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

Open verelpode opened 5 years ago

verelpode commented 5 years ago

Advanced Extents & Segments Proposal

Rough sketch -- Version 1 (2019/05/07)

The potential for advanced Extents and Segments in C# is exciting and under-estimated. I am writing this proposal because I feel that the current version of the C# 8.0 Range proposal is not yet ready for release. It would be sad if a half-baked version is released prematurely and set in concrete forever. Although future extensions are possible in C# 8.5, this becomes difficult when it breaks compatibility with the syntax and design in C# 8.0, therefore it would be best to design the advanced scenarios NOW not later.

This is a rough sketch and I've been forced to rush it, thus I'm sure it contains some mistakes and omissions, but it is nevertheless worthwhile to present. Example:

int myOffset = ...;
int myLimitOffset = ...;
Segment<char> mySegment = ...;
Segment<char> resultSegment = mySegment[myOffset from start until element is CharMatchers.VerticalWhiteSpace 
     && element != '\u2029' with fence myLimitOffset with maxLength 5000*2];

The above example does this: Beginning with the Segment<char> (or Span<char> or Array or List<char>) named "mySegment", make a sub-segment of mySegment (alternatively an Extent alone) that begins at offset "myOffset" from the start, and continues until an element (char) is a vertical whitespace character and does not equal "paragraph separator" (U+2029), but do not extend the Extent or Segment any further than "myLimitOffset", and limit Extent.Length to 5000*2.

If you want to get the Extent (offset and length) alone without making a new Segment<T> corresponding to that Extent, then you can write:

Extent x = [mySegment at myOffset from start until element is CharMatchers.VerticalWhiteSpace 
     && element != '\u2029' with fence myLimitOffset with maxLength 5000*2];

Relative offsets: The "from" keyword makes an offset relative to something else. The default is "from start" thus writing "myOffset from start" is the same as writing simply "myOffset" without any "from" keyword. Supported "from" keywords include:

    100 from start
    100 from end
    100 from myPositionX forwards
    100 from myPositionX backwards
    100 from myPositionX backwards for 300+10
    100 from last '%' backwards
    100 from first CharMatchers.UppercaseLetter forwards
    100 from first CharMatchers.UppercaseLetter || CharMatchers.WhiteSpace forwards

The "for" keyword makes an Extent. For example, 100 for 20 means Extent.Offset = 100 and Extent.Length = 20.
100 from myPositionX backwards for 300+10 means the Extent.Length is 300+10, and the Extent.Offset is calculated like this: Begin at offset myPositionX then slide the offset backwards by 100. The calculation is simply:

    Extent.Offset = myPositionX - 100;
    Extent.Length = 300+10;

Supported "with" keywords include:

    with fence myLimitOffset
    with maxLength myMaxLength
    with minLength myMinLength
    with length myLength    // maybe, see also "for".
    with direction backwards
    with direction forwards

CharMatchers.VerticalWhiteSpace is an immutable singleton class that implements IElementMatcher<char>. Anyone can write their own classes that implement IElementMatcher<T> and match elements using any criteria desired.

Naturally if you want the opposite of a particular matcher, you can use the logical-not operator with the "is" operator:

element is !CharMatchers.Alphabetic && element is !CharMatchers.WhiteSpace

Without using a matcher, the following example begins at offset "myStartOffset" and continues until an element (char) is the carriage-return character or the newline character:

Segment<char> resultSegment = mySegment[myStartOffset until element == '\r' || element == '\n'];
// Or if you only want the Extent:
Extent x = [mySegment at myStartOffset until element == '\r' || element == '\n'];

"while" keyword

Note the difference between the "until" and "while" keywords. The following example begins at "myStartOffset" and continues while the elements are decimal digits or underscore:

Segment<char> resultSegment = mySegment[myStartOffset while element is CharMatchers.DecimalDigit || element == '_'];
// Or if you only want the Extent:
Extent x = [mySegment at myStartOffset while element is CharMatchers.DecimalDigit || element == '_'];

"where" keyword

The following loop iterates through each segment/run of consecutive whitespace characters:

foreach (Segment<char> whitespaceSeg in mySegment[myStartOffset where element is CharMatchers.WhiteSpace])
{ ... }

The foreach loops functions with the "where" keyword because "where" produces IEnumerable<Segment<T>>:

IEnumerable<Segment<char>> results = mySegment[myStartOffset where element is CharMatchers.WhiteSpace];

Note that the returned IEnumerable instance is not a pre-generated array, rather it produces its enumerable elements on-demand like how System.Linq.Enumerable does. This can be implemented using the preexisting yield return feature of C#. Also on the topic of efficiency, note that Segment<T> is a struct, thus the where keyword does not create thousands of objects in the heap.

TO DO: The "where" keyword gives you the matching segments. Decide whether to make an option or variation of "where" that gives you both the matching and non-matching segments.

Moving Average

A "moving average" example was provided on the following webpage, but the version there as of 2019/05/07 looks defective unfortunately. https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/ranges-indexes Many elements are missed/ignored in that moving average because it does start += 100" yet "Range r = start..start+10; Furthermore, it has a function named "MovingAverage" that doesn't return a MovingAverage at all, surprisingly. It is named MovingAverage but it returns the same as System.Linq.Enumerable.Average.

The following design of MovingAverage attempts to eliminate the defects. In addition, it is better because it smooths-out the average by overlapping the segments.

using System.Linq.Enumerable;
static IEnumerable<double> MovingAverage(Segment<int> inData)
{
    foreach (Segment<int> seg in inData.CutAndSplice(inPieceLength: 20, inOverlapLength: 10))
    {
        yield return seg.Average();
    }
}

See also: https://en.wikipedia.org/wiki/Moving_average

Factionalize

The "factionalize" operation splits a segment into a sequence of "factionalized segments". A "factionalized segment" is a Segment<T> with a faction value assigned. For example, factionalization could be used as a stage in syntax parsing of text that is formatted to obey particular syntax rules. Example:

enum MyFaction { ... }
Segment<char> mySegment = ...;
foreach (FactionalizedSegment<char,MyFaction> in mySegment.Factionalize<MyFaction>(MyFactionalizer))
{ ... }

The foreach loops functions with Segment<T>.Factionalize because Factionalize returns IEnumerable<FactionalizedSegment<TElement,TFaction>>.

If Factionalize is used as a stage in syntax parsing of a programming, scripting, or data language, then TFaction could be defined as an enumeration like this:

enum TokenKind
{
    None = 0,
    WhiteSpace,
    Number,
    Word,
    Keyword,
    PlusSymbol,
    MinusSymbol,
    MultiplySymbol,
    ...
}

An instance of the delegate DlgFactionalizer is given to the Segment<T>.Factionalize method. See definition of this delegate within the .cs file.

Other slicing operations

See the .cs file for other slicing operations in Segment<T> such as:

public IEnumerable<Segment<T>> CutUp(int inPieceLength)
public static IEnumerable<Segment<T>> operator / (Segment<T> inSegment, int inPieceLength)
public IEnumerable<Segment<T>> CutAndSplice(int inPieceLength, int inOverlapLength)
public IEnumerable<Segment<T>> Dice(int inPieceLength, int inSkipLength, bool inInvert = false)
public IEnumerable<Segment<T>> Split(DlgSegmentSplitter<T> inSplitter)
public static IEnumerable<Segment<T>> Interleave(int inLength, params Segment<T>[] inSegments)
public Segment<T> ChopOffStart(int inPieceLength)
public Segment<T> ChopOffEnd(int inPieceLength)
public Segment<T> CleaveStart(int inPieceLength)
public Segment<T> CleaveEnd(int inPieceLength)
public void SeverStart(int inPieceLength, out Segment<T> outStartPiece, out Segment<T> outRemainder)
public void SeverEnd(int inPieceLength, out Segment<T> outEndPiece, out Segment<T> outRemainder)
public void Sever(Extent inExtent, out Segment<T> outStart, out Segment<T> outMiddle, out Segment<T> outEnd)
public (Segment<T> partA, Segment<T> partB) Bisect(int inOffset)
public IEnumerable<FactionalizedSegment<T,TFaction>> Factionalize<TFaction>(DlgFactionalizer<T,TFaction> inFactionalizer)
public Segment<T> Truncate(int inMaxLength)
public Segment<T> GetExtent(Extent inExtent)
public Segment<T> GetExtent(int inOffset, int inLength)
public Segment<T> GetExtentToEnd(int inStartOffset)
public Segment<T> GetExtentToStart(int inOffset)
public Segment<T> GetExtentAtStart(int inLength)  // might be renamed to GetPrefix
public Segment<T> GetExtentAtEnd(int inLength)    // might be renamed to GetSuffix
public Segment<T> GetRange(int inStartOffset, int inEndOffset)
public Segment<T> GetRangeInclusive(int inStartOffset, int inEndOffset)

Syntax for basic extents and ranges

Basic examples following (basic meaning not using the until, while keywords etc).

Extent x = [20 for 30];   // makes Extent.Offset=20, Extent.Length=30
Extent rangeA = [20..50]; // makes Extent.Offset=20, Extent.EndOffset=50
Extent rangeToEnd = [20..];
Extent rangeToStart = [..20];
Extent singleElement = [5];  // makes Extent.Offset=5, Extent.Length=1 or maybe Length=0
Extent negativeOrdinal = -[5]; // Extent.Offset == DataLength - 5
Extent reverseOrdinal = ~[5];  // makes 0-based ordinal in reverse, as if System.Array.Reverse was executed.
Extent rangeB = [20 .. -[5]];  // Extent.EndOffset == DataLength - 5

The following are the same, which means that -[5] actually invokes the operator - (Extent) overload method that is defined in struct Extent.

Extent negativeOrdinal = -[5];
Extent negativeOrdinal = -(new Extent(5, 1));

Likewise ~[5] invokes the operator ~ (Extent) overload method that is defined in struct Extent.

Iteration in reverse order

Example:

Segment<char> seg = ...;
int len = seg.Length;
for (int i = 0; i < len; i++)
{
    char ch = seg.InReverse[i];
    // Also supported:
    char ch = seg.GetItemReverse(i);
}

Builder

See Segment<T>.Builder in the .cs file.

https://github.com/verelpode/Advanced-Extents-Segments

verelpode commented 5 years ago

V1 of my proposal attempted to support the reverse-1-based ordinals. This feature is against my own opinion, but I'm doing it anyway out of respect for the opinions of some other people who claim it is a justifiable feature. The question is, how can the following problem be eliminated: Apparently the current design of ^0 will trigger never-ending complaints over years or decades because of the inconsistent introduction of 1-based ordinals into a language that was forever 0-based.

How can this problem be eliminated? One possibility is to design it with the principle that subtraction means subtraction. It's hard to complain about a design where subtraction means subtraction. People cannot complain that it's confusing when the principle is so simple that subtraction means subtraction.

If the syntax [5] produces an instance of System.Extent or System.Range, and if the Extent or Range struct includes a normal C# operator-overload-method for the arity-1 minus operator (meaning static Extent operator - (Extent) { ... }), then the syntax -[5] invokes the operator-overload-method in the standard manner, which returns an Extent or Range that represents the equivalent of Array.Length - 5.

The upcoming decades of never-ending complaints are prevented because it's not confusing anymore when the - operator means -.

So that's one problem hopefully eliminated. Next, the second problem needs to be eliminated. The second problem is what @lostmsu mentioned: The majority of the reason for this feature to exist is academic scenarios. The added complexity and performance penalty of supporting negative ordinals may well outweigh the benefit in real-world scenarios, if any meaningful amount of benefit exists at all. A method of addressing this problem is to collect a good quantity of real examples from real software and then perform an analysis of the cost versus benefit in each example when it is converted to use negative ordinals.

CyrusNajmabadi commented 5 years ago

The question is, how can the following problem be eliminated: Apparently the current design of ^0 will trigger never-ending complaints over years or decades because of the inconsistent introduction of 1-based ordinals into a language that was forever 0-based.

It's your opinion that this will be a problem. This is not an opinion shared by the LDM.

In my personal opinion i don't see an issue here. People will learn how indexing will work, and will move on. And that's that. So there's no issue to solve, and no need to 'eliminate' anything.

CyrusNajmabadi commented 5 years ago

Next, the second problem needs to be eliminated. The second problem is what @lostmsu mentioned: The majority of the reason for this feature to exist is academic scenarios. The added complexity and performance penalty of supporting negative ordinals may well outweigh the benefit in real-world scenarios,

It doesn't appear as if that's the case. So the "may well" part is not an issue.

if any meaningful amount of benefit exists at all. A method of addressing this problem is to collect a good quantity of real examples from real software and then perform an analysis of the cost versus benefit in each example when it is converted to use negative ordinals.

This has been done. It was used to help drive and refine the feature. CoreFx also helped here which led to some later tweaks on the impl.

CyrusNajmabadi commented 5 years ago

Apparently the current design of ^0 will trigger never-ending complaints over years or decades because of the inconsistent introduction of 1-based ordinals into a language that was forever 0-based.

Note: we examined the broad ecosystem of languages that support features like this. We couldn't find any sort of similar sentiment to the one you're espousing for them. Their communities were able to pick up and understand how this sort of indexing works, and there's no indication from preliminary usage that the C# ecosystem is different here. Your concern, while well-meaning, seems speculative and doesn't match the reality of the greater programming community.

jnm2 commented 5 years ago

@verelpode

As jmn2 said, this is tiring and absorbs a lot of time and energy,

Please don't take my name in vain. That is not what I was talking about. I was referring to your desire to redesign a language feature that was mostly out the door without taking into account the years of study that went into it.

jnm2 commented 5 years ago

Maybe the name "Roslyn" was a mistake because it's a female name and thus makes it more difficult for males to remain non-emotional

This is horrifying. Where are you coming up with this stuff?

jnm2 commented 5 years ago

@verelpode That was a really low-effort and sucky thing for me to say. I'm leaving it here just to take responsibility for it, but I was only thinking about myself. I'm sorry.

My impression is that you could get a lot of mileage in these conversations by framing your points in a way that makes it easy for folks to want to agree with you, but it totally makes sense if I've lost the right for you to listen to me with my last comment.

verelpode commented 5 years ago

In connection with the academic nature problem, here's one way of eliminating the problem of the dubious at-runtime complexity and performance penalty: Support this usage of negative ordinals:

char[] dataArray = ...;
Span<char> slice = dataArray[20 .. -[5]];

...but don't support negative ordinals in this case:

Range r  = [20 .. -[5]];
Extent x = [20 .. -[5]];

...because the first example can be implemented with zero penalty at runtime whereas the second example cannot. In terms of a cost-vs-benefit analysis, the second example is much more difficult to justify than the first example where the total length is known. This is a matter of finding a reasonable balance or compromise without springing to either extreme. This isn't a black and white issue.

I'm searching for ways to eliminate the above-mentioned problem because, as a general policy, I always try to eliminate a problem instead of burying my head in the sand and pretending that the problem doesn't exist. On a few occasions in the past, I've used self-delusion to make myself feel better, but it only worked short-term and in the long run I felt overall worse, so I try not to do that anymore. (This is a 100% truthful description of my experience in general and it is not directed at any particular participant here. Also note my comments can benefit "invisible" readers here who read this thread but haven't posted any messages.)

verelpode commented 5 years ago

@jnm2

My impression is that you could get a lot of mileage in these conversations by framing your points in a way that makes it easy for folks to want to agree with you

Should I desire to have that mileage in this case? Your situation is different than mine. When clicking on your name, your profile says ".NET Foundation member" whereas my profile deliberately does not name my employer. Furthermore, I'm not a Microsoft staff member paid to work on C# 8. I'm paid to work on a different project. I don't have the onus nor responsibility to solve problems in C# 8 nor to prove any of my ideas for C# 8.

@CyrusNajmabadi said in reply to me "The onus is on you", but that's incorrect. The applicable Microsoft staff members have the onus and responsibility. The staff who are paid to work on a project have the onus and responsibility to ensure that the problems in that project are addressed and eliminated, and that customer feedback is analyzed for valid and useful points. My onus and responsibility is to eliminate the problems in the project that I'm paid to complete, and that project is not C# 8. I also have a responsibility to make an extra effort for customers of my employer but nobody here is a customer of my employer.

@CyrusNajmabadi said "you've stated you want this very large feature", but I never stated that. My message clearly states: "This is a rough sketch and I've been forced to rush it, thus I'm sure it contains some mistakes and omissions"

It doesn't make sense to say that I want something that contains mistakes and omissions. It's also not my responsibility to fix all of the mistakes and omissions.

svick commented 5 years ago

@verelpode

You can become a member of the .NET Foundation too.

I don't have the onus nor responsibility to solve problems in C# 8 nor to prove any of my ideas for C# 8.

Nobody says that it's your job to fix C#. But it seems it's your opinion that the proposed version of C# 8.0 is problematic. And if you want that to change, then it's up to you to make your case.

verelpode commented 5 years ago

@svick Thanks for the link. By the way, when I said "academic", I meant the general sense, not specifically people who work in academic institutions. Anyone may produce an academic-only design. I don't work in an academic institution but nevertheless I've produced academic-only designs on few occasions and I had to go back and produce a new version/revision of the design in order to make it suitable for use in a real situation, but that wasn't bad news because I wasn't forced to throw the whole design in the garbage bin, rather I just revised it and fixed the problems.

I've also personally known a few people who DO work in academic institutions and who have impressive two-way connections between academic and practical applications, and impressive bidirectional knowledge transfer between teacher and students -- not only the teacher-to-student direction, but also student-to-teacher whenever possible.

if you want that to change, then it's up to you to make your case.

It's not as simple as that. Projects can be terribly bogged down by the people-politics and human psychology. Some projects are not technically difficult but are delayed for many years because of human psychology. It would be much simpler if criticism was only criticism, but sometimes humans state a criticism even when they don't believe it themselves! It can be difficult to distinguish between a genuine critique versus an ulterior motive or knee-jerk reaction triggered by an emotion. Fear is also a common problem -- sometimes humans imagine that they or their position is being threatened even when it isn't, and this can trigger harassment/mobbing or an attack against the imagined enemy who is no enemy in reality.

verelpode commented 5 years ago

@svick That webpage is unfortunately vague and short on details. Please don't be offended by the following question because I don't believe it's true. In fact, the following sounds like a conspiracy theory, if you ask me. But anyway, I'm curious to hear your response so here it is despite my skepticism. Here's what I heard: Large corporations in the stockmarket are legally required/obligated by the current laws to maximize profits for shareholders. Software engineers complete more work in less time when they work overtime, thus higher profits, but it's not legal to ask any employee to work more than 40 hours per week. To work around this law, software engineers can be encouraged to become a member of a non-profit organization, and then they usually work additional hours during evenings and weekends. In total they work much more than 40 hours per week for the same salary as 40 hours. I'm reluctant to repeat everything that I've heard but now my curiosity has gotten the better of me, so what are your thoughts about the inappropriate and disagreeable claim that some open-source organizations are "for suckers" and "naive young software engineers" who don't realize they're being manipulated into working much harder and longer for much less salary than they're entitled to, in order to maximize profits for the shareholders of the large stockmarket-based corporations.

I know, I know, crackpot conspiracy theory, but you work in an academic institution therefore I guess you're the same as me in viewing it as intellectually stimulating to discuss the purely-theoretical merits and flaws of a theory even when it's a wild crackpot theory.

I've also attended debating clubs at universities where sometimes a controversial crackpot theory is deliberately chosen as the topic of the debate, and it does produce an entertaining intellectual debate for the club members to enjoy.

jnm2 commented 5 years ago

Should I desire to have that mileage in this case? [...] I don't have the onus nor responsibility to solve problems in C# 8 nor to prove any of my ideas for C# 8.

Why should you not want to benefit yourself or others by this conversation? That's all "mileage" meant. There's not much purpose in having a conversation if you don't want to be heard, and if you do want to be heard, it just makes sense to choose to say things in such a way that people will want to converse with you and consider what you have to say. I don't think this is controversial.

Your situation is different than mine. When clicking on your name, your profile says ".NET Foundation member" whereas my profile deliberately does not name my employer. Furthermore, I'm not a Microsoft staff member paid to work on C# 8. I'm paid to work on a different project.

My profile does not name my company either. I'm a part owner of a local business. The link @svick supplied is a good explanation of what a .NET Foundation membership is.

Just to be frank, it's super weird that you're doing things like looking up our profiles, coming to conclusions, and expounding on those conclusions at length in this conversation. For example, the whole "academic" section above. This is not normal or benefiting the topic.

svick commented 5 years ago

@verelpode

Large corporations in the stockmarket are legally required/obligated by the current laws to maximize profits for shareholders.

They're not.

Software engineers complete more work in less time when they work overtime

They don't.

To work around this law, software engineers can be encouraged to become a member of a non-profit organization, and then they usually work additional hours during evenings and weekends.

I don't see how that makes sense. You do need to contribute to a .NET Foundation project to become a member, but that can be just a one-off thing and contributions during work hours count too. And once you are a member, your only obligation is to pay membership dues, and even that is optional.

People who contribute to open source projects in their free time do it because they want to, not because they joined a foundation and now feel they have to.

what are your thoughts about the inappropriate and disagreeable claim that some open-source organizations are "for suckers" and "naive young software engineers" who don't realize they're being manipulated into working much harder and longer for much less salary than they're entitled to, in order to maximize profits for the shareholders of the large stockmarket-based corporations

Personally, I do think that compensation for open source work is a problem in the industry. But that applies to all open source projects with volunteer contributors, I don't see how manipulation or profits enter the picture.

Though all of this off-topic here. If you want to discuss these kinds of theories, I suggest you choose another venue.

verelpode commented 5 years ago

Example of a technique in a debating club. The following example isn't true -- please don't flip out -- this is nothing more than an theoretical example of the intellectual fun at a club.

@HaloFour wrote:

as a previous member and as continuing contributor they do have a great deal of respect for his input. Infinitely moreso than yours.

So in a debating club, here's how we respond if the opposing team says something like the above comment. We reply by saying that actually they don't respect him, rather they're using or exploiting him in order to advance their own career. He believes they respect him but actually they merely view him as a useful utility.

THAT'S NOT REAL. That's just a debating club example.

msedi commented 5 years ago

I'm just listening to this, and we also had a lot of discussions in our team about the range feature - to be honest, no one liked it, although everyone liked that there is finally something that can describe ranges and our team has a lot of different experiences from other languages (MATLAB, Maple, Mathematica, Python, R, etc.).

We had already implemented this features years ago, without the help of C# for our matrix classes and other classes that needed range support. The solution was quite simple, we created an Indexerstruct (in your words Range) and each class that should be capable using this extended property indexer needed to implement this[Indexer idx] {get; set;}. This worked just fine except that we didn't have language support during parsing the code. I guess this is the main feature (not really the Range itself) that the compiler is able to resolve the Range notation and create a Range instance for you (a code rewrite at compile that I would like to see more often, since we have more of these things, e.g. physical units).

Without the help of C# we had to write the indexing elements in string representation, so for example

Indexer i = "10:20"

translated to an Indexer that took all elements between 10 and 20 (including both), as this is the case with Range (Start=10; End=20).

Since we are coming from the MATLAB world, we took start and end as additional parameters to be able to describe the extents of the range without having to know the real start and end index. So using

Indexer i = "start:end"

simply takes the whole range of the object using the Indexer.

We also made it possible to have offsets from the start and end, including some math operations on it.

Indexer i = "start+10:end-10"

We could also produce Indexer ranges with a userdefined increment:

Indexer i = "10:2:20" // take every second element from 10 to 20 Additionally we could produce Indexer arrays:

Indexer i = "10,11,12-14,18-end"

Also it worked for multidimensional indexing;

Indexer i = "10,11,12-14,18-end;1-10"

Everything works really fine, except, as mentioned above that we don't have compiler support to resolve it.

In the end, I think the Range is useful for very primitive scenarios, as for example String.Substring() or some other methods that require simple ranges.

For more complex cases I assume it's not so useful.

I know this is a bit off this topic now and a separate request: If roslyn would support code rewrites people could create their own Ranges, Indexer or whatever.

verelpode commented 5 years ago

@svick

once you are a member, your only obligation is to pay membership dues

So, I give my work to the foundation and I have to pay the foundation (it's a small $ amount to pay but nevertheless I pay the foundation something). Shouldn't it be the reverse? Shouldn't the foundation pay me for my long hard work in developing stuff for the foundation? Stuff for corporations to use and profit from?

verelpode commented 5 years ago

@svick Aha, that info was interesting! So a couple of points in the theory are inaccurate. The theory said that the profit maximization is forced by law, but Cornell Uni says it's not law, rather it's the directors. The corporate directors decide to maximize profits because of pressure from shareholders etc.

Usually maximizing shareholder value is not a legal obligation, but the product of the pressure that activist shareholders, stock-based compensation schemes and financial markets impose on corporate directors.

The second inaccuracy is that overtime increases profits. It probably doesn't, but the corporate directors may want overtime anyway because they mistakenly believe it increases profits, and refuse to believe otherwise.

verelpode commented 5 years ago

@jnm2

There's not much purpose in having a conversation if you don't want to be heard

True.... I thought hard about what you said and in conclusion I think you're right. There's not much purpose in me continuing to participate here, especially because zero Microsoft employees are participating in the discussion. So it seems like the sensible and logical thing to do here is to end my participation. It also appears that there's no logical reason for me to join the foundation.

jnm2 commented 5 years ago

@verelpode None of those are things I said. What I actually said (a few times now) is very much more difficult than leaving: it's only worthwhile to present your ideas in an appealing way.

CyrusNajmabadi commented 5 years ago

True.... I thought hard about what you said and in conclusion I think you're right. There's not much purpose in me continuing to participate here, especially because zero Microsoft employees are participating in the discussion.

This has not been a problem for many others in the past. Perhaps you are jumping to conclusions on how things with based on minimal participation while disregarding the advice and experience of many here we have been involved a lot in Roslyn over the last decade. I would strongly suggest trying to approach things more from a perspective that there could bring positive outcomes here and that people here are trying to help you get to that point.

You're welcome to leave if you want, but you'll only be going against your item professed still interests.

CyrusNajmabadi commented 5 years ago

@CyrusNajmabadi said in reply to me "The onus is on you", but that's incorrect.

No, it is correct. You are proposing the feature. The onus is on you entirely to get it to a state that it could be accepted by teh LDM. You can hope that others will help you take up the mantle, but no one is obligated at all to do so. It's entirely on you how you put it out and how you engage in the discussion around it.

Many people (including several conversing with you) have been successful in the past doing this sort of thing. And many here are giving you strong and sound advice on what you can do to be more successful. You can either listen and attempt to adopt that advice, or you can choose not to. But the outcomes of that choice are basically all on you.

The applicable Microsoft staff members have the onus and responsibility.

No. They don't. This is simply false.

The staff who are paid to work on a project have the onus and responsibility to ensure that the problems in that project are addressed and eliminated,

The staff believes the existing feature has been satisfactorily designed and implemented to their standards.

and that customer feedback is analyzed for valid and useful points.

As all your points were raised and addressed during the design portion of this feature, the staff believes that that has already been done.

@CyrusNajmabadi said "you've stated you want this very large feature", but I never stated that.

I presumed that by stating you wanted a different approach to ranges in the previous thread, that you wanted this. And i presumed that by opening this issue and outlining this large feature that that was tacitly stating you wanted it. If you don't want it, i apologze for the assumption. Nearly every other proposal ever made has been by someone who actually wants it done, so it seemed reasonable to assume the same of yours.

It's also not my responsibility to fix all of the mistakes and omissions.

It is if you want this proposal to go anywhere. Unless you can convince someone else to help you, then the onus is entirely on you to get the issue to the state that it could be meaningful.

And, if you're not going to work positively with others to get them to help you, and you're not going to put in the effort yourself, the expected outcome woudl be that nothing would come of this.

CyrusNajmabadi commented 5 years ago

So it seems like the sensible and logical thing to do here is to end my participation

As mentioned many times over, there are better avenues for you to discuss this sort of thing. For example: gitter

There are long and fruitful discussions there about both C# and the Roslyn project. And many team members participate there. So far, like with much of the rest of the advice provided, you have ignored approaching this problem space in any sort of different way than the one way you prefer. You are under no obligation to change or try something different. But you're very likely to run into much more limited success here if you continue behaving in this same manner for all issues that bother you.