Hacker News new | ask | show | jobs
by mumblemumble 1690 days ago
That's an interesting position to share in the context of a discussion about Racket, since Racket embraces object-oriented programming. It's not purely OO, of course, but quite a few core libraries rely on its OOP features.
1 comments

That might be for historical reasons. (IIRC, mostly, OO was the GUI libraries, and what's layered directly on top of those.) OO is no longer as en vogue, in either Racket or the broader field. In Racket, you'll see a lot of code using `struct`, and without traditional gratuitous use of object classes for everything.

https://docs.racket-lang.org/guide/define-struct.html

> New datatypes are normally created with the struct form, which is the topic of this chapter. The class-based object system, which we defer to Classes and Objects, offers an alternate mechanism for creating new datatypes, but even classes and objects are implemented in terms of structure types.

That's my usual assessment, but today at RacketCon Ryan Culpeper gave a strong case for using OO more in Racket, with a demonstration of his point in his new http client library.
> traditional gratuitous use of object classes for everything

This sort of phrasing is sort of distressingly characteristic of contemporary discussions about object-oriented programming.

I can understand where it comes from - if you look through my comment history, you'll probably find plenty of examples of me running my mouth about Java or the overuse of OOP in Python - but I assure you there is a baby in all of that bathwater, and it doesn't need to be thrown out. That baby is dynamic dispatch, and it does let you do some things that can be a hassle without it.

Unfortunately, it tends to be poorly taught or poorly understood nowadays. This is not a "no true Scotsman" argument. I'm not saying no true hammer would be used to drive screws. I'm just observing that, if a carpenter was never taught about screwdrivers, it's no surprise they'll develop a lot of pent-up frustration about hammers, and perhaps even be a bit confused about what they're really for. It seemed to me that one of the core sections of the essay ikrubner linked above rested on a conflation of dynamic dispatch and dynamic typing. Which is a worrisome thing I've seen many people do. It's no wonder we don't use OOP well, living in an intellectual environment where its only truly distinguishing characteristic rarely even makes it into lists of its key features. So, perhaps it's even worse than just having only been given a hammer. We were only given a hammer, and were also never taught about nails.

Anyway, enough complaining. Let's take Racket's image drawing library as a positive example. It's implemented around an object-oriented interface. What this does is lets you write code against that interface, so that it is able to output graphics to any format that has a suitable implementation of that interface, without needing any special glue code or explicit branching logic to make it happen. I would argue that this is quite useful.

As a contrasting example, Haskell's typeclasses are superficially quite similar, but, since they use static dispatch, adding a new output format does tend to require some glue code - not much, but still more than zero - that's specific to each drawing routine you want to hook up to that new format.

There's a nice essay, https://www.sicpers.info/2018/03/why-inheritance-never-made-... , that serves as an excellent excoriation of the C++/Java/etc lineage of OOP. But one key thing needed to contextualize it is that OOP mechanisms like Racket's or CLOS aren't trying to do OOP in the same way that Java does, and therefore don't run afoul of the same shortcomings. In particular, they're not trying to turn it into a single golden hammer that solves all abstraction problems. Racket gets a lot more mileage out of its module mechanism, for example.