const/new

80 views
Skip to first unread message

kc

unread,
Apr 9, 2015, 12:26:00 AM4/9/15
to core...@dartlang.org
Lasse made a couple of suggestions:

- Make "new" optional.
- Make "const" be an expression modifier, not a constructor call modifier, and inside the expression, all map and list literals are automatically const, and all constructor calls are also const invocations ("new" is not allowed, extra const prefixes are ok if you want them, so this is backwards compatible).



At the moment const/new undermines the declarative and dsl-ish quality of Dart:

1. 'const' example

// Before:
var lst = const [const Point(1,1), const Point(2,2)];

// After:
// the const-ness applies to the contained objects.
var lst = const [Point(1,1), Point(2,2)];

// After shorthand:
// const applies to rhs
const lst = [Point(1,1), Point(2,2)];




2. 'new' from a Sky example

Would be more dsl-ish without new.

 
UINode build() {
   
return new Container(
      children
: [
       
new Button(key: 'Go', content: new Text('Go'), level: 1),
       
new Button(key: 'Back', content: new Text('Back'), level: 3),
       
new Input()


       
// PopupMenu requires a PopupMenuController and should be wired up
       
// to a button to create the controller only when the menu is open, etc.
       
// new Container(
       
//   style: _menuStyle,
       
//   children: [
       
//     new PopupMenu(
       
//       controller: controller,
       
//       items: [
       
//         [new Text('People & options')],
       
//         [new Text('New group conversation')],
       
//         [new Text('Turn history off')],
       
//         [new Text('Archive')],
       
//         [new Text('Delete')],
       
//         [new Text('Un-merge SMS')],
       
//         [new Text('Help & feeback')],
       
//       ],
       
//       level: 4),
       
//     ]
       
//   )
       
// ]
     
);
 
}
}
 



My understanding is that with function generics 'new' could be optional.

K.


 

Lasse R.H. Nielsen

unread,
Apr 9, 2015, 2:53:33 AM4/9/15
to kc, core...@dartlang.org
On Wed, Apr 8, 2015 at 3:44 PM, kc <kevin...@gmail.com> wrote:
Lasse made a couple of suggestions:

- Make "new" optional.
- Make "const" be an expression modifier, not a constructor call modifier, and inside the expression, all map and list literals are automatically const, and all constructor calls are also const invocations ("new" is not allowed, extra const prefixes are ok if you want them, so this is backwards compatible).

The latter of those suggestions is on my list of things to make DEPs for (below allowing both types of optional parameters on the same function).
I hope to get time for those ... real soon now.
 
...

My understanding is that with function generics 'new' could be optional.

I don't expect that to be generally the case. Generic functions would mean that you can make factory *functions* that pass type parameters to constructors. It wouldn't allow you to just omit the "new" for an actual constructor.
Also, there would be no way to make a static function called Foo without shadowing the Foo class. If you have a Foo class, writing Foo(42) won't call a constructor.

(That said, making "new" optional is still a personal long-term goal :)

/L
--
Lasse R.H. Nielsen - l...@google.com  
'Faith without judgement merely degrades the spirit divine'
Google Denmark ApS - Frederiksborggade 20B, 1 sal - 1360 København K - Denmark - CVR nr. 28 86 69 84

Benjamin Strauß

unread,
Apr 9, 2015, 4:21:52 PM4/9/15
to core...@dartlang.org, kevin...@gmail.com
(That said, making "new" optional is still a personal long-term goal :)

As a new developer learning dart, i would be slightly confused why there are three different ways to create an object.

new List(); // normal way
List.new(); // metaclasses (if/when gilads DEP will be accepted)
List(); // optional new keyword

While i see the benefit in metaclasses, i am not sure what would be gained by making new optional, other than typing four less characters.

Why would you like ìt to be optional?

Austin Cummings

unread,
Apr 9, 2015, 4:35:06 PM4/9/15
to Benjamin Strauß, core...@dartlang.org, kevin...@gmail.com
I agree with Benjamin. I've heard from new developers that Dart is unfriendly to them (mostly because the lack of documentation). Having three different ways to create objects, including the optional new keyword, would just make Dart a little more complicated. Which is contradictory to what Dart is.

--
You received this message because you are subscribed to the Google Groups "Dart Core Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to core-dev+u...@dartlang.org.

Günter Zöchbauer

unread,
Apr 10, 2015, 2:47:08 AM4/10/15
to core...@dartlang.org, benm...@gmail.com, kevin...@gmail.com
The benefit of omitting new would be that it doesn't matter whether you use a named constructor or a static method to create a new instance. I find it rather annoying that I have to go back and forth several times when I want to instantiate a class.
I write `new SomeClass.` and investigate the autocompletion list. Then I decide which constructor I need, only to see that the analyzer shows a warning which I have to investigate, only to learn that the constructor I choose is actually a static method.
Then I remove the `new` to be able to move on.
After a few lines I learn that there is an even better fitting way to create an instance of the class and I change my code accordingly and get a warning again because this time it actually is a constructor.

I find this quite bothersome and can't see any benefit at all in writing `new ` especially when investigating new APIs which is hard enough by itself most of the time.

