Discussion: remove the need to end a statement by semicolon #496
Replies: 67 comments 20 replies
-
In short, C# was not designed for semicolons to be optional therefore making them so would leave numerous situations where the syntax would be ambiguous. Lots of work for zero gain. |
Beta Was this translation helpful? Give feedback.
-
The short answer is: no. |
Beta Was this translation helpful? Give feedback.
-
I think the only way this could ever work is to have a "light" mode which can enforce line breaks after statements which do not end in a semicolon. Light mode would probably also include curly brace removal and require strict indentation. I was curious what these changes would actually look like in real code, so I updated the current copy of CSharpSyntaxTree.cs by adding a Some excerpts follow. Light: public override IList<TextChange> GetChanges(SyntaxTree oldTree)
if (oldTree == null)
throw new ArgumentNullException(nameof(oldTree))
return SyntaxDiffer.GetTextChanges(oldTree, this) Original: public override IList<TextChange> GetChanges(SyntaxTree oldTree)
{
if (oldTree == null)
{
throw new ArgumentNullException(nameof(oldTree));
}
return SyntaxDiffer.GetTextChanges(oldTree, this);
} Light: private bool IsPreprocessorSymbolDefined(InternalSyntax.DirectiveStack directives, string symbolName)
switch (directives.IsDefined(symbolName))
case InternalSyntax.DefineState.Defined:
return true
case InternalSyntax.DefineState.Undefined:
return false
default:
return this.Options.PreprocessorSymbols.Contains(symbolName) Original: private bool IsPreprocessorSymbolDefined(InternalSyntax.DirectiveStack directives, string symbolName)
{
switch (directives.IsDefined(symbolName))
{
case InternalSyntax.DefineState.Defined:
return true;
case InternalSyntax.DefineState.Undefined:
return false;
default:
return this.Options.PreprocessorSymbols.Contains(symbolName);
}
} |
Beta Was this translation helpful? Give feedback.
-
I woudl only accept this if we avoided the mistakes of javascript. i.e. it would be the case that we would only infer a semicolon in the presence of an error in the code. Right now, javascript puts semicolon insertion in places like so that return
foo(); is parsed differently than return foo(); To me, that's unacceptable. If the code has a production that can be parsed at that point, then semicolon could not be inserted. However, if no production matches, and certain conditions are true, then semicolon insertion woudl be ok. Those conditions would be the same as javascript:
This would mean that semicolon would be ok here: Foo()
if (bar)
baz() But it would not be ok here: Foo() /*not inferred here*/ if (bar) baz(); Note: i'm also against this feature as it makes language versioning much harder. That's because now when you add a new language feature, it might make previous code parse differently. i.e. say you have: Foo()
if (bar) { } If we then add an "if" operator to the language, then the following could start parsing differently. You have to be super super super careful to prevent these types of breaks. |
Beta Was this translation helpful? Give feedback.
-
Also, i should rephrase. The problem isn't that you just have to be careful about makign changes to the language. The problem is that this sort of approach actually limits the types of language changes you make in the future. i.e. today we can add any language syntax for any sort of construct that would have been illegal before. Now we're limited in that not only did it have to be illegal before, it had to be illegal even in the presence of optional semicolons. i.e. if there was a case where we would allow that construct by inserting a semicolon, then we can no longer have the new feature as it might break code that became legal due to to semicolon insertion. |
Beta Was this translation helpful? Give feedback.
-
There is really good slideshow presenting how C# Light could look like - https://www.slideshare.net/ScottWlaschin/c-light. Worth going through. |
Beta Was this translation helpful? Give feedback.
-
@Krzysztof-Cieslak I'd suggest a slightly different syntax type Person(name: string, birthday: DateTime) =
/// Full name
member __.Name with get() = name
/// Birthday
member __.BirthDay with get() = birthday |
Beta Was this translation helpful? Give feedback.
-
I don't understand why that kind of syntax is called "light". It's not lighter, it's just different. I don't think that the syntax examples above are any easier to read. If anything I think that when they get slightly more complicated that they're much harder to read as you lose the punctuation tokens for implied whitespace sensitivity which can be easy to miss. And in a language like C# where whitespace is intentionally almost always trivia it's inevitable that ambiguities will be introduced which would still require disambiguation and potentially have different meanings depending on whether that "optional" punctuation is present. The CLR supports dozens of languages with wildly different syntactic rules. Take your pick. This idea that C# should somehow conform to the syntax of other languages is beyond me. |
Beta Was this translation helpful? Give feedback.
-
I don't understand why C# would have to be like a language which "does not need semicolon to end a statement". It works fine the way it is. There's always VB, if you would rather be semicolon-less. :-). |
Beta Was this translation helpful? Give feedback.
-
There is F# that does almost everything without semi colon and less verbose language. Semi colons provide compiler enough information to detect further errors down the line instead of stopping at one error. Various languages without semi colon has problem of error loop, you fix one and next one is revealed after fixing last one. This is important feature while coding, c# compiler knows when the statement is supposed to end and this improves intellisense. |
Beta Was this translation helpful? Give feedback.
-
I am on a journey into F#, coming from C# and find the lack of terminations (braces more than semicolons) extremely confusing. I don't understand the movement to remove the punctuation from our languages. I want to be able to shape my code beautifully and intentionally and that requires freedom of expression through whitespace which (IMO) requires that we have punctuation to mark the beginnings and end of things just like we do in language. Interestingly, F# has 'light' by default, but also has a non-light mode that then requires this punctuation and allows us to define the shape of the code how we want. I haven't managed to convince my team to switch to that by default yet. I probably never will.
Firstly, code is written by people for other people to read. When people write, they can be ambiguous; although the compiler or interpreter (running the code) might not be ambiguous, it is vitally important that we convey our intention of the code to the human reader. Secondly, the complexity of the code (or, more importantly, the increased cognition required to understand the intention), has a serious adverse effect on the speed and ability for someone to understand the code. More time is spent trying to understand code than writing it in the first place. Thirdly, ambiguity brought about by inconsistent conventions (naming, operators, layout, syntax, grammar) and the translation of an intention into the code reduces the ability to understand the code without significant cognitive effort. It's time we remembered why we had a revolution a couple of decades ago and got back to setting up the next team to win (there is a quote there but I can't find who it was). We need to stop minifying and reducing descriptions of intent down to the least amount of characters and the lines. Memory, pixels, and storage are so cheap now compared to when we started this game - use them and write beautiful prose that eloquently and easily describes what we are coding. |
Beta Was this translation helpful? Give feedback.
-
@ronniebarker this is getting a bit OT now but I'd really be interested to see which bits of F# whitespace significance you find confusing. It's pretty simple - basically just indent to create a child scope, that's it. Most F# is pretty consistent in this regard across projects (more so in my experience than C#), with the possible exception being creation of records. Happy to take this external - slack or twitter DM. |
Beta Was this translation helpful? Give feedback.
-
@isaac_abraham I don't think it's OT. If people propose a #light mode (and even work on prototype) then this is the core of the issue. Why do many of us think whitespace sensitivity and optional semicolons (read as: mostly no semi colons at all) are a good thing while others seem to have real issues with it? |
Beta Was this translation helpful? Give feedback.
-
I think that my point is not really about F# as such, more one of the mindset of developers. We need to think long and hard about how we document the intentions that we are communicating and I, for one, like to have some creative freedom to allow me to present my creation in an elegant, easily understandable and readable form. Naming and use of whitespace are the two elements that I use the most when doing that. Languages that force a strict layout take that away from me. I also fight against many of the conventions that we use for naming. I like starting functions with a capital letter and have always hated javascript's tendency to camelCase instead of PascalCase methods. Functional languages like f# make that even more complicated - I seem to be forever staring at a line of code lately trying to undertsand if I As for the specific question, you asked me @isaacabraham, it's mostly the indentation I guess at the moment. I hate it. Tabs would be better - as I could set mine to be 10 spaces and make it clearer for my non-F# brain and the other members on the team could leave it at 1 or 2 if they wanted to keep it nice and compact, but F# went spaces. I think it's just to annoy me because I sometimes can't see that there is one space missing in my indentation that has some whitespace in-between and the compiler dumps all over me!
I know it is wrong and I accept that - but the intention doesn't always jump out at me as much. I just like being able to specify it and not care so much about the whitespace - use that to make the code more readable. |
Beta Was this translation helpful? Give feedback.
-
many people use 4 spaces indent and VS even gives you vertical lines. |
Beta Was this translation helpful? Give feedback.
-
@marchy most if not all of those features are already possible in .NET through F#. I would suggest you have a look into it if the features that you mention are crucial for you. Plus, it has the benefit that it is available today and if you are using .NET Core then you will already have it installed. (Random trivia - AFAIK some of the core members of Swift came originally from F#). |
Beta Was this translation helpful? Give feedback.
-
@isaacabraham I am familiar with every feature that has been on C# since C# 2.0, and every Swift and Kotlin feature since Swift 1.0 and Kotlin Alpha 1 (2 years before Google blessed it). F# is a fringe language, I'm sorry. It's ugly and it will never be destined for mass adoption. It does not have the same prerequisites for success nor adoption trajectory that Typescript has achieved, and it never will. From the sounds of your recommendation to look at F#, it sounds like you lack the familiarity with Swift needed to add value to the discussion. Swift and F# as languages are nowhere near the same ballpark. Kotlin, Swift and Typescript, yes. Let's try to be practical not theoretical here. |
Beta Was this translation helpful? Give feedback.
-
So, a couple things: with regards to codebase-wide fixes, https://github.com/dotnet/format is a thing we're working on. Now, as to your assertions about swift: you seem to take for granted that semicolons are bad and we'd remove them if we weren't concerned about back compat. No one on the team has said that, and it's certainly not what I'd do if I were making a new language today. Punctuation is important for readability and ensuring that what you think you wrote is actually what you wrote. As to associated types, static interface members, discriminated unions... All of these are on the docket for future versions of C#. Swift is a nice language. They've done some things I like and some things I disagree with. We're not going to ditch C# for it though, and regardless of anything else we're not going to remove semicolons from this language. |
Beta Was this translation helpful? Give feedback.
-
@marchy I would suggest you have an order of magnitude greater chance of deployment an F# on .NET than a Swift app on .NET. I wasn't trying to get into a whole "this language is better than that" debate - just pointed out that you said that C# is not suitable for you because it doesn't have language-level support for collections, first-class immutability etc. - F# has all of those. Whether you want to invest looking into it is your choice - I'm not selling you anything, and there's really no need to behave in such a rude or arrogant manner. |
Beta Was this translation helpful? Give feedback.
-
@isaacabraham thanks, I was trying hard not to come off as arrogant. It was genuinely pointing out that suggesting F# when the discussion at hand was the intrinsic limitations to modernization of C# (in this case semi-colons... but there is a long list of others) and pragmatic mass-adoption alternatives was very out of place. I get that on paper F# has some of these aspects, but it's a language with no mass-adoption potential especially in the light of Swift/Kotlin/Typescript alternatives. We've assessed Silver/Swift on .NET and it was not holistically viable in its form as provided by a 3rd party. I didn't suggest this, thus why asking Microsoft folks to chime in on an official consideration/stance. The things we ARE seriously assessing (as are many other companies who have .NET in their DNA) is Swift on AWS and Typescript/Express/Node as the contenders that C#/.NET is up against. And unless Microsoft takes a serious bet on the winning horse (which at this point is Swift, and absolutely not C#/F#), it's only a matter of time before the C#/.NET ecosystem will be nothing but developer retention and companies that are quite frankly STUCK with it, rather than WANTING to be on it. I know large companies who are already executing a strategy of minimizing C#/.NET surface area and spin up all new services/re-architectures on Typescript/Node/Express. We are trying very hard to NOT do that, and remain on .NET. The hard-headed stance on something as obvious as this issue/thread (ie: @333fred 'regardless of anything else we're not going to remove semicolons from this language') just validates that C# is too old / outdated to ever catch up – be it for technical or philosophic reasons – I don't know and am not trying to attempt to guess. |
Beta Was this translation helpful? Give feedback.
-
Maybe there are more important things that the team believe are worth investing time and energy into than removing semicolons. |
Beta Was this translation helpful? Give feedback.
-
Or rather that doing so would represent nothing but a massive waste of time and yield no benefits to developers, except that some segment of developers will now feel the impulse to go back and modify all of their existing code because they can. It's a huge amount of work, it creates more problems than it solves, it's a net negative in terms of productivity, it will inevitably result in a lot of ambiguities requiring a semicolon to disambiguate and it will invariably tie the hands of future language evolution. Not liking semicolons and demanding that a language that has them is somehow old and crusty (aka not "modern") is not a compelling argument. C# isn't supposed to be the one language that meets everyone's different stylistic demands. .NET was designed from the very beginning to support a wide variety of languages. Feel free to choose a language that has a syntax you'd prefer. |
Beta Was this translation helpful? Give feedback.
-
I can't speak to Swift, but JavaScript, PowerShell and Go infer the end of statements instead of requiring an explicit terminating semicolon and it's the most frustrating thing in the world. These languages use a simple straightforward rule that's easy to understand - if the statement is syntactically complete at the end of line, infer statement termination. As a consequence, they all have a nasty wart where this is illegal code:
You instead have to format it with the periods at the end of each line so that an implicit semicolon isn't inferred. Why is this a problem? Cognitive science, specifically studies on how people scan lines of text with their eyes (we use saccades), shows that punctuation (and small words) at the end of a line is extremely likely to be missed (not seen); the same content at the start of a line is almost never missed. So both these languages force their consumers to format code in the way that is most likely to trigger confusion by making it illegal for format code in the way that is least likely to do so. Note that this is not an issue of personal preference, but a direct consequence of the way the human visual system works. One caveat: If memory serves, the research was done on native English speakers, people who had always read left-to-right; I don't know how well this applies to non-native speakers who started with a language that reads in a different direction. |
Beta Was this translation helpful? Give feedback.
-
In Visual Basic the line continuation operator ( |
Beta Was this translation helpful? Give feedback.
-
The line continuation operator has been there since QBASIC. You could never implicitly split an expression over multiple lines in VB (classic or .NET), until VB.NET 2010 when they tried to make it optional to make LINQ feel less awkward. As I recall it took multiple releases of the language each reworking some specific cases where they could be removed without introducing ambiguities, and there are still numerous scenarios where |
Beta Was this translation helpful? Give feedback.
-
@marchy said approximately "Koolraap's thinking is completely invalid, one commit and you're done, no more semi colons" That one commit can cost millions of dollars. In boring enterprises like where I work, change requires testing, sign off, approvals, blah blah blah. The code base I spend most of my time in sucks. It's horrible, more than one developer has run from the room with melting eyes. But if I went and updated to C#10 and auto-formatted the code to remove ;'s it'd cost > million bucks to do a complete regression test. I know we don't have tests for everything the system does (well, we do. It's called "PROD"). Doesn't matter how correct the tools are, it does not matter how much you argue with "the business", they're not going to let something through without testing, because they value their application which they paid you and me to write more than our opinion on semi colons. In summary. Is my opinion "completely invalid"? I don't think so, but I bet I'd really enjoy discussing the issue with @marchy over a beer. |
Beta Was this translation helpful? Give feedback.
-
@marchy one more example. Once upon a time I worked upon an application used by millions of people to do their tax returns. The code had one global array for data with thousands of items with things like
We had a spreadsheet mapping the array indexes to something meaningful. So I wrote a little utility to fix the code so it read:
Great, right? Nope. I argued for weeks to get this change through. That was 15 years ago. I'm now older, wiser (synonym for jaded?) and more accepting that it's not my decision to sign off on risk, no matter how apparently small. It's the people paying me to write code for them. Do I like it? Nope. But in the end, it's not my money. |
Beta Was this translation helpful? Give feedback.
-
How about
I think removing semicolon will improve productivity, and worried of legacy project, we can solve with building options |
Beta Was this translation helpful? Give feedback.
-
Optional semicolon is a good idea. Yeah there is some edge cases. Mire than 99% times we are writing code that would not require a semicolon. So adding a semicolon after every statements for just that 1% of code is not worth it. I would just write that 1% in a better way to not require a semicolon. |
Beta Was this translation helpful? Give feedback.
-
That's exactly why I talk about typing an |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
All modern languages such as Kotlin, Swift, Go, ES7 does not need semicolon to end a statement. Can we make semicolon become optional?
Beta Was this translation helpful? Give feedback.
All reactions