-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Meta-issue for discussion of the proposal to make semicolons after statements optional #30347
Comments
Just my 2 cents, but coming from a JS / Android background, I'd love either "Semicolons - YES" or "Semicolons - NO". I do not think OPTIONAL semicolons are healthy for a development community for two reasons:
To keep an open mind, I'd love to hear more about the reasoning in support of optional semicolons. Do folks feel it will help adoption? Is it a stepping-stone toward a Dart v3 w/o semicolons? |
The bikeshedding in the JS community isn't over something purely stylistic. Semicolon insertion in JS (and some other "optional semicolon" languages like Kotlin) can have very dramatic effects on the semantics of the code. For example, consider: // Javascript
function test() {
return 1 + 1
+ 2
+ 3
}
console.log('Hello, world! ' + test()); // Kotlin
fun test(): kotlin.Int {
return 1 + 1
+ 2
+ 3
}
fun main(args: Array<String>) {
println("Hello, world! ${test()}")
} What do you think they print? |
(I am reserving judgement on the issue when it comes to Dart until there's a concrete proposal.) |
Make it an error to have statement continuations after the return line. Also, I'm curious if there's actually a problem here, given what go, kotlin, and swift have been doing. Do they report this as a static warning or error? I am not worried about "two ways to do it", there are infinite ways to do most formatting and conventions. I am confident that the combination of automatic formatters and style guides (both global and local per-team) will create cultural norms here. |
@sethladd Before we talk about all the tools that could be built to support this, could you maybe just elaborate a bit about what you see as the user benefit? How will this help us write better programs as a community? What "user need" is it targeting / solving? To be clear: I prefer languages without semi-colons, but I just don't quite see what this will add to the Dart community or how it will help the ecosystem overall, and that's what I'm trying to understand a bit. I'll await the proposal to see if it answers those Qs :) |
Modern languages are generally believed to be less boilerplate, more terse, and including language features working for you. For example, type inferencing is the language working for you. We could force you to right type annotations everywhere, or we can say "in many cases, we can infer it for you". Auto-inserting punctuation is another way the language can work for you. Also, there's an element of being seen as a light-weight, modern language and staying competitive. The trend in languages was to go to var, to go for closures, to go for |
The code above is valid in Javascript and Kotlin respectively. (But the important question to me is, can you guess what they print?) I think "make it an error to have statement continuations after the return line" is a perfectly valid part of a complete proposal, but I'd need to see the complete proposal before I could really say how valid it is. BTW, omitting punctuation isn't new. Perl, Fortran, even COBOL all had stuff like this. Lisp didn't even have semicolons. I would hardly say it's a sign of a modern language. |
Re-modernizing? But yes, good point, plenty of languages pioneered here. |
In fact, Perl went even further and allowed you to omit the |
So there are several problems that arise if Dart removes the semicolon requirement: With semicolons: print("hello");
() { print("goodbye"); }; Without semicolons: print("hello")
() { print("goodbye") } The first example would just print "hello", the second example could either print "hello" or throw an error, depending on how it's interpreted by the parser. This can become worse if someone does this: returningPrint() => print
() { print("goodbye") } Now, instead of the function returning There would be a lot of ambiguity introduced by closure syntax... who says it's a call + block or a closure? |
How do swift, go, and kotlin handle these cases? |
Go has a crazy syntax for lambdas which is whitespace-sensitive (you can't put a line break after the arguments before the return type, or some such). They also have a reserved word before the lambda which disambiguates between closures and calls. Swift and Kotlin use braces for closures. I haven't quite figured out the syntax exactly. Kotlin, as previously mentioned, makes choices that make its semicolon-insertion confusing and bug-prone. |
If there is a simple way to get rid of all ambiguities, then getting rid of semicolons would be great of course. |
We would make semicolons optional mainly to support:
Idiomatic Dart code would not contain semicolons, "Effective Dart" would tell you to omit them, and dartfmt would probably strip them. Note that Ruby, Scala, Go, Lua, and Python all allow semicolons and yet semicolons have not infested their ecosystems. :) |
yes god { |
Excuse me my freshman impertinence but I want to place some biased yet sincere questions here. Isn't semicolons at the end of statements a part of solid complex language syntax? (sorry for clumsy English) |
@Kirrrr I also don't mind writing them, but if the Dart team sees a good way to get rid of them without causing serious downsides, I don't see why they shouldn't make an attempt. I think non-nullable-, union-, immutable- types and extension methods have much higher priority, but that doesn't mean I'm against getting rid of |
Good faith questions are always welcome. :)
Nope. It's an arbitrary choice. Some languages have nice, clean, solid syntax but no semicolons (Lisp, Smalltalk, Python). Perl does require semicolons but is notoriously tricky. Complexity is never a goal, it's a cost we pay to attain other goals. Simplicity is the goal.
It depends on the language and the rules you use to treat newlines as significant. If we do it well, no. We wouldn't make them optional if it caused significant changes to the way people write their Dart code.
Not really. It's just a character. There's nothing magical about ";" compared to "\n", ".", etc.
Some of the languages with optional semicolons are pretty similar to Dart syntactically — Swift, Kotlin, and Scala in particular.
Yes. It's a pretty small change. Go made semicolons optional after the language was in wide use without any major problems.
Users choose products for both technical and emotional reasons. Programming languages are visual products (for most users) and the visuals matter. If most of our users find that Dart looks nicer and is less error-prone without requiring explicit semicolons, it's a win. |
I would recommend either Semicolons must be used or no semi-colons. If we are going to take the effort to change the language regarding this, it needs to be clear and not a patch intermediate step. Optional semi-colons serves no practical matter nor resolves a problem. It would only exist as a migration path and, if so, thus should be avoided as it easily could be left in the SDK for years due to debate. The Dart language isn't against introducing breaking changes (see: Dart 2.0). So again, the decision should be either with semi-colons or no semi-colons. In my opinion, I say leave the semi-colons in. It fits Dart's intention of not being surprising to developers. |
Coming from hobbyist languages like BASIC and Lua, I would love to see Dart get rid of (or at least make optional) the ending semi-colon. For me, it makes the language appear less fussy and more readable. |
Well, migration is a problem. :) Also, allowing semicolons makes things easier for tools like code generators that produce Dart source code and don't want to have to fuss with newlines. Python, Ruby, Kotlin, Scala, and Swift all allow semicolons. Despite that, they all have consistent clean ecosystems where semicolons rarely appear in user code. |
Migration is always a problem (see Dart 2.0). But should mean making it optional. Does the language really need to make semicolons optional? No, it doesn't. The language is best when designed for the developer's use as a consumer of the API. Whether tools like semicolons is irrelevant. I think the semicolons should stay and not be optional. It makes the language easier to understand especially when different examples of the code are given. And that is Dart's best feature, not being surprising to the developer and using tried and true concepts. Optional semicolons causes more confusion for new users as well as teams trying to come to a standard. The Dart Style Guide would have to choose a side and that'll decide how most users go. |
I was on the fence about optional semi-colons, but have been persuaded the arguments made above: If the Dart Style Guide recommends no semicolons and Overall, I think it's a good thing if peeps go with the Dart Style Guide out of the box! The fewer style discussions we have the more time we have to write our apps. As a bonus, it makes it easier is to read through other code bases as well :) |
I think it's impossible to have an informed opinion without knowing what the concrete proposal is. If it's like more like JavaScript or Kotlin, where you can't tell at a glance what the code does, and where in some common cases you can write code that actively looks different than what it does, then it's probably a mistake. If it's more like Lisp, where there's no ambiguity, then it's probably fine. In between these poles are languages like Pascal, where semicolons are optional in certain cases and must be omitted in certain cases and required in others, but that doesn't gain you much (maybe slightly cleaner lambda block syntax though the |
@zoechi I think it would be regrettable not to appeal to JS developers , especially for those looking for an alternative to Node. Using |
I like that feeling, though 🤔 |
Semicolons are really just noise. If you need to write something like:
then there is something else wrong than just needing semicolons. IDE can warn you in instances where you might get tripped up, but overall, removing semicolons is much cleaner. Coming from Kotlin, swift, JS, I keep forgetting to put in I mean the examples listed above are valid, however given a strong direction on what it prints just requires a little more learning.
if an operator is listed on the next line of a return statement, dart should just collect them or just make it an error to place an operator on the next line as first statement. |
It is uncommon to see semicolons in the code written by developers who switched from Java to Koltin, even among those who coded in Java for years (including myself). An exception may be one-liner lovers, who like e.g separate a statement and print. In Flutter I often make mistakes by either not adding the semicolon or adding it where it is not necessary - examples below Example 1
Example 2
If you implement this right, you unlikely to break anything by making this optional and I'm pretty sure that majority of developers will not be using semicolon inference if it becomes an optional language feature. |
I'm on my first day with Flutter/Dart, pleasant experience, except: I come from Swift, Kotlin, Python, JavaScript. Semicolon are something of last century. Please, please dear Dart team: make the semicolon optional. We don't need them. Listen to your users to 1.) make sure that Flutter/Dart gets a broad adoption so that Flutter/Dart doesn't drown away like other Google projects |
Is there any insight from the dart team on how do you see this proposal ? |
+1 for NO semicolons For some reason, I've got used to no semicolons in JS very easily. But I find it much harder to get used to semicolons in Dart again. |
This issue isn't a proposal, as much as it is an indication of desire. Wanting to have a roof over one's head is a valid desire for a solution to a real problem. But it's not equivalent to an architectural blueprint of a specific home someone could build. :) I spent a lot of time earlier this year and last year working with the rest of the language team to design a concrete proposal that would satisfy this desire. So far, we have yet to figure out a design that we feel comfortable adding to the language. This is a particularly hard problem in Dart because of the syntax it already has. Most other languages with optional semicolons were either designed that way from the start (Ruby, Python, Scala, Swift) or had the luxury of starting from very simple grammars (Go). Dart's C/Java/JS-esque syntax is neither. It's a very dense syntax that overloads many tokens to mean different things in different contexts and doesn't rely heavily on keywords. That makes it really hard to determine which newlines are meaningful. I wrote up a summary of my investigation so far here. We haven't given up hope, but we are tabling it for now to focus on more impactful features like non-nullable types and extension methods. |
I am unable to read the whole thread, but I will address some concerns that I saw popping up often. An example of ambiguity was this:
The concern would be that this could be either 1. calling the getter
Furthermore, using quite simple code analysis, once can figure out if A lot of the issues can be actually solved by adding a continuation character in order to clarify ambiguity when the statement on the current line is valid. For example, the following code...
would just return 2, with a warning that the lines after the
or in the following way (since
|
Another concern was method chaining. The following example was given: var buffer = StringBuffer()
..write(copyright)
..writeln()
..writeln("// GENERATED FILE, DO NOT EDIT!")
..writeAll(generatedMethods, "\n");
var text = buffer.toString(); The problem would be that, theoretically, In this case, some simple smarts is needed. You can't |
There are a large number of examples where grammar rules, type analysis or common sense can tell you that the next line should be a continuation of the previous one. The trick is that we need to figure this out while parsing (which pretty much precludes type analysis) and in a way so that we can supply help while the code is being written, and that we must define a finite (preferably small and consistent) set of rules that covers all these examples. A 50-point set of exceptions is not good for users trying to predict what their code means. Simple rules like "if the following line can continue, then it will" is dangerous, so is "if the following line cannot continue, then it won't" because either will require the author to understand all the fine points of the Dart grammar before they know whether they can omit a semicolon or not. Not saying that the suggestions here are not reasonable, just that they, by themselves, are not enough. |
The main problem with this is that there is actually a significant number of cases in the wild where this already happens. People do end up with fairly long types (usually function or generic types) and variable names sometimes and wrapping does occur. Breaking that code would make this a harder feature to ship.
We don't want to rely on type analysis to parse. That would mean the grammar isn't context free, which is widely considered a bad idea in programming languages. C and C++ are famously not context free and it causes no end of headaches. Search for "most vexing parse" for one example. In particular, consider that dartfmt, by design, does not do any type analysis. This is important because we want to be able to format code that may have type errors or that imports other files that aren't available. If you need types to parse, it means dartfmt can no longer do that. Your other points about using the trailing token or the first token on the next line to tell when to ignore newlines are correct. That's what all the proposals we've considered do, and those cases aren't particularly problematic. :) |
@munificent for sharing your experience investigating this. I am not a language expert. I do wonder which is easier to implement: remove semi-colons or having them optional? I would imagine the former is easier as the latter would require additional work like tracking where to insert a semicolon and doing that. However, the former would still require determining what is a new statement or end of a statement. I ask cause my preference is the former as I do not think optional semi-colons provide value, if they are optional, so they might as well not be needed. |
To a compiler, it's exactly the same. If all semicolons are optional, then the language grammar has to work without any semicolons, so it has to be able to do everything that the no-semicolons parser does. Making semicolons optional is not a goal. The goal is to make them all go away, they do indeed not provide any value in the long term. However, when we implement language versioning it is possible to make a breaking syntax change between language versions, so it is possible to have Dart 2.8 with semicolons and Dart 2.9 completely without semicolons without having to worry about backwards compatibility. You'd have to migrate all your code to be able to run it as Dart 2.9, but that migration should be "trivial": parse all the code into a syntax tree using the 2.8 parser, then emit that syntax tree using the 2.9 Dart formatter. Nobody wants to insert semicolons. What we want is to break statements. A semicolon is an explicit statement break, so that's easy. Without semicolons, the parser has to divine where to break the tokens into separate statements using other rules (like "only at newlines", "not if followed by X", "not if preceded by Y", "unless it's an odd line on a Thursday"). This is doable, but we also want the set of rules to be predictable, which most likely means simple, memorable and few, so users won't make mistakes all the time, and we want the syntax to allow most of the code that is already written if we just remove the existing semicolons. We have not found a set of rules satisfying this—the rules are either too complex and irregular or too simplistic to allow the code that people are already used to writing. The former means that we can't really expect code authors to get things right, which is a bad user experience. The latter means that we would require everybody to start writing code significantly differently from what they do now, and when they don't, they get things wrong, which is again a bad user experience. (This is also why @munificent keeps saying that listing some cases that seem simple is not an argument for anything, we need the full set of rules for handling the entire language syntax so we can check how they interact with the body of existing code, which could include all code on Pub and all Dart code on Github, in order to be able to properly consider the complexity/consistency trade-offs and see which edge cases of existing code would break.) |
Maybe by adding some flag in pubspec.yaml, the packages that don't have it should be used with semicolons (the compiler, etc, will know how to handle them) as long as environment sdk ('>=2.0.0-dev <3.0.0') allows it. For the new/updated packages you will go without semicolons/migrate old project. About removing semicolons I am very sure that there are places where they can easily be removed and some places where needs more thinking (there was a time, some years ago, when this breaking changes were more easy to be done. Now with all the houses along the road it's getting harder or impossible to make the road a highway) |
That's basically what the new "language versioning" stuff does. It lets us use the minimum version in the pubspec's SDK constraint to infer what version of Dart your package is operating at. This is, for example, how users will opt into the non-nullable type changes, which are breaking. We've designed "language versioning" as its own feature so that we can also use it for other future breaking changes. Semicolons are definitely another place where we could consider using this feature, because it would enable us to make other technically breaking changes to the grammar in order to simplify the newline breaking rules. |
Make them optional. Thank you. |
Personally, I really don't like using Semicolons;;;; it is not necessary these days.. See Python, Go, it is more readable. and nowadays compilers can recognize without semicolons. you don't have to put semicolons even in Javascript/Typescript. |
Great idea, add my vote. I spent years working in languages that contain semicolons. However, after few months with Swift I could see they nothing but extra keystroke (when writting) and visual spam (when reading)... I even persuaded my team to stop writing them in JS/TS. Please add "optional parenthesis in conditionals, cycles and similar" to discussion as well ("optional" just for backward compatibility). Similarly to semicolons they are just boilerplate both when writing and reading. |
My apologies for such a long comment Everything I'm about to write is my opinion, as shaped by my experiences in production. Also, I love Python, I use it all the time so my opinion has nothing to do with Having said that this how I see the whole semicolon/braces/C family Dart isn't Python, it isn't sound to attempt altering core design semantics of a "C family", means parentheses, block braces, and semicolons. The question isn't whether Python is 'correct' or not, the question is whether The consideration of arrow functions as a parallel case vis a vis semicolon One does not perform an in-situ engine overhaul/redesign, of a reliably designed Supposing the core team decided to remove semicolons... Even with a vastly expanded support and tooling team to assist the core Dart is in the middle of re-inventing itself and repositioning itself for All of that effort spent, to successfully remove semicolons... By comparison... The recent Flutter on desktop as a serious competitor to electron, now that would be something Look I like python, I write python, I also compile my python using pyinstaller. Instead, I think: "There's Python over there, and there's Dart over here." There isn't some Regarding the visual 'noise' of semicolons and braces... Sure Python is easy to read, but to be honest, JS isn't that hard to read, and It's not sensible to paint all programming languages with the same "JS treatment", I'm going to prefer keeping semicolons (not as optional) and About semicolons... After a while, your brain tunes them out and they cease to be so-called There is a panoply of languages for people who dislike the C family semantics So I'm all for better code editor tooling intelligence, and If you're using the newer ML based editor enhancements (tab nine), then chances |
But that's the very definition of noise. Just because your brain learns to ignore it, doesn't mean it isn't there, just like the background hiss in analog music tapes - you don't really notice it until it's gone. If semicolons can be made superfluous (which according to this issue is a big "if"), then they become noise and should be removed. |
I think we can make semicolons optional in most clear situations, and keep the semicolons in some rare ambiguous situations. Code without some redundancy semicolons or parentheses will make code clean and more readable and less typing. We can reference some ES 6+ design ideas to make dart writing more efficient and intuitive. |
Here is what eslint try to do with semicolon. Here is its implementation. |
Modern languages, like Swift Kotlin has optional semicolon, and it is great. |
I just wanna ask. Can we get optional semicolon in 2020 / 2021 ? |
Languages like Swift & Kotlin with "Semicolons - NO" have in fact optional semicolons. If you want semicolon at the end of each line, you can write it. Compiler will let you. However, no one does it. Neither 1. nor 2. of your points are observed for these languages. Semicolons should be optional but there should be language wide guideline to not to write it. In case of Dart it will render legacy code with semicolons compilable. For new code, semicolons will considered be obsolete. |
Completely untrue. I write a semicolon at the end of every line of Swift and Kotlin. I'm not the only person. |
As always, exceptions, outliers and "I will do it my way people" exists. That's the point of optionality, to allow for some freedom, right? Still, every style guide for Swift I have ever come across (corporate, open source or otherwise) tells you not to use them (including the one from Google). That effectively switches them off for wast majority of code and it is unlikely that beginners will come across such non-standard code. I teach Swift at a university and I've not seen semicolons being used at lectures / tutorials or similar. |
Closing the present issue; for future discussion please use the main language issue for this: dart-lang/language#72 As for current status, please see dart-lang/language#72 (comment) |
This issue is to provide a forum for community discussion and feedback related to the proposal to make semicolons optional after statements.
This entry will be updated when a proposal is available.
cc @munificent @eernstg @floitschG @lrhn
cc @Hixie
The text was updated successfully, but these errors were encountered: