Live data from Hacker News

Inheritance was invented as a performance hack

catern.com

121–130 of 268 posts

Re: Inheritance was invented as a performance hack

#121
This writeup is a bit unclear. It actually mentions two problems. The first is functions out-living stack-allocated arguments... this isn't a GC issue but a compiler issue that could be solved by escape analysis (or more powerful variants, like Rust's lifetime analysis). I guess that maybe they're implicitly talking about using a spaghetti stack instead of doing escape/lifetime analysis, and then needing the GC for the stack frame to support interior references. In any case, as they state the first problem, it's a compiler problem, not a GC problem. As they state in the article, inheritance doesn't solve this, and Simula just forbids by-name/by-reference arguments that are allocated in the caller's call frame.

The second problem they describe is linked lists. A Java-like linked list means an extra level of indirection, where the list element holds a reference to the held object. For both performance and space reasons, they wanted to remove that layer of indirection. That meant either having their garbage collector support interior references (references to any field inside the object) or else making a reference to a linked list element be the same as a reference to the held object. They chose the second option, by way of making the element and the held object one and the same, using inheritance. A Simula linked list has as much indirection as a C++ std::list, one fewer indirection than a java LinkedList.

They mention reference counting, but a mark-and-sweep, copying, or tricolor tracing collector would still have this same issue if it didn't support interior references. As sophisticated as Oracle's latest JVM is, I don't believe any of its several garbage collectors support interior references. Physically in the JVM's memory, LinkedList really has an extra layer of indirection as compared to C++'s std::list, and the JVM uses escape/lifetime analysis in order to stack-allocate some objects that would otherwise need to be heap-allocated.

Re: Inheritance was invented as a performance hack

#122

In my experience, 90% of the time people use inheritance but they really only cared about composition, and their language simply does not have any convenient facility to compose types and re-export their methods. With a good type system that includes traits, you almost never need virtual dispatching, as any Rust developer may tell.

Recently experimented a bit with Rust and I found the reverse to be true. You cannot compose types in Rust. You compose behaviors not types. Very important distinction as I found out the hard way.

Take the following example I have found on the net: https://play.rust-lang.org/?version=stable&mode=debug&editio...

In that example, both the bicycle and the car have the property `speed`. Imagine you have multiple types now that need to have the `speed` property. You would need to copy-paste the same code for each new type in order for you to be type safe.

Apparently it is called *Monomorphization*: https://cglab.ca/~abeinges/blah/rust-reuse-and-recycle/#mono...

From the article:

* But if I want a single queue to be able to handle different tasks, then it's not clear how that could be done with monomorphization alone. That's why it's called "mono"morphization. It's all about taking abstract implementations and creating instances that do one thing. *

Which was exactly what I was experimenting with: A single queue worker that can handle different cases. Honestly, it made Rust almost not worth it for me. Sadly, I was too deep to turn back so I wound up doing the whole thing in Rust. I have tons of copy-paste code. It is ugly and it is bothering me.

Re: Inheritance was invented as a performance hack

#123

Earlier quoted context omitted.

"Catching on" doesn't mean "is the right way to do things". Code reuse is in fact a prime example of a misuse of inheritance

It's the main reason why inheritance became so popular and so useful. Specialization remains a very common design pattern that is incredibly useful and trivially and intuitively solved with inheritance. No other programming concept (HKT, ad hoc polymorphism, functional programming, etc...) comes close to its elegance.

Code-reuse via "Implementation Inheritance" is completely unnecessary for specialisation or polymorphism.

When someone says that "inheritance is bad for code reuse" they're not talking about interfaces, or using inheritance for polymorphism. They're strictly talking about sharing code using implementation inheritance, which is the thing that has been widely criticised for more than 30 years now.

One can argue that even the "Template Method Pattern" doesn't fall into "implementation inheritance", since the implementation lives in the subclass.

If you read the posts, discussion is way more nuanced than "inheritance bad vs inheritance good".

Re: Inheritance was invented as a performance hack

#124

Pretty off topic comment, but I read the title as "inheriting money is a way avoid being a high performer", which happens to be true, although completely irrelevant to the actual article. ;)

I read it similarly as "inheriting money". And it's true that inheritance IS a performance hack--not for the children, but for the parents. Inheritance incentivizes parents to accumulate wealth not just for one lifetime but for multiple lifetimes. (Granted it may paradoxically have the opposite effect on the children as you mention.) Here's Milton Friedman on the matter: https://www.youtube.com/watch?v=km9OCw3f5w4

