-
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
Make new optional #20750
Comments
This comment was originally written by @zoechi What about cases without a named constructor or do you propose to use only named constructors? |
This comment was originally written by norman...@gmail.com 'new' makes it clear that we instantiate new object, not referencing to existing variable. |
No. Nameless constructors are fine the way they are.
For consistency sake I would say make var buf = new StringBuffer(); I think it's pretty clear what is going on here. Even if |
This comment was originally written by @Emasoft Please don't. That would make the code much less readable. You would not be able to distinguish methods calls from class instantiations anymore. var car = Car.new(); It is completely useless, and it would drastically reduce readability of code. |
This comment was originally written by @richardeakin
In other languages that don't require the new keyword to make an object, like C++, python, and newer language's like Apple's swift, method calls and class instantiation is completely distinguishable. The reason is simply that the way you write the code makes it clear (method names start with lower case, classes start with upper case). In all practicality, this is all the information you need to determine when a new object is constructed, as 98% (or more) of all code out there follows by this simple style rule. I'll even go as far as to say that it really doesn't matter anyway, I've never had a problem with 'knowing where something was originally constructed' using the C++ standard library (constructors look_like_this()), methods can always return a newly constructed object and you would not know at the call site. If one is worrying about something like where objects are constructed, there are probably much larger things wrong with the structure of their codebase. |
Added Area-Language, Triaged labels. |
This comment was originally written by nino.porcino...@gmail.com if 'new' is made optional, then also 'const' (from constant constructors) should be optional too. The semantic should be: var p = Point(); // alias for var p = new Point(); if Point is normal constructor |
No, optional const has it's own issues. See issue #18241 |
If the use of |
Since we have factory constructors, there really is no functional distinction between: class C { factory C.foo() => expr; } and class C { static C foo() => expr; } Constructors are intended to be a recognizable way to get objects of a type. If I want a Foo, I'll look at Foo constructors to see which one I can use. The reason factory constructors exists is that if you use a constructor, then the call points use "new", and then you can't replace the constructor with a static function. If there hadn't been a "new" operator, and being a constructor was a property of a method, not of its usage, then there would be no need for factory constructors. (By extension, a feature that makes sense for factory constructors, like being a delegating factory constructor, could just as well apply to all static methods). |
This comment was originally written by @seaneagan
Yep, the api doc tool could even consider those to be "Constructors" and group them for the user. With the current setup if the api user needs to first look through the constructors and static methods to determine all the ways to create an instance, and they need to remember which category each falls into rather than just remembering the name.
But as an api user there's nothing that guarantees me that the api author won't refactor to a static method, if
Of course we would need generic methods (issue #254) for that, which would be great to have anyways. And there would need to be a way to create an unnamed static method, which wouldn't be too difficult to come up with a declaration syntax for. |
This comment was originally written by @Emasoft A programming language must be EXPRESSIVE. Because if it is not, it is not easily readable. And if it is not easily readable it is much more difficult to learn, much more difficult to find errors in the code causing bugs, and much more difficult to integrate the code written by other developers and to understand how it works. Being EXPRESSIVE is now considered a major feature of a language. And: var car = Car(); is less expressive than: var car = new Car(); because just reading the former I cannot infer if Car() is a Method or a Class, while if I read the latter I can infer that Car() is a Class at a glance. This is why using the "new" keyword is so much better than not using it. There are other possible advantages, but this is the main one. |
Incorrect, you can infer Car is a class because the C is capitalized. |
This comment was originally written by @richardeakin
I agree, and moreover you really don't need to know whether the method is a constructor or a class - you just need to know that it returns a new variable of type Car. I believe the use of new keyword is more familiar to those who have had the habit engrained into them by working with java, javascript, or c# for a long time. Many others find the following statements much more expressive: var pt = Point( 2, 3 ) + Point( 4, 5 ) + Point( 6, 7 ); as compared to what is currently required (and appears to only be for stylistic and habitual reasons): var pt = new Point( 2, 3 ) + new Point( 4, 5 ) + new Point( 6, 7 ); Honestly, when I was reading response #12, I thought he/she was going to be in favor of making new optional until he/she began writing example code! About expressiveness, I think it is more than just being readable - it is also about being able to efficiently code your thoughts. I think writing new 3 times in one line hinders this goal, IMO. |
This comment was originally written by @richardeakin Sorry for typos, meant to write: "...you really don't need to know whether Car() is a method or class constructor..." Anyway point being, it returns a variable that didn't exist before that line, that is sufficient. |
This comment was originally written by @Emasoft
Sorry to disappoint you, but in Dart there is no guarantee that a class name is capitalized, and no guarantee that a method name is not capitalized. Capitalization is not part of the Dart specifications, is not enforced by the compiler, and this practice is then completely arbitrary. I use Dart libraries with all sort of different capitalization styles. You cannot base your inference on this. This is why you need the "new" keyword to distinguish the class from the method.
EXPRESSIVENESS is not CONCISENESS. It is just the opposite. In fact the best designed language is the one that reach the right balance between EXPRESSIVENESS and CONCISENESS. By definition: EXPRESSIVENESS: "The amount of information about what the code does that is explicitly expressed by the language syntax and keywords. Also referred to as verbosity." CONCISENESS: "The amount of compactness (less number of characters needed to be typed) allowed by the language to write syntactically correct statements. Also referred to as brevity." The former improves the amount of things you can understand reading a code statement, the latter improves the speed at which a code statement can be read (or written). var pt = new Point( 2, 3 ) + new Point( 4, 5 ) + new Point( 6, 7 ); is MORE EXPRESSIVE and LESS CONCISE than: var pt = Point( 2, 3 ) + Point( 4, 5 ) + Point( 6, 7 ); because you can infer MORE things (that you are creating some new Points objects instead of calling a Point method for example) but you need more time to read it. In an hypotetical top EXPRESSIVE language would be like this: define new variable ofType:Class(Point)) withName:pt = define new Class(ofType:Point)( withParameters: x:2, y:3 ) + define new Class(ofType:Point)( withParameters: x:4, y:5 ) + define new Class(ofType:Point)( withParameters: x:6, y:7 ); While that would be very expressive and clear (you will understand even if you don't know the language) that would be not CONCISE enough, because it will be slow to write and to read. This is why EXPRESSIVITY is reduced with a more CONCISE syntax: var pt = new Point( 2, 3 ) + new Point( 4, 5 ) + new Point( 6, 7 ); This syntax is a good compromise between EXPRESSIVENESS and CONCISENESS, because it is as compact as it can be without leaving space to any ambiguity. This other one instead: var pt = Point( 2, 3 ) + Point( 4, 5 ) + Point( 6, 7 ); is too much CONCISE, because it is so compact that it leaves some things undefined, causing ambiguity in reading the code. You must also consider that all modern editors have an "autocompletition" feature. This means that sometimes it is quicker to write: new Point() than to write: Point() and this is because you only need to type 'new P', then the autocompleter will show a list of Class Names beginning with 'P' to select from and press enter. |
You will still be able to type 'new P' afterwards. This proposal is to make
False implication. When you write the letter 'P' your auto-completer will show all these in either case. The reason being is you might be referring to a static method on a class so the auto-completer will currently suggest classnames that start with the letter 'P' to complete. (again, no change) |
This comment was originally written by @zoechi Requiring |
This comment was originally written by @Emasoft
Not true. If the "new" keyword is present, the autocompleter will know that next comes a class name, and nothing else. Because only class names require "new". If the 'new' keyword is missing, the autocompleter have NO WAY to know if you are going to type a class name or a method name. And neither someone who read the statement. And that is exactly because the new keyword add an information otherwise lacking.
A style guide is nothing more than a suggestion if it's not enforced by the compiler. And in the real world you cannot rely on something arbitrary. Even if I always remember to follow the guidelines in my part of the code, other programmers working at the same project could not. And external Dart libraries we use on the project are often written with the more diverse styles. Those ported from javascript for example rarely use capitalized letters for classes. And nobody will assure you that in the libraries you imported there are no methods with capitalized letters with the same names of some of your project classes. You would always risks to mistake a Color() method with a Color() class. This is why a 'new' keyword is so important to have in a OO language. Removing it to save yourself the trouble of typing 3 petty characters is not worth the resulting loss of expressiveness and all the bugs deriving from it. |
The percentage of people who do not follow the style guide for method and class names will probably be minuscule (Probably some C# programmers). So such ambiguity is tolerable. And, even then, analyzer should emit a warning so this is really not a big issue. I believe removing "new" is the way to go. |
[Edited with some more details] I realized that some of the community really likes the However, most of what I hear is that "its already here, and its not a big pain, so lets keep it" and "it can lead to more info if a new object is being created". The only language that needed it was C++, but definitely not needed in Java or C#. From personal experience, I have never seen the "less info because of lack of new" problem in our 10000 file python codebase... for the simple reason that all class names are Capitalized. And pep8 / pyflakes tests automatically fail if that's not the case (I don't remember the last time that happened because someone forgot to Capitalize the class name). Also, I was surprised to know that the Why did we agree to get chained to the unessential The only reason to keep In this article, Bruce Eckel scratches his head on why Java didn't drop the
|
The Dart: class A {}
main() {
var B = A;
new B(); // [error on line 5] 'B' is not a type.
} Javascript: function A() {}
var B = A;
new B(); // returns instance of A. This actually works! Dart could be using the P.S. Just to make things clear: I'm still against the enforcement of |
I think this should work with dart-archive/dart_enhancement_proposals#4 |
I think this may be the way to go, especially with the new linter. For example, you could then make sure the code base always uses uppercase for classes. I would prefer removing new keyword completely, but I think this would be better, then the current situation. |
FWIW this would help Flutter code, which create a lot of new instances in build() methods. |
Kotlin (language for JVM) also omits the new keyword. Look at type safe builders in Kotin. They are so beautiful to work with and UI object hierarchies can be constructed with ease and readability is terrific! Dart really needs syntactic sugar here - making new optional would help a bit. verticalLayout {
val name = editText()
button("Say Hello") {
onClick { toast("Hello, ${name.text}!") }
}
} |
Optional new is an accepted feature: #27154 |
Here's my two cents on the subject,
After new being optional, it will be great if i can write |
@hooluupog What? The Dart design team already made the code unreadable enough making 'new' optional. Now you suggest to make type names optional? How the hell I'm supposed to know what this line of code means, for example?
Somebody is forgetting that readability and understandability of code is the MOST IMPORTANT FEATURE of a programming language. Otherwise we would all be better to keep writing in binary 010101... |
@Emasoft I do not suggest to make type names optional.In fact,I fully support strong type. What i mean is to remove unneeded redundancy. Even in Go(which is a very opinionated language),I |
@hooluupog I can still read the type in your Go example. The A is at the right side of the assignement operator. Not so in your proposal. At the right side of '=' you don't have type names anymore, and this is confusing. Showing it at the left side is not enough. Not only I cannot use the 'var' to infer the type, but also because If I can declare a List just like you say:
...then I should be able to pass the same expression to a method with the following signature:
..resulting in:
But then how I'm supposed to know what this line of code means? Can you see what the problem is? |
That particular shorthand is unlikely to be accepted. Apart from the lower readability, it's also ambiguous. It looks simple here because the List<B> list = [(x + 2)]; It's very non-obvious that you need to coerce List<B> list = [.foo(x + 42)]; would mean that the omitted thing before the |
@irhn That Readability must be paramount. Do you know that on average we spend 87% of the development time debugging and looking for errors in the code and only 13% of the time actually writing the code? |
I don't think the I also don't think writing less code is an important goal, but more code is more to read and redundant information, like repeated type annotations, often make code harder to read, which should be a good enough reason to try to get rid of them. |
The |
It takes as many space as any other character ;-) and there are no other places where |
Closing: With the feature specification on implicit creation, it has been decided that Dart will have the feature which is requested here. ;-) For an instance creation expression (say, Implementation of this feature is ongoing. |
Cool! is there a tracking issue for the implementation? |
Yep: #30921. Note that the 'Specification' subtask isn't checked, but that is the language specification proper. The design has been finalized and agreed to, and it is documented in the feature specification for implicit creation. That material will later be integrated into the language specification. |
Guys, from my point of view having "new" keyword for instance creation and without it, seems like noisy Will be new keyword removed in future completly ? |
No promises. I hope it will be removed at some point, but it's a low-priority and heavily breaking change, so the cost/benefit ratio is not in its favor as a stand-alone change. If we have another related language change, we may be able to roll the removal of |
Eliminating A lot of valuable work has been done in the area of lints for Dart, and it seems that the community is quite happy about having support for specifying various constraints on code. The ability of the |
I see how
new
makes it familiar to new programmers but thenew
keyword is really not necessary in the end. Dart has named constructors and static methods and it is up to the library maker to decide which is appropriate to use. Currently named constructors need `new' while static methods do not. My focus here is to relieve the programmer of having to remember what side of the bed the library developer woke up on and remembering do I need the new keyword or not.Story time:
One day a library developer woke up and said parsing ints from strings is "discovering" the int so therefore it is not a constructor and a static method instead: Integer.parse(); was born. The library user MUST NOT use
new
to construct this Integer. Then another morning a library developer makes Element.html() and this time he think this is a constructor. The library user MUST usenew
to create his Element. This requires the library user to stop and think, do I neednew
or not?, when really in the end the library user just wants an object created; it doesn't matter how it's made.Before:
After (optional):
A discussion in issue #18241 talks about making
const
andnew
together being optional. This issue was created to focus on just making thenew
keyword optional.The text was updated successfully, but these errors were encountered: