dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.95k stars 4.02k forks source link

Support := syntax as an alternative to var #16442

Closed corliss closed 6 years ago

corliss commented 7 years ago

The title says it all...

jnm2 commented 7 years ago

(after all the user doesn't memorize list entries from one version of Visual Studio to the next!)

Of course they do. Even i do this :)

That's what muscle-memory is. You get used to interacting with the tooling in a certain way, to the point that you're just doing it automatically.

True story.

jnm2 commented 7 years ago

This is getting absurd. You remember lists of intellisense tokens that can be displayed at any line in any file? I'm not talking about menus.

I remember lists of intellisense completions that are displayed at different types of context in every file, yes. That means I anticipate which tokens will show up, almost without thinking.

CyrusNajmabadi commented 7 years ago

You remember lists of intellisense tokens that can be displayed at any line in any file? I'm not talking about menus.

Yes.

This is getting absurd.

Look, i'm going to nip this part of the conversation in the bud. This is a dead-serious point i'm making on this topic. You may feel like this is some sort of exaggeration or joke, but i can assure you, it is not. The muscle-memory issue is very real and one that we continuously run into as we do invariably make changes, or refactor these systems.

And, yes, specifically, i (and many others) absolutely do end up remembering these things. Note, it's not remembered at the level of "i can go and repeat to you what they aall are and what the order is**". It's remembered at the level of "without thinking, my fingers just know that if they do this set of strokes, they will get the result they want in the IDE".

Frankly, i could not even tell you how i type. It's just an unconscious process for me, both in this Chrome window, and in VS. But that process has been deeply shaped by how the tools work and how i've interacted with them over my entire life. But it's very real, and it's very important for many people. :)

--

Heck, i could not even tell you the layout of the qwerty keyboard if you asked me. But trust me, my muscle memory lets me go at a brisk 150wpm with nearly no errors. Over the years, my brain has attuned me to how VS works and what the editing experience is like for languages like C#. We can and will change then. But only when we feel we have a great solution and and that the experience improvement is really worth it. :)

CyrusNajmabadi commented 7 years ago

do you complain when a new C# keyword, say await, is added to the language and now shows up everywhere in intellisense lists?

"We can and will change then. But only when we feel we have a great solution and and that the experience improvement is really worth it. "

As i've repeated on numerous occasions. We absolutely will change things when we've convinced ourselves there is enough value and that the experience degradation will not be significant. But we absolutely go through that exercise each and every time.

'await' is actually a terrible example because the feature itself was so staggeringly beneficial, it was worth almost anything :) It literally introduces a fundamental shift in how you did a certain type of programming that has now becomes so exceptionally common to developers.

If := had even 1/10th the value of await for me, then i'd likely be gung-ho about taking it, damn the impact to typing :)

But it's not there. This is a feature that literally adds problems (multiple ways to do the exact same thing), with so little gain (2-4 characters...), that it's really hard for it to ever overcome these other issues as well.

CyrusNajmabadi commented 7 years ago

I'm asking this because it seems that you aren't giving the full story here. You're making these out to be unique to := and I'm having to point out that they are not, not a fun position.

No. I'm absolutely not. It's an issue with every language feature we make. And we can and do revise and adapt language decisions based on this sort of feedback. Again, even while adopting a very sql-like language feature for the the language with linq-query-expressions, we decidedly went away from their syntax precisely due to tooling concerns.

And, as mentioned above, in the cases where we've adopted new word-like syntax, we've always had to make the argument that the value of the feature itself warranted precisely these issues that i've brought up. More proposals than i can count have not made the cut. The ones that you've seen be successful, were so precisely because they could demonstrate the value that would outweigh the drawbacks.

CyrusNajmabadi commented 7 years ago

Countering with a diatribe about awake when that was just an example name

I addressed 'await' because it was the example you brought up.

and not even highlighting that every change in the C# keyword list

The argument i made included all the changes for every C# keyword *. Again, as i've already* stated, all the language features that we have shipped have been assessed to have enough value to warrant inclusion, despite all these other concerns we have.

A significant problem here is htat you seem to be arguing: "but you've made changes before, and it was ok. Ergo, it's ok to make this change".

That is not accurate or appropriate. We've made changes before when we've been able to judge that the value of the feature outweighed all the negatives (including ones i've mentioned here). Along with the dozens of features that have made the cut there are hundreds to thousands that have not. Many of which did not make it for the reasons i've given here.

You're looking at what succeeded, and saying that that should make it ok to do it here. I'm looking at what failed, and i'm stating that this so far seems to be more like the latter than the former.

--

Note: these are just my personal appraisals of the situation. However, having been part of examining more proposals that i can count, these are the types of issues that are rising to the top of my concern list.

You are welcome to think this is absurd. There appears to be nothing i can do to dissuade you of that. But, i'm sorry to say that these are real concerns for us, and they are things we consider with every single language proposal that goes through. It has served us well so far, though it often does lead to disappointment for many people who have syntax they want that we do not adopt.

--

** I literally said: " We absolutely will change things when we've convinced ourselves there is enough value and that the experience degradation will not be significant. But we absolutely go through that exercise each and every time."

I then wanted to point out that 'await' was simply a particularly bad example because when we evaluated all the criteria the gains brought aobut by the feature outweighed the problems that i've outlined above.

CyrusNajmabadi commented 7 years ago

Let me try one more approach to help this make sense for you @corliss:

There are many different things we consider when trying to evaluate whether or not we should take on a language feature. Those things include, but are not limited to, considerations around scenarios the feature enables or simplifies. How well that language feature fits into the existing language. How much it conflicts, or overlaps with an existing feature. How much future work it enables or compliments. How much future work it might interfere with. How much impact will it have on tooling/IDE. Will it cause problems in the tooling/IDE space. How will it hurt/help readability. etc. etc. etc. The set of things considered is actually pretty darn large.

Now, across all these things we consider, some thing won't even show up as a blip on the radar. For example, some features may have almost no IDE impact, whereas some will be huge. Some features might be massively complex to implement in the compiler, and some might be literally one hour of work. Some features may make certain coding patterns massively simpler, and some may barely affect them at all.

We take all these pros/cons and we weight them and try to judge the overall value the feature will have. If it's negative, we def won't want to take it. But if it's anywhere from hugely positive to slightly positive, we'll assess it against all the other features and try to decide what to do.

However, at no point do we try to lie to ourselves or mask potential downsides of a feature. Responsible evolution and development requires us to appropriately understand and assess these things.

--

Now, when it came to your feature, i put my LDM hat on and i asked myself what value i saw here and what potential downsides i saw. I very serious problem with your feature is simply taht i can't even really say that much positive about. It saves a few characters, but at the cost of now potentially bifurcating our audience. It does not substantually make any existing coding patterns significant better. And, on top of all that, it would absolutely either:

1) affect existing customers who expect muscle memory to remain. or 2) provide a suboptimal coding experience for users who want to use the new feature.

This is not a positive assessment for the feature.

--

Now, i spent the time to go in depth explaining what i was looking at and how i was assessing. You have taken great issue with the criteria i've used and how i've evaluated. I hope that you can see that i've been dead serious with my assessment and that i've simply taken this feature and attempted to put it under the lens that i use with every language feature.

iam3yal commented 7 years ago

And for the lazy of us. 😄

This is inspired by the immaculateness of Go code.
As an example, see https://github.com/google/btree/blob/master/btree.go.

The line-noise overhead of, say,

    var item = n.Items[i];
    var next = n.cow.NewNode();

is significant compared to using the proposed :=

    item := n.Items[i];
    next := n.cow.NewNode();

It isn't just that four characters (3 of which are red) have been replaced by a single inconspicuous character. It's more that the mind is focused directly on the thing of interest, namely the variable name, instead of being chaperoned by the var.

Tuples can also be usefully improved from

    var (foo, bar, baz) = GetItems();

to just

    (foo, bar, baz) := GetItems();

I know that keywords over symbols is a tenet of C# design. However, perhaps it is worth questioning that in this case.

jnm2 commented 7 years ago

@eyalsk quick question: how did you render that border without making the contents bold?

<table><tr><td>Never mind</td></tr></table>
AustinBryan commented 6 years ago

:= is so tiny it's too easy to miss. And, when the names are simple x and y it might not seem it, but when the names are longer:

x := 3;
activeMemberCommittees := new List<Member>();
name := "foo";
fileStreamDatabase = new FileStreamDatabase();
imageDatabase := new ImageDatabase();
lastFocusedWidget := currentFocusedWidget
currentFocusedWidget = GetFocusedWidget();

It's almost as if it's trying to hide where the new variables are, and that's an important thing to hide. This code is much more readable (and still very brief compared to explicit typing!)

var x = 3;
var activeMemberCommittees = new List<Member>();
var name = "foo";
fileStreamDatabase = new FileStreamDatabase();
var imageDatabase = new ImageDatabase();
var lastFocusedWidget = currentFocusedWidget
currentFocusedWidget = GetFocusedWidget();
jnm2 commented 6 years ago

Would you close the issue, please, since all language design issues have migrated to https://github.com/dotnet/csharplang?

DavidArno commented 6 years ago

One for @gafter to close, maybe?