A core Python committer's (very shallow) thoughts on Dart(sayspy.blogspot.com)
sayspy.blogspot.com
A core Python committer's (very shallow) thoughts on Dart
http://sayspy.blogspot.com/2012/05/my-very-shallow-thoughts-on-dart.html
6 comments
It already is - you just have to run in checked mode.
I have to admit, there's some part of me that wants to think that "types as documentation" is a good idea. But I have to go with the OP on this one... I watched the Dart presentation from Lang.NEXT and laughed a bit to myself at one point because even in the presenter's example, the "type documentation" was already outdated. During his presentation it doesn't matter, because everyone watching is in the context of the code as part of his discussion. But if you put that code in front of somebody a year from now, out of context, would they immediately pick up on it? Or will they be frustrated by the fact that they expect the types to be what they say they are, but they aren't?
Are people really going to run in checked mode to verify their code? Or they going to do what they do with compiler warnings and turn them off as soon as they see one? I'm sure there will be a million blog posts titled "Dart Best Practices" that will say "do not use checked mode, it slows down execution and prints confusing messages". Of course, any bugs in checked mode will mean people will need to get their production systems working by ignoring checked mode.
I guess... my gut tells me that you should either have types, or not have types. Being in the middle creates too many opportunities for cognitive dissonance, too many opportunities for sneaky bugs, and too many opportunities to keep having this debate. It's one of those things that seems really smart and cool that, on a practical level, will probably turn out to be a complete waste of time and a total distraction.
Are people really going to run in checked mode to verify their code? Or they going to do what they do with compiler warnings and turn them off as soon as they see one? I'm sure there will be a million blog posts titled "Dart Best Practices" that will say "do not use checked mode, it slows down execution and prints confusing messages". Of course, any bugs in checked mode will mean people will need to get their production systems working by ignoring checked mode.
I guess... my gut tells me that you should either have types, or not have types. Being in the middle creates too many opportunities for cognitive dissonance, too many opportunities for sneaky bugs, and too many opportunities to keep having this debate. It's one of those things that seems really smart and cool that, on a practical level, will probably turn out to be a complete waste of time and a total distraction.
I guess... my gut tells me that you should either have types, or not have types. Being in the middle creates too many opportunities for cognitive dissonance, too many opportunities for sneaky bugs, and too many opportunities to keep having this debate. It's one of those things that seems really smart and cool that, on a practical level, will probably turn out to be a complete waste of time and a total distraction.
The worlds collective programming experience doesn't really back that up. Almost every language drops (or makes optional) type support when constructs become too complicated, or they become so complicated no one can understand them.
Languages with the best type systems (OCaml) aren't particularly popular, while languages we think of as strongly typed (eg Java) have big backdoors to allow people to bypass the type system.
On the other side, weakly typed languages are adding typing-like features by integrating unit test facilities into the environment (which - optionally - catch many of the bugs typing can help with).
Like so many things, optional typing might seem impure, but often messy systems are the most robust.
The worlds collective programming experience doesn't really back that up. Almost every language drops (or makes optional) type support when constructs become too complicated, or they become so complicated no one can understand them.
Languages with the best type systems (OCaml) aren't particularly popular, while languages we think of as strongly typed (eg Java) have big backdoors to allow people to bypass the type system.
On the other side, weakly typed languages are adding typing-like features by integrating unit test facilities into the environment (which - optionally - catch many of the bugs typing can help with).
Like so many things, optional typing might seem impure, but often messy systems are the most robust.
Dart's optional typing is not common in languages at all. What you're referring to is a combination of dynamic and static typing, which is not Dart-style optional typing. In statically-typed languages, the dynamically-typed values are clearly delimited in the source text and are not a compiler switch.
A Quick Tour of Dart. Presented by Gilad Bracha
Summary
Gilad Bracha discusses Dart, its type system, interfaces, generics, ADTs without types, built-in factory support.
http://www.infoq.com/presentations/A-Quick-Tour-of-Dart
Summary
Gilad Bracha discusses Dart, its type system, interfaces, generics, ADTs without types, built-in factory support.
http://www.infoq.com/presentations/A-Quick-Tour-of-Dart
even in the presenter's example, the "type documentation" was already outdated.
Yes, but it's not the same as outdated comments. A well featured optional type system will let you know that is happening. An out of date comment will just continue to deceive.
Or they going to do what they do with compiler warnings and turn them off as soon as they see one?
My advice, is not to work in such shops.
I guess... my gut tells me that you should either have types, or not have types. Being in the middle creates too many opportunities for cognitive dissonance
As if there's a lack of them on the ends of the spectrum compared to the middle. We will find out if it will be more of a mess, so many will have gut-calibration data.
Yes, but it's not the same as outdated comments. A well featured optional type system will let you know that is happening. An out of date comment will just continue to deceive.
Or they going to do what they do with compiler warnings and turn them off as soon as they see one?
My advice, is not to work in such shops.
I guess... my gut tells me that you should either have types, or not have types. Being in the middle creates too many opportunities for cognitive dissonance
As if there's a lack of them on the ends of the spectrum compared to the middle. We will find out if it will be more of a mess, so many will have gut-calibration data.
Is that compile-time or run-time? If it's run-time, do you need to traverse all your code paths to make sure it's really really right?
(I'm genuinely curious.)
(I'm genuinely curious.)
Interesting, and very positive review.
Maybe it's my Java background coming through, but I like the idea of Factory constructors.
Maybe it's my Java background coming through, but I like the idea of Factory constructors.
Every time I read about Java developers and their love of Factories (and Factory Factories) I think of this wonderful comment on Joel on Software:
http://discuss.joelonsoftware.com/default.asp?joel.3.219431
NB Factories are one of these things that seem like a good idea in theory, but often seem to end up with crazy levels of abstraction in practice.
http://discuss.joelonsoftware.com/default.asp?joel.3.219431
NB Factories are one of these things that seem like a good idea in theory, but often seem to end up with crazy levels of abstraction in practice.
A message I received from a friend working at Google:
"New layers, more layers, bigger layers, better layers, abstract layers, injected layers, factory layers, module layers, AbstractFactoryFactoryModuleBuilderInjector layers, layers upon layers within layers wrapped in layers, a glorious spire of layers to reach the heavens and bring renown to Babylon! Hellelujah!"
"New layers, more layers, bigger layers, better layers, abstract layers, injected layers, factory layers, module layers, AbstractFactoryFactoryModuleBuilderInjector layers, layers upon layers within layers wrapped in layers, a glorious spire of layers to reach the heavens and bring renown to Babylon! Hellelujah!"
There is no doubt that there is a culture of abstraction stupidity in Java (although it isn't as bad as it used to be), and yes, I agree that a FactoryFactory is a code smell.
That doesn't make factories bad.
That doesn't make factories bad.
Factories is not bad in practice.
Essentially closures, curried functions, partial evaluated is the same thing: code that generate code.
I'm not a java developer
Essentially closures, curried functions, partial evaluated is the same thing: code that generate code.
I'm not a java developer
> Maybe it's my Java background coming through, but I like the idea of Factory constructors.
Better languages don't special-case the constructor instead (no `new` operator), the constructor is just a class method. Bam, "factory method" constructors out of the box and problem solved.
Better languages don't special-case the constructor instead (no `new` operator), the constructor is just a class method. Bam, "factory method" constructors out of the box and problem solved.
Better is pretty subjective here.
Factories aren't common in Python, but they are used in exactly the same cases where they are used in Java (eg [1],[2],[3]). If you need to decide at runtime what object from an object hierarchy to create you use a factory. There's nothing inherently bad about that.
[1] http://www.linuxtopia.org/online_books/programming_books/pyt...
[2] http://stackoverflow.com/questions/8129018/factory-method-in...
[3] http://eikke.com/python-factory-like-type-instances/ (though I prefer the version in the comments here)
Factories aren't common in Python, but they are used in exactly the same cases where they are used in Java (eg [1],[2],[3]). If you need to decide at runtime what object from an object hierarchy to create you use a factory. There's nothing inherently bad about that.
[1] http://www.linuxtopia.org/online_books/programming_books/pyt...
[2] http://stackoverflow.com/questions/8129018/factory-method-in...
[3] http://eikke.com/python-factory-like-type-instances/ (though I prefer the version in the comments here)
> Factories aren't common in Python
Factories are everywhere in Python because the default construction workflow goes through a bloody factory method.
> There's nothing inherently bad about that.
You may want to read my comment instead of inventing things I never wrote, because the comment you replied to didn't even remotely hint at factories being bad.
Oh, and the first two examples you provide are absolutely horrendous, it's not surprising they are used "in exactly the same cases where they are used in Java", because what you show there really is java code translated to Python.
Whereas the third one is something you can't do in Java: it factorizes the creation of a class through customization of the metaclass's standard creation protocol. The version in the comments overrides the creation of the instance (through, again, a completely standard override of Python's built in construction protocol), which is less efficient but doesn't require understanding metaobjects.
Factories are everywhere in Python because the default construction workflow goes through a bloody factory method.
> There's nothing inherently bad about that.
You may want to read my comment instead of inventing things I never wrote, because the comment you replied to didn't even remotely hint at factories being bad.
Oh, and the first two examples you provide are absolutely horrendous, it's not surprising they are used "in exactly the same cases where they are used in Java", because what you show there really is java code translated to Python.
Whereas the third one is something you can't do in Java: it factorizes the creation of a class through customization of the metaclass's standard creation protocol. The version in the comments overrides the creation of the instance (through, again, a completely standard override of Python's built in construction protocol), which is less efficient but doesn't require understanding metaobjects.
I really don't understand what advantage they provide over regular static methods...
It comes down to the fact that interfaces aren't classes.
To whit: let's say you want to have an interface for associative arrays. Let's call it Map. Now let's say you want to provide a static method to create an instance of the default Map implementation (call it, say, HashMap). So you'd think about doing something like this:
interface Map { ... static defaultImpl() { .... } }
Except, interfaces can't have implementation in them. That would imply multiple inheritance (which languages like Dart and Java don't support).
Okay, so one workaround: use an abstract class:
abstract class Map { ... static defaultImpl() { .... } }
The only problem is that if you define Map as an abstract class instead of an interface, that means that all implementations of Map must extend Map. Given single inheritance, this means anything providing a Map-style interface can and must only extend from the base Map class.
So... Factory classes are there because of how Java treats interfaces and single inheritance.
To whit: let's say you want to have an interface for associative arrays. Let's call it Map. Now let's say you want to provide a static method to create an instance of the default Map implementation (call it, say, HashMap). So you'd think about doing something like this:
interface Map { ... static defaultImpl() { .... } }
Except, interfaces can't have implementation in them. That would imply multiple inheritance (which languages like Dart and Java don't support).
Okay, so one workaround: use an abstract class:
abstract class Map { ... static defaultImpl() { .... } }
The only problem is that if you define Map as an abstract class instead of an interface, that means that all implementations of Map must extend Map. Given single inheritance, this means anything providing a Map-style interface can and must only extend from the base Map class.
So... Factory classes are there because of how Java treats interfaces and single inheritance.
I think they are there for reducing the need for dependency injection frameworks.
Some discussion
https://plus.google.com/u/0/110377859584351043951/posts/1FsB...
http://code.google.com/p/dart/issues/detail?id=76
Well..
DI Frameworks were originally created to provide an alternative to Factories.
DI Frameworks were originally created to provide an alternative to Factories.
There does not need to be any knowledge of _any_ class. A factory method _still_ needs a class instance, you don't need them with factory constructors.
A classical, say Java or C# way will still need coupling to such a class. In dart, there is real decoupling going on.
A classical, say Java or C# way will still need coupling to such a class. In dart, there is real decoupling going on.
> A factory method _still_ needs a class instance
Uh no it does not, it just needs a class. Unless what you mean by "a class instance" is "a class object". A factory method is a classmethod, not an instancemethod.
A factory method and a "factory constructor" need exactly the same thing: the class object.
> In dart, there is real decoupling going on.
In dart, there's mostly a bloody mess of 4 different constructors when all you need is a constructor and an initializer, as done in e.g. Ruby or Python. And these can be "regular" methods (respectively on the class and on the instance).
Conversely, you can also have an "overridden" constructor as in Javascript: an instance is built, the constructor function is called using the instance as its context, and if the constructor returns something that something is returned by `new` in stead of the original object.
Uh no it does not, it just needs a class. Unless what you mean by "a class instance" is "a class object". A factory method is a classmethod, not an instancemethod.
A factory method and a "factory constructor" need exactly the same thing: the class object.
> In dart, there is real decoupling going on.
In dart, there's mostly a bloody mess of 4 different constructors when all you need is a constructor and an initializer, as done in e.g. Ruby or Python. And these can be "regular" methods (respectively on the class and on the instance).
Conversely, you can also have an "overridden" constructor as in Javascript: an instance is built, the constructor function is called using the instance as its context, and if the constructor returns something that something is returned by `new` in stead of the original object.
> A factory method is a classmethod, not an instancemethod.
This completely depends on your implementation. It's possible to implement it as instance method, or static method.
> Uh no it does not, it just needs a class.
Whether it be a static factory method or an instance method, fact is you need a reference to an implementation (class). In dart, you can do
Named constructors felt very liberating when working with Dart.
> Define an interface for creating an object, but let the classes which implement the interface decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses.
This completely depends on your implementation. It's possible to implement it as instance method, or static method.
> Uh no it does not, it just needs a class.
Whether it be a static factory method or an instance method, fact is you need a reference to an implementation (class). In dart, you can do
List someListInstance = new List();
where List is an interface. There is none class needed in your consuming code, none. In C# or Java, this is impossible: You need _some_ class (whether it be a static method on it, or an instance method) to get a new instance of the interface.Named constructors felt very liberating when working with Dart.
new List.from([instance1, instance1]);
delivers a lot of clarity, while offering the promised decoupling by the GoF:> Define an interface for creating an object, but let the classes which implement the interface decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses.
> It's possible to implement it as instance method
It makes no sense, if you're doing that you've switched to full-blown factories (abstracts or builders), you're not using factory methods anymore.
> Whether it be a static factory method or an instance method, fact is you need a reference to an implementation (class). In dart, you can do
> List someListInstance = new List();
> where List is an interface. There is none class needed in your consuming code, none.
That's got nothing to do with factories, or interfaces.
> You need _some_ class (whether it be a static method on it, or an instance method) to get a new instance of the interface.
You always need a class, even in Dart there has to be a default List implementation of some sort which can be called (and has to be specified on the interface, it's not like you can even provide your own default implementation of a third party's interface). As to the calling code needing to know about that one concrete implementation:
> Named constructors felt very liberating when working with Dart.
Yeah, that's so much more liberating than:
It makes no sense, if you're doing that you've switched to full-blown factories (abstracts or builders), you're not using factory methods anymore.
> Whether it be a static factory method or an instance method, fact is you need a reference to an implementation (class). In dart, you can do
> List someListInstance = new List();
> where List is an interface. There is none class needed in your consuming code, none.
That's got nothing to do with factories, or interfaces.
> You need _some_ class (whether it be a static method on it, or an instance method) to get a new instance of the interface.
You always need a class, even in Dart there has to be a default List implementation of some sort which can be called (and has to be specified on the interface, it's not like you can even provide your own default implementation of a third party's interface). As to the calling code needing to know about that one concrete implementation:
abstract class Foo {
public static Foo foo() {
return new FooImpl();
}
public abstract void printFoo();
}
class FooImpl extends Foo {
public void printFoo() {
System.out.println("I am FooImpl");
}
}
class Main {
public static void main(String[] args) {
Foo foo = Foo.foo();
foo.printFoo();
}
}
Oh look at that, the calling code does not know anything about FooImpl.> Named constructors felt very liberating when working with Dart.
Yeah, that's so much more liberating than:
List.from([instance1, instance2]);
Wait, no it's not.Your consuming code is tied to Foo. In dart, the consuming code only needs tying up to the interface.
> You always need a class
Nope. That's the whole point which I am trying to communicate: you do not need a reference to a class to get the instance of the interface from, as you confirm later on:
> As to the calling code needing to know about that one concrete implementation:
My personal feeling of liberation comes from the fact that the code is simpler and more clear. The non-coupling is nice, but can be achieved with dependency injection too: the point is the transfer of characters into a mental model which is more efficient with the named constructors/factory constructors.
> You always need a class
Nope. That's the whole point which I am trying to communicate: you do not need a reference to a class to get the instance of the interface from, as you confirm later on:
> As to the calling code needing to know about that one concrete implementation:
My personal feeling of liberation comes from the fact that the code is simpler and more clear. The non-coupling is nice, but can be achieved with dependency injection too: the point is the transfer of characters into a mental model which is more efficient with the named constructors/factory constructors.
> Your consuming code is tied to Foo. In dart, the consuming code only needs tying up to the interface.
Foo is an abstract class, which is the exact same thing.
> Nope. That's the whole point which I am trying to communicate: you do not need a reference to a class to get the instance of the interface from
Neither do you in the code I posted, can you bloody read?
> My personal feeling of liberation comes from the fact that the code is simpler and more clear.
You'll have to give actual examples of that, because I've not seen it so far.
> the point is the transfer of characters into a mental model which is more efficient with the named constructors/factory constructors.
This phrase doesn't even make sense, what "transfer of characters" are you talking about, and how is it more efficient for the user to type more? (named constructors only add ceremony to factory methods) (I'm not even going to talk about factory constructors again, they're a band-aid on the self-inflicted wound of stupid java-style constructors)
Foo is an abstract class, which is the exact same thing.
> Nope. That's the whole point which I am trying to communicate: you do not need a reference to a class to get the instance of the interface from
Neither do you in the code I posted, can you bloody read?
> My personal feeling of liberation comes from the fact that the code is simpler and more clear.
You'll have to give actual examples of that, because I've not seen it so far.
> the point is the transfer of characters into a mental model which is more efficient with the named constructors/factory constructors.
This phrase doesn't even make sense, what "transfer of characters" are you talking about, and how is it more efficient for the user to type more? (named constructors only add ceremony to factory methods) (I'm not even going to talk about factory constructors again, they're a band-aid on the self-inflicted wound of stupid java-style constructors)
That looks like the named-default-class-for-an-interface feature, not something specific to the factory pattern.
(I don't know Dart, though)
(I don't know Dart, though)
Single-inheritance, but interfaces can have default implementations? Isn't that... multiple inheritance?
You can implement multiple interfaces on a single class, but only "inherit" from a single implementation.
Or, perhaps more specifically, you can implement an interface without extending its default implementation.
As the article states, the default implementations are there more so that you can say "m = new Map()", instead of having to remember about this other thing called "HashMap".
Or, perhaps more specifically, you can implement an interface without extending its default implementation.
As the article states, the default implementations are there more so that you can say "m = new Map()", instead of having to remember about this other thing called "HashMap".
[deleted]
they still went a little overboard in my opinion on some things (e.g. the list interface has a last() method instead of supporting negative indexes).
A last method is much more intention revealing and easier to scan for me than negative indexes.
A last method is much more intention revealing and easier to scan for me than negative indexes.
Are you also a fan of list.first() over list[0]? I think it's just a convention that takes getting used to and ends up being quite handy.
Have you seen some of the early Bittorrent code? Code with lots and lots of this[n:-3] or this[1,:,:] sprinkled around in the same piece of code starts to get like regexp or Perl. It's a cool operator to have to get stuff specified in a few keystrokes, but that makes it quite terse, so high density use of it is hard to read.
...have done toy examples now in 18 languages...this is actually usually enough for me to grasp the inspirations for a language and thus understand its essence.
Usually is the dangerous word here. (Dangerous as in, "a little knowledge.")
Usually is the dangerous word here. (Dangerous as in, "a little knowledge.")
Actually, that's the point when I stopped taking him seriously (though why anyone in core Python should be taken seriously as a language designer I don't know). 18? Come on. I've deployed projects in that many languages.
My point is more that in-depth knowledge in a number of languages is also vital. The 18 toy examples is completely unimportant. Competency in core Python is. I would look for such depth in one or two other languages.
Some responses from the Dart team: https://plus.google.com/115362263245161504841/posts/82jKeP4Y...
But, just like documentation, if it gets out of date you're really wonked.
I'd prefer something that is both useful as documentation and is used by the compiler (a la Haskell's type classes).