Inheritance is a natural phenomenon.

If all my money were stolen when I die (let's say, 100% inheritance tax), I wouldn't have much incentive to grow my business more once my business makes more money than I can possibly spend in a lifetime.

Sure, some people may still do it because they love working or because they love providing for their society.

The main reason I want to accumulate money, is so I can offer them a job instead of them going through the corporate bullcrap I had to do when needing some starting capital.

Bigger businesses are capable of bigger bets (think Elon Musk) which benefit everyone, removing an economic incentive doesn't sound wise for innovation and growth.

Re: Inheritance was invented as a performance hack

#125
post #38

Earlier quoted context omitted.

In your view, how is "interfaces with default implementations" different from "inheritance for code reuse"? At a minimum it looks like a virtual function with a default implementation in the base class. If a derived class doesn't override it, isn't that code reuse?

Maybe he meant something similar to Go interfaces, but they are abstract and coupled loosely with implementations after the fact. That or abstract class/pure interface. There's no need for default implementations introducing assumptions in code.

"Interfaces with default implementations" are a thing in Java and in some other languages, but most people don't know about them:

https://docs.oracle.com/javase/tutorial/java/IandI/defaultme...

Re: Inheritance was invented as a performance hack

#126
post #119
post #98

Earlier quoted context omitted.

The other day I got into a heated debate with a C# developer on the merits (or lack thereof) of adding an "I" prefix to interfaces. Turns out in C# there's no syntactic difference between implementing an interface and inheritance, so it makes sense in C# to explicitly state that something is an interface but, arguably, only there.

The argument against “I” is that the user (client code) of an instance shouldn’t have too care whether the type of the reference is an interface or a class. Concerns of the implementor shouldn’t determine the naming visible to the client code. Of course, it’s an established C# convention (and inspired by the naming convention for COM interfaces) so one better sticks with it, but I think the convention was a bad choic…

Yeah, IMV its a similar problem to the convention of prefixing DB objects with T (table) or V (view), but not as bad because refactoring between class and interface should be rare.

Re: Inheritance was invented as a performance hack

#127
post #121

This writeup is a bit unclear. It actually mentions two problems. The first is functions out-living stack-allocated arguments... this isn't a GC issue but a compiler issue that could be solved by escape analysis (or more powerful variants, like Rust's lifetime analysis). I guess that maybe they're implicitly talking about using a spaghetti stack instead of doing escape/lifetime analysis, and then needing the GC for t…

> A Java-like linked list means an extra level of indirection

I guess you mean java.util.LinkedList that has virtually no use case that's not outperformed (both space and time) by another datastructure.

Writing your own linked list with prev(+next) pointers ain't hard by it's nothing like C++ templates. The removal of layer of indirection does work in Java [pretty well] as well - like extending AtomicReference (or AtomicInteger), if you need a CAS and some other data, of course it comes with false sharing.

Re: Inheritance was invented as a performance hack

#128

Earlier quoted context omitted.

What's wrong with someone wanting to provide for his offspring?

Ted Kazinsky was talking about it in his manifesto. https://unabombermanifesto.com/#THE%20POWER%20PROCESS It depends on how much you provide for your offspring according to this deranged terrorist. And I've read stories from billionaire kids not living "the good life" because they never have to fight/work for anything.

That's just bad parenting.

I think rich people tend to be people obsessed with work, giving access to money is easier than teaching their kids to earn stuff - it is a different problem.

Re: Inheritance was invented as a performance hack

#129

I think discussions of OOP and inheritance often miss the influence of Knowledge Representation on OOP: I’m not entirely clear of the history myself, but I’ve gotten the impression that knowledge representation research (things like frame systems) was a semi-independent influence on the design of OO systems

>discussions of OOP and inheritance often miss the influence of Knowledge Representation on OOP: I’m not entirely clear of the history myself,

Fyi... The "knowledge representation" aspect of OOP inheritance is emphasized by computer science professor Andrew P. Black. He wrote a long paper[1] about it and also has a video[2]. It's unfortunate that Black's alternative perspective (which he shared with Philip Wadler) is not discussed as often as "Object-Oriented Programming is Bad"[3] videos.

