logoalt Hacker News

sunshowers01/24/20251 replyview on HN

> Flexibility increases your "design space" and hence never a weakness.

This is just objectively false. Constraints liberate and liberties constrain.

> Rigorous discipline is needed throughout development but tooling can only do so much.

Have you used Rust? I would recommend building some kind of non-trivial command line tool with it — you will quickly see how low your expectations for tooling have been.

> Eg: Base.method() has {pre1} and {post1} as contracts. Derived.method() has {pre2} and {post2} as contracts. What should be the relationship between {pre2}&{pre1} and {post2}&{post1} to enforce proper subtyping?

As someone who understands variance etc quite well, my answer is to simply not have subtypes. You absolutely do not need inheritance subtyping to build production software. (Rust has subtyping and variance only for lifetime parameters, and that's confusing enough.)

> Sure, there are other types of polymorphisms which can be better in certain scenarios. But that is not under discussion here; we are talking about "traditional" dynamic runtime dispatch based polymorphism which is far easier to understand and implement even in small languages like C.

I use traits for runtime dispatch in Rust all the time?

Inheritance is only traditional because C++ and Java made it so. I think it's been a colossal mistake.


Replies

rramadass01/24/2025

> This is just objectively false. Constraints liberate and liberties constrain.

You are completely wrong here. Flexibility by definition means an increase in the allowed degrees of freedom in one or more axes which in turn allows one to mix and match feature sets to express more design concepts (eg. Multi-paradigm). Your second line is a silly slogan which presumably means constraints make the job of picking one choice from a set easier due to less thought needed. It is applicable to inexperienced developers but certainly not to experienced ones who need all the flexibility that a language can give.

> As someone who understands variance etc quite well, my answer is to simply not have subtypes. You absolutely do not need inheritance subtyping to build production software. (Rust has subtyping and variance only for lifetime parameters, and that's confusing enough.)

You have not understood the example. Variance is used to constrain types but pre/post are predicates relating subsets of values from the types; this constrains the state space (cartesian product of the types) itself. Second, your statement not to use subtyping is silly. Subtype relationships arise naturally amongst concepts in any non-trivial system which you can group in a hierarchy based on commonality (towards the top) and variability (towards the bottom). Inheritance is just a direct way of expressing it.

> Inheritance is only traditional because C++ and Java made it so. I think it's been a colossal mistake.

Statements like these betray an ignorance of the subject. I have already shown that Inheritance can be used for different purposes of which Subtyping in the LSP sense is what everybody agrees on. The other uses need experience and discipline but are very powerful when done clearly. Inheritance was first introduced in Simula67 based on a idea presented by Tony Hoare in 1966. C++ popularized it and others simply copied it. See wikipedia for more details - https://en.wikipedia.org/wiki/Inheritance_(object-oriented_p...

PS: This discussion reminded me of "The Blub Paradox" by Paul Graham (https://paulgraham.com/avg.html) which i think most Rust evangelicals suffer from. Just from my cursory look at Rust i have seen nothing compelling to want me to study it in depth over my preferred language of C++. With the addition of more features into "Modern C++" to support Functional Programming it has become even more flexible and powerful albeit with a steeper learning curve.

show 1 reply