Live data from Hacker News

Go and Rust – objects without class

lwn.net

31–40 of 60 posts

Re: Go and Rust – objects without class

#31

Earlier quoted context omitted.

I think that you've missed the fact that we're discussing OO techniques and approaches here, rather than the overall usability of JavaScript. The software I mentioned includes JavaScript written in exchange for money, for clients, facing deadlines, in addition to open source JavaScript projects that may not face such constraints. In such code, we often see prototype-based OO not living up to the hype, and not being s…

I will omit language war you both (parent and grandparent) seem to like waging and I'll go straight to the point. Which is that OO based on prototypes is strictly more powerful than popular class based ones. Which is proven by the very fact you mention: people are writing class-based OO implementations in JavaScript with easy, one can create such an implementation in under 100 LOC. So if you think that "superiority"…

I don't think the assertion that JavaScript's prototype-based OO is more expressive because it lets you fake partial implementations of class-based OO with relative ease is true.

Now, if we could reliably implement class-based OO systems comparable to, or even better than, those found in Java, C#, C++, Python, Ruby, and Smalltalk, for example, then maybe we could say prototype-based OO is more expressive.

However, all we end up with are multiple half-assed (for a lack of a better term) approaches, each of them critically incomplete in one way or another, and often incompatible with one another, too. This creates the integration and maintenance headaches that should be more than apparent to anyone who has worked on any sizable JavaScript code base.

In fact, I think we see the opposite in reality. It's much more effective to implement prototype-based OO systems using class-based OO languages. We see exactly this with the major JavaScript implementations (i.e., prototype-based OO systems) today being written in C++.

So prototype-based OO fails to deliver both in terms of expressiveness and maintainability. It is just a worse technique, when considering the facts. Trying to pretend it's good at things it clearly isn't good at doesn't make much sense to me.

And there's no "language war". C and C++ do the vast bulk of real work today. No other languages today can compare to them, and the ones that try still depend very heavily on one or both.

Re: Go and Rust – objects without class

#32
post #7

Earlier quoted context omitted.

I am not sure the issue of “I don’t make sense in this derived class” is solved by decoupling types and inheritance. For example, given the article's GO code: type file interface { Read(b Buffer) bool Write(b Buffer) bool Close() } my first thought was: wait, not all files are writable, that interface is ill specified. I do think subtyping and subclassing should be different things, but it's not a panacea against bad…

I think this points to a seperate issue as well: Often times we have a choice to express the same thing through types or through state. As the influence of functional languages grows, we tend to choose types more often. It wouldn't be surprising to have a ReadOnlyFile type and a ReadWriteFile type. This can easily be justified because an individual file object doesn't need to change its read/write property after it h…

yeah, I really liked the idea of using typestate to model exactly this in rust, but it was apparently a failed experiment :(

Re: Go and Rust – objects without class

#33
post #7

Earlier quoted context omitted.

I am not sure the issue of “I don’t make sense in this derived class” is solved by decoupling types and inheritance. For example, given the article's GO code: type file interface { Read(b Buffer) bool Write(b Buffer) bool Close() } my first thought was: wait, not all files are writable, that interface is ill specified. I do think subtyping and subclassing should be different things, but it's not a panacea against bad…

That interface isn't great, but that interface isn't coming from Go. I realize you aren't claiming it is, and you're absolutely right that Go's interfaces don't automatically "solve" issues of bad design. Programmers are free to come up with bad interface designs in Go just as easily as they came up with bad class designs in Java or C++. This is just to avoid confusion for people who aren't generally familiar with Go…

Well, sure, but Reader and Writer are interfaces existing in java too :)

Anyway I think we agree on the general issue, but actually I suspect go's approach _does_ solve some bad design issues that crop up in common OO, namely the fragile base class one.

I just don't think it impacts the misspecification one.

Re: Go and Rust – objects without class

#34

Earlier quoted context omitted.

I will omit language war you both (parent and grandparent) seem to like waging and I'll go straight to the point. Which is that OO based on prototypes is strictly more powerful than popular class based ones. Which is proven by the very fact you mention: people are writing class-based OO implementations in JavaScript with easy, one can create such an implementation in under 100 LOC. So if you think that "superiority"…

I don't think the assertion that JavaScript's prototype-based OO is more expressive because it lets you fake partial implementations of class-based OO with relative ease is true. Now, if we could reliably implement class-based OO systems comparable to, or even better than, those found in Java, C#, C++, Python, Ruby, and Smalltalk, for example, then maybe we could say prototype-based OO is more expressive. However, al…

> C and C++ do the vast bulk of real work today.

That's true, but I just have to ask: so what? I, for one, don't subscribe to the theory that popularity equals quality. Although both C and C++ are immensely popular in terms of code written in them that doesn't mean they're the last word in language design.

> No other languages today can compare to them, and the ones that try still depend very heavily on one or both.

I don't understand what you mean by "compare to them". If you mean in terms of features - sure there are languages more advanced. If you mean in terms of popularity then I can only say I find such comparisons meaningless.

> Now, if we could reliably implement class-based OO systems comparable to, > or even better than, those found in Java, C#, C++, Python, Ruby, and Smalltalk, > for example, then maybe we could say prototype-based OO is more expressive.

We can do this (modulo "reliably", which I don't understand what you mean by) and that's the problem. You yourself explain this:

> However, all we end up with are multiple half-assed

That's exactly the case. Java, C++, Python and Ruby are extremely incompatible with each other. No wonder that JS implementations of ideas taken from those languages are still incompatible - although less so than originals between themselves. It's also not that strange that they are incomplete - given that everything you'd like to do in class-based system you can do with prototypes there is simply no need for frameworks being complete.

Can you post a few examples of what is possible in Java and not possible in JavaScript?

Also remember that language designers can alter syntax to better support their systems, so we need to exclude syntax from comparison.

> It's much more effective to implement prototype-based OO systems using class-based OO languages.

I don't know if it's impossible, but your examples are flawed. Of course you can write any language in any language, like JS VMs are. But that's completely different matter, I was talking about using the language itself in a prototype based manner. I suspect that, due to static and low-level nature of classes in C++ it's completely, utterly impossible to replicate JS object system inside C++. That you can write interpreter that implements this system is obvious and not interesting at all.

As a counter example, in Python you could, with careful use of metaclasses and implementation details of classes and objects create objects whose methods lookup order and semantics of would be the same or close to those of prototype based JS - in the language itself.

=======

Your arguments fail to prove that prototype based-ness somehow fails. It does not, in itself, fail in any way. As I wrote above, show what can be done with classes (single inheritance model) that cannot be replicated using JS or better IO prototype semantics - that would be convincing. The fact that JavaScript development is a mess - I won't deny it - proves nothing about prototypes and only a bit about JS.

By the way, have you tried Haskell, OCaml or F# and Erlang?

Re: Go and Rust – objects without class

#35

The value of Go and Rust, I think, is that they are object-oriented languages that try to avoid conflating classes with types. If you think of a type as a set of possible values, then a subclass is actually a supertype—a superset of the possible values of its parent class—and likewise a superclass is a subtype. The “is-a” relationship is saying “for all instances I of X, I is an instance of Y” which is essentially th…

> If you think of a type as a set of possible values, then a subclass is actually a supertype—a superset of the possible values of its parent class—and likewise a superclass is a subtype.

You have this exactly backwards. A subclass is a subtype. A superclass is a supertype.

Let's say you have superclass A and derive subclass B from it. In the universe of all possible values, some will be A but not B (they will either be direct instances of A, or instances of some other subclass of A). But every B will also be an A by definition since B is-a A.

Therefore the set of values that are B is a subset of the set of values that are A.

Re: Go and Rust – objects without class

#36

Earlier quoted context omitted.

Not all tools are equal, however. The class-based OO approach of C++ has proven to be practical for real-world software development. The same goes for the approaches taken by Java and C#, for example. While they can be abused, these approaches generally provide a usable balance between conceptual comprehensibility, consistency, modularity, code sharing/reuse, and the ability to model a variety of realistic domains. T…

Real world software, as you say, with money, clients and deadlines, is written in JavaScript all the time. It's not like it is a toy language or academic research project. It's the widest deployed platform in the world.

> Real world software, as you say, with money, clients and deadlines, is written in JavaScript all the time.

That says a lot about the lack of alternatives for code that must run in a browser and next to nothing about the merits of prototypes.

I have the fortune to work with a bunch of people that worked on Self, or worked with people that did. Many of them told me that after all of that experience, the conclusion they came to was that prototypes don't really work well in practice, even when you have multiple parents like Self. (JS lacks that, which makes it even more painfully limited.)

Meanwhile, many JS luminaries, people who understand every corner of the language, are working hard to add class syntax to ES6 (, or defining transpilers that support it (Erik Arvidsson with Traceur, Jeremy Ashkenas with CoffeeScript).

I find prototypes interesting. I've implemented my own prototype-based language from scratch to understand them better. As soon as I had it working and started writing code in the language, the first thing I found myself wanting was to add classes to it.

Re: Go and Rust – objects without class

#37

Earlier quoted context omitted.

I will omit language war you both (parent and grandparent) seem to like waging and I'll go straight to the point. Which is that OO based on prototypes is strictly more powerful than popular class based ones. Which is proven by the very fact you mention: people are writing class-based OO implementations in JavaScript with easy, one can create such an implementation in under 100 LOC. So if you think that "superiority"…

I don't think the assertion that JavaScript's prototype-based OO is more expressive because it lets you fake partial implementations of class-based OO with relative ease is true. Now, if we could reliably implement class-based OO systems comparable to, or even better than, those found in Java, C#, C++, Python, Ruby, and Smalltalk, for example, then maybe we could say prototype-based OO is more expressive. However, al…

> So prototype-based OO fails to deliver both in terms of expressiveness and maintainability. It is just a worse technique, when considering the facts. Trying to pretend it's good at things it clearly isn't good at doesn't make much sense to me.

You are focusing too much on prototype OO.

The models offered by Smalltalk, Beta, CLOS, Haskell and quite a few others are different approaches to the classical model known to the average developer.

This is the main problem in the "offshore everything model" that looks for cheap dumb developers able to work like cogs and not required to think.

> And there's no "language war". C and C++ do the vast bulk of real work today. No other languages today can compare to them, and the ones that try still depend very heavily on one or both.

When I started developing (1986), C was just another language that most people did not care about. In fact I only cared to write some C code around 1993.

The current situation came to be due to UNIX's influence in the enterprise and the fact that any developer worth his salary isn't not going to rewrite the full stack from zero.

It has nothing to do with their suitability for OO development.

Re: Go and Rust – objects without class

#38

The value of Go and Rust, I think, is that they are object-oriented languages that try to avoid conflating classes with types. If you think of a type as a set of possible values, then a subclass is actually a supertype—a superset of the possible values of its parent class—and likewise a superclass is a subtype. The “is-a” relationship is saying “for all instances I of X, I is an instance of Y” which is essentially th…

If you think of a type as a set of possible values, then a subclass is actually a supertype—a superset of the possible values of its parent class—and likewise a superclass is a subtype.

Nope. A subclass is usually (not always!) a subtype, not the other way round. Or, more specifically (and accurately), most statically-typed class-based OO languages treat subclasses in their type systems as subtypes by default, i.e., they assume that a subclass instance can act as an instance of its superclass, LSP-wise. This, I believe, is as accurate statement as one can make (on this level of generality).

The “is-a” relationship is saying “for all instances I of X, I is an instance of Y” which is essentially the definition of superset. That is what the Liskov Substitution Principle is about.

It's a definition of a superset, if Y is the superset and X is the subset.

In C++ and other languages with support for object-oriented programming, a subclass is not necessarily a supertype: virtual functions can throw “I don’t make sense in this derived class”.

That's a part of why I believe that static typing doesn't make too much sense when it comes to OO languages (with (sub)classes). If static typing is supposed to take care of subtype assignability statically and the semantics of the behaviour of derived classes can break the LSP assumptions, static typing becomes sort of worthless.

Re: Go and Rust – objects without class

#39

Earlier quoted context omitted.

Not all tools are equal, however. The class-based OO approach of C++ has proven to be practical for real-world software development. The same goes for the approaches taken by Java and C#, for example. While they can be abused, these approaches generally provide a usable balance between conceptual comprehensibility, consistency, modularity, code sharing/reuse, and the ability to model a variety of realistic domains. T…

Real world software, as you say, with money, clients and deadlines, is written in JavaScript all the time. It's not like it is a toy language or academic research project. It's the widest deployed platform in the world.

Javascript is one of (imo) the most horrendous OO language of all time. No static analysis, horrible scoping/syntax, class declaration, and so on.

Re: Go and Rust – objects without class

#40

The value of Go and Rust, I think, is that they are object-oriented languages that try to avoid conflating classes with types. If you think of a type as a set of possible values, then a subclass is actually a supertype—a superset of the possible values of its parent class—and likewise a superclass is a subtype. The “is-a” relationship is saying “for all instances I of X, I is an instance of Y” which is essentially th…

> If you think of a type as a set of possible values, then a subclass is actually a supertype—a superset of the possible values of its parent class—and likewise a superclass is a subtype. You have this exactly backwards. A subclass is a subtype. A superclass is a supertype. Let's say you have superclass A and derive subclass B from it. In the universe of all possible values, some will be A but not B (they will either…

I was a bit backward with my language. What I was trying to get at is that many OO languages encourage you to add fields in derived classes. This makes the derived class a supertype, being a larger set that fully includes the set of its parent class. You’re adding elements to a product type. But this often breaks substitutability, so to conflate class inheritance (a useful concept) with subtyping (another useful concept) is fraught with problems.
Post reply on HN