Instantiating from a metaclass is unique enough for me to accept a different way of instantiation but would of course prefer it to be uniform.

Rich Eakin

unread,
Apr 10, 2015, 12:08:33 PM4/10/15
to Benjamin Strauß, core...@dartlang.org
On Thu, Apr 9, 2015 at 3:52 PM, Benjamin Strauß <benmastra@gmail.com> wrote:
While i see the benefit in metaclasses, i am not sure what would be gained by making new optional, other than typing four less characters.


In the small example above from sky, it is actually 15 x 4, so you'd be typing 60 less characters for one piece of UI construction.  To me not having to do that is a huge improvement in quality of life. 
 
Why would you like ìt to be optional?


Other than Günter's explanation below, which I agree with, my opinion is that having to write new 15 times in a small piece of code makes it less readable, especially from a declarative standpoint.

Lasse Reichstein Holst Nielsen

unread,
Apr 11, 2015, 5:32:41 AM4/11/15
to core...@dartlang.org, kevin...@gmail.com
I don't want it to be optional, I want it to be removed completely - I just don't think that's likely to succeed, so the compromise is to make it optional, which will be a backwards compatible change.

Making new optional is not only about not typing four characters - but that does add into it too.
The four characters are redundant. It's statically detectable that I'm calling a constructor, and not having a "new" in front is known to be an error. Writing redundant and unnecessary stuff is just annoying, and getting rid of the annoyance is an improvement in itself.


It could also remove the need for non-const factory constructors completely. There is no real difference between a non-const factory constructor and a static method, except that the former needs to be called using "new" and have the surrounding class as return type. 

It has been argued that having constructors be different from static functions makes it easier for the user to see what is going on. You can *see* that you are creating a new object.
That's just not true. We have factory constructors that don't create new objects, and we have static methods that do create new objects.
It does help with naming, though - if you write `new List.fixed(...)` you don't need the constructor to have a name that says that it creates something. A static function would probably have been named `List.createFixed(...)`. I think that's only a matter of tradition, and we can still use `List.fixed(...)` as a constructor without getting confused - it works for Scala.

So, we have some classes with static factory methods (Uri.parse(...)) and factory constructors (Uri(...)) where the latter require "new" and the former does not. For `Uri`, that was a choice, and I think the right one, but it's not without problems - it's not easy for a user to see which members are constructors and which are static methods. If you could call them in the same way, then the suer doesn't have to know - the static class API is indifferent to what is a constructor and what is not.

Some classes have static factory methods that are asynchronous. You can't make these factory constructors because constructors must return the correct type - which is not a Future.
This means that some APIs will have both normal constructors and async factory methods, and you get users who want to write `new Foo.asyncFactory(...)` because they want "new" whenever they are creating a new object. If we remove "new", then hopefully that goes away, and an async factory method won't stand out as much.

We still need to have generative constructors, and be able to distinguish them from other members, due to the generative constructor chaining of subclasses - you can't do `Foo() : super.bar();` if super's *bar* isn't a *generative* constructor, but factory constructors become much less interesting.

Another, related, wish: A const constructor can't create a new const object containing an argument. If you write:  `const Foo(a) : x = const Bar(a);` then it's invalid because it can't be run with "new" because `a` isn't constant. If you write `const Foo(a): x = new Bar(a);` then it's invalid in a const context. Now, if you could write: `const Foo(a) : x = Bar(a);` and have the omitted const/new" be treated as "const' in a const context and as "new" in a runtime context, then it becomes much more useful. Omitting const/new actually gives extra power!


Günter Zöchbauer

unread,
Apr 11, 2015, 5:50:15 AM4/11/15
to core...@dartlang.org, kevin...@gmail.com

On Saturday, April 11, 2015 at 11:32:41 AM UTC+2, Lasse Reichstein Holst Nielsen wrote:

It could also remove the need for non-const factory constructors completely. There is no real difference between a non-const factory constructor and a static method, except that the former needs to be called using "new" and have the surrounding class as return type. 


As far as I remember this requires generic functions first. 
 

Erik Ernst

unread,
Apr 13, 2015, 4:44:56 AM4/13/15
to Lasse Reichstein Holst Nielsen, core...@dartlang.org, kc
On Sat, Apr 11, 2015 at 11:32 AM, Lasse Reichstein Holst Nielsen <l...@google.com> wrote:
On Thursday, April 9, 2015 at 10:21:52 PM UTC+2, Benjamin Strauß wrote:
(That said, making "new" optional is still a personal long-term goal :)
[..]
[..]

Another, related, wish: A const constructor can't create a new const object containing an argument. If you write:  `const Foo(a) : x = const Bar(a);` then it's invalid because it can't be run with "new" because `a` isn't constant. If you write `const Foo(a): x = new Bar(a);` then it's invalid in a const context. Now, if you could write: `const Foo(a) : x = Bar(a);` and have the omitted const/new" be treated as "const' in a const context and as "new" in a runtime context, then it becomes much more useful. Omitting const/new actually gives extra power!

This is actually quite similar to a concept that I've recommended a few times:  Const functions. A const function is a function f where every invocation of f with `const` arguments yields a `const` value.  It would have to be provably terminating (e.g., based on absence of recursion, or based on using "strictly smaller" arguments in recursive calls), and we would require that `e` must be a constant expression in a declaration like `const T f(..args..) => e` whenever ..args.. are const values, and then add the extra case "invocation of const function on const args" to the list of constructs that yield a const value.  Ideally, we would be able to express constly that the first element of const <String>["one", "two"] is "one", the depth of `const Tree(const EmptyTree, const EmptyTree, 5)` is 1, and the sum of its values is 5.  ;-)

  best regards,

--
Erik Ernst  -  Google Danmark ApS
Skt Petri Passage 5, 2 sal, 1165 København K, Denmark
CVR no. 28866984

kc

unread,
Apr 13, 2015, 8:43:33 AM4/13/15
to core...@dartlang.org, kevin...@gmail.com
The issue with 'new' is that it makes the language irregular and less composable. Smalltalk and Scheme do not have this problem - they have 'uniform access'. 

K.

Bob Nystrom

unread,
Apr 17, 2015, 2:18:48 PM4/17/15
to Lasse Reichstein Holst Nielsen, core...@dartlang.org, kc
On Sat, Apr 11, 2015 at 2:32 AM, Lasse Reichstein Holst Nielsen <l...@google.com> wrote:
On Thursday, April 9, 2015 at 10:21:52 PM UTC+2, Benjamin Strauß wrote:
(That said, making "new" optional is still a personal long-term goal :)

As a new developer learning dart, i would be slightly confused why there are three different ways to create an object.

new List(); // normal way
List.new(); // metaclasses (if/when gilads DEP will be accepted)
List(); // optional new keyword

While i see the benefit in metaclasses, i am not sure what would be gained by making new optional, other than typing four less characters.

I'm personally not that excited about the metaclasses proposal since it only seems to go halfway... which often means a feature that just leaves users in the uncanny valley between a simpler language and the thing they actually wish they could express.

If we were to make the new keyword optional, one solution may be to say that you invoke constructors through the call() method on the metaclass. So List() would mean the same as:

var listClass = List;
listClass();

This gets you back down to two ways to do it. To get down to one, we'd just remove new completely since it adds no value.
 

Why would you like ìt to be optional?

I don't want it to be optional, I want it to be removed completely - I just don't think that's likely to succeed, so the compromise is to make it optional, which will be a backwards compatible change.

Making new optional is not only about not typing four characters - but that does add into it too.
The four characters are redundant. It's statically detectable that I'm calling a constructor, and not having a "new" in front is known to be an error. Writing redundant and unnecessary stuff is just annoying, and getting rid of the annoyance is an improvement in itself.


It could also remove the need for non-const factory constructors completely. There is no real difference between a non-const factory constructor and a static method, except that the former needs to be called using "new" and have the surrounding class as return type. 

It has been argued that having constructors be different from static functions makes it easier for the user to see what is going on. You can *see* that you are creating a new object.
That's just not true. We have factory constructors that don't create new objects, and we have static methods that do create new objects.
It does help with naming, though - if you write `new List.fixed(...)` you don't need the constructor to have a name that says that it creates something. A static function would probably have been named `List.createFixed(...)`. I think that's only a matter of tradition, and we can still use `List.fixed(...)` as a constructor without getting confused - it works for Scala.

So, we have some classes with static factory methods (Uri.parse(...)) and factory constructors (Uri(...)) where the latter require "new" and the former does not. For `Uri`, that was a choice, and I think the right one, but it's not without problems - it's not easy for a user to see which members are constructors and which are static methods. If you could call them in the same way, then the suer doesn't have to know - the static class API is indifferent to what is a constructor and what is not.

Some classes have static factory methods that are asynchronous. You can't make these factory constructors because constructors must return the correct type - which is not a Future.
This means that some APIs will have both normal constructors and async factory methods, and you get users who want to write `new Foo.asyncFactory(...)` because they want "new" whenever they are creating a new object. If we remove "new", then hopefully that goes away, and an async factory method won't stand out as much.

We still need to have generative constructors, and be able to distinguish them from other members, due to the generative constructor chaining of subclasses - you can't do `Foo() : super.bar();` if super's *bar* isn't a *generative* constructor, but factory constructors become much less interesting.

Another, related, wish: A const constructor can't create a new const object containing an argument. If you write:  `const Foo(a) : x = const Bar(a);` then it's invalid because it can't be run with "new" because `a` isn't constant. If you write `const Foo(a): x = new Bar(a);` then it's invalid in a const context. Now, if you could write: `const Foo(a) : x = Bar(a);` and have the omitted const/new" be treated as "const' in a const context and as "new" in a runtime context, then it becomes much more useful. Omitting const/new actually gives extra power!

I want to give you a high five for this. I agree with every bit of it.

Cheers!

- bob
 


kc

unread,
Apr 22, 2015, 8:05:42 AM4/22/15
to core...@dartlang.org
More via a twitter conversation:


K.
Reply all
Reply to author
Forward
0 new messages