His paper is a long read (over an hour) that covers the intellectual history of OOP starting with Simula/Smalltalk. The following is an excerpt from https://www.sciencedirect.com/science/article/pii/S089054011...:

Most of us can grasp new ideas most easily if we are first introduced to one or two concrete instances, and are then shown the generalisation. To put this another way: people learn best from examples. So we might first solve a problem for , and then make the changes necessary for 4 to approach infinity. [...]

To illustrate the power of inheritance to make complex abstractions easier to understand, letʼs look at a case study from the functional programming literature. In Programming Erlang [19, Chapter 16], Armstrong introduces the OTP (Open Telecom Platform) generic server. [...]

To make sure that the message about the way that the OTP server works does sink in, Armstrong presents us with four little servers … each slightly different from the last. server1 runs some supplied code in a server, where it responds to remote requests; server2 makes each remote request an atomic transaction; server3 adds hot code swapping, and server4 provides both transactions and hot code swapping.

Each of these “four little servers” is self-contained: server4, for example, makes no reference to any of the preceding three servers.

Why does Armstrong describe the OTP sever in this way, rather than just presenting server4, which is his destination? Because he views server4 as too complicated for the reader to understand in one go. Something as complex as server4 needs to be introduced step-by-step. However, his language, lacking inheritance (and higher-order functions) does not provide a way of capturing this stepwise development.

In an effort to understand the OTP server, I coded it up in Smalltalk. [...] First I translated server1 into Smalltalk; I called it BasicServer, and it had three methods and 21 lines of code. Then I needed to test my code, so I wrote a name server plug-in for BasicServer, set up unit tests, and made them pass. In the process, as Forsythe had predicted, I gained a much clearer understanding of how Armstrongʼs server1 worked. Thus equipped, I was able to implement TransactionServer by subclassing BasicServer, and HotSwapServer by subclassing TransactionServer, bringing me to something that was equivalent to Armstrongʼs server4 in two steps, each of which added just one new concern.

Once I was done, I discussed what I had learned with Phil Wadler. Wadler has been thinking deeply, and writing, about functional programming since the 1980s; amongst other influential articles he has authored “The Essence of Functional Programming” [21] and “Comprehending Monads” [22]. His first reaction was that the Erlang version was simpler because it could be described in straight-line code with no need for inheritance. I pointed out that I could refactor the Smalltalk version to remove the inheritance, simply by copying down all of the methods from the superclasses into HotSwapServer, but that doing so would be a bad idea. Why? Because the series of three classes, each building on its superclass, explained how HotSwapServer worked in much the same way that Armstrong explained it in Chapter 16 of Programming Erlang. This was an “ah-ha moment” for Phil.

To summarise: most people understand complex ideas incrementally, by starting with a simple concrete example, and then taking a series of generalisation steps. A program that uses inheritance can explain complex behaviour incrementally, by starting with a simple class or object, and then generalising it in a series of inheritance steps. The power of inheritance is that it enables us to organise our programs incrementally, that is, in a fashion that corresponds to the way that most people think.

[1] https://www.sciencedirect.com/science/article/pii/S089054011...

[2] https://www.youtube.com/watch?v=Rmg_trKnanU

[3] https://news.ycombinator.com/item?id=19407599

Re: Inheritance was invented as a performance hack

#130

Earlier quoted context omitted.

I read it similarly as "inheriting money". And it's true that inheritance IS a performance hack--not for the children, but for the parents. Inheritance incentivizes parents to accumulate wealth not just for one lifetime but for multiple lifetimes. (Granted it may paradoxically have the opposite effect on the children as you mention.) Here's Milton Friedman on the matter: https://www.youtube.com/watch?v=km9OCw3f5w4

Inheritance is a natural phenomenon. If all my money were stolen when I die (let's say, 100% inheritance tax), I wouldn't have much incentive to grow my business more once my business makes more money than I can possibly spend in a lifetime. Sure, some people may still do it because they love working or because they love providing for their society. The main reason I want to accumulate money, is so I can offer them a…

> Inheritance is a natural phenomenon.

Biological inheritance, property inheritance, however, is not.

> If all my money were stolen when I die (let's say, 100% inheritance tax), I wouldn't have much incentive to grow my business more once my business makes more money than I can possibly spend in a lifetime.

Even if one agrees that that is true, that’s not an argument that inheritance is natural, that’s an argument that it is a feature of society chosen to incentivise people to accumulate wealth surplus to their personal needs.

Post reply on HN