Hacker News new | past | comments | ask | show | jobs | submit login

Forgive my ignorance of Rust, but GUI toolkits are probably the strongest candidate for OOP style development, and everything I've read about Rust doesn't lend itself well to OOP.

StyledObject -> View -> Text

StyledObject -> View -> ViewContainer -> Button -> ToggleButton -> MyCustomToggleButton

StyledObject -> View -> ViewContainer -> VerticalLayout -> ListView




>Forgive my ignorance of Rust, but GUI toolkits are probably the strongest candidate for OOP style development

That's so 1991. We're on to GUI's as pure functions of state these days, get on with the program :-)


There's really no such thing. You might be using pure functions from your perspective, but someone is handling all that backing layer data and mutable information.


There's no such thing as structured programming, at the assembly level it always just compiles down to conditional jumps. There's no such thing as a digital circuit, because real-world voltages are always analogue. Etc.


Which is all dealing with retained, mutable data. Period. I'm not making the comment for the sake of pointing out _levels_ of abstraction.

I made the comment because such an abstraction doesn't at all map to reality.


> Which is all dealing with retained, mutable data. Period.

Only if you choose to model your system that way. You can push the same paradigm all the way through: immutable events, and pure functions that transform an event and a previous (immutable) state into a new state.


No, you really can’t, and that’s what all the functional/immutable evangelists don’t get: you can’t.

You’re going to recreate framebuffers and font atlases and invalidate your entire UI every single time? Good joke.


So much for "not pointing out levels of abstraction". Maybe somewhere in the guts of the low-level runtime a mutable framebuffer is being used for now, sure, but I don't care about that any more than I care about whether my processor is jumping vs doing a conditional move.


Yeah, but some abstractions are leakier than others. I have never hit a real-world voltage bug or conditional jump bug, as far as I remember.


Have you ever hit a bug in the implementation of immutable data? I haven't. (And I have seen a miscompiled loop, though I agree they're very rare).


Well, now that I think about it, I have seen a compiler bug in an IBM Java compiler where an if condition would never be hit, despite the code being fine and the Sun Java compiler working as expected.


I'm not entirely convinced. Libraries like React have succeeded in web development due to the complete lack of html having an extensible component model. Native applications don't have to worry about shoehorning a workable framework into stateless document renderers.


No, this is a larger trend. Both major mobile platforms are moving in this direction as well (SwiftUI, Jetpack Compose).


Tell us more ?


Check out these articles surveying the landscape of reactive UI, from the same author as the linked article:

https://raphlinus.github.io/ui/druid/2019/11/22/reactive-ui....

https://raphlinus.github.io/rust/druid/2020/09/25/principled...


Elm and React for one... and all the other similarly inspired UI libs (even SwiftUI is kind of going there)... Plus the increased interested on fp UIs for games, entity systems, etc...

https://www.freecodecamp.org/news/the-revolution-of-pure-vie...


Cycle.js, Callbags, etc.


As every "flat" hierarchy this is inflexible and impossible to get right (think "ComboBox" or "MenuButton" for example).

A better approach are mixins. Separate ones for layout and behavior. This is much more flexible, and avoids code duplication or "crazy" inheritance hierarchies at the same time.

Rust Traits are ideal for mixins. So a GUI toolkit in Rust should be just fine.


> As every "flat" hierarchy this is inflexible and impossible to get right (think "ComboBox" or "MenuButton" for example).

why does it work fine in Qt then ?


It doesn't work super well. It functions, but there's all kinds of funky interface design which basically exists because of the nature of inheritance.


React is a very popular GUI toolkit and it doesn't use OOP functionality at all.


https://reactjs.org/ says right on the front page: "Build encapsulated components that manage their own state, then compose them to make complex UIs."

Components managing their own state is a textbook definition of OOP.


Encapsulation is not equivalent to OOP. If it is, then why do we have two separate terms for the same thing?


React isn't the one doing the actual drawing.


That's one way to do it, but you could have something very similar that uses composition instead of inheritance (and a nice trait hierarchy to top it off). MyCustomToggleButton would contain an instance of ToggleButton and override some behavior while implementing ToggleButtonInterface or whatever. I don't know if that's the way to go but that'd work.


But rust does have Traits which work perfectly fine for that same logic. We can just say this trait implements the Button and ToggleButton Traits.


> But rust does have Traits which work perfectly fine for that same logic. We can just say this trait implements the Button and ToggleButton Traits.

i've never seen that not being called oop


It pretty much is. But it's not exactly class inheritance, so most people don't consider Rust to be OOP. Structs ("classes" in Rust) can implement Traits and Traits can "inherit" each other, but structs can't inherit implementations from other structs.


> Structs ("classes" in Rust) can implement Traits and Traits can "inherit" each other, but structs can't inherit implementations from other structs.

Right, this is textbook interfaces used for composition.

Let me paste you a few paragraphs from the GoF book, released in 1994:

> Inheritance versus Composition

> The two most common techniques for reusing functionality in object-oriented systems are class inheritance and object composition. As we've explained, class inheritance lets you define the implementation of one class in terms of another's. Reuse by subclassing is often referred to as white-box reuse. The term "white-box" refers to visibility: With inheritance, the internals of parent classes are often visible to subclasses.

> Object composition is an alternative to class inheritance. Here, new functionality is obtained by assembling or composing objects to get more complex functionality. Object composition requires that the objects being composed have well-defined interfaces. This style of reuse is called black-box reuse, because no internal details of objects are visible. Objects appear only as "black boxes."

...

> Object composition has another effect on system design. Favoring object composition over class inheritance helps you keep each class encapsulated and focused on one task. Your classes and class hierarchies will remain small and will be less likely to grow into unmanageable monsters. On the other hand, a design based on object composition will have more objects (if fewer classes), and the system's behavior will depend on their interrelationships instead of being defined in one class.

Like, it's the most well-known OOP design book and it states exactly that - more than a QUARTER CENTURY ago. Who in hell argues that this isn't oop ?!


Even the bible has more than ONE single interpretation, and as much as you would like, GoF isn't the bible of OOP, just a famous book among plenty of others.

Maybe widen the bibliography of OOP programming languages beyond Smalltalk and C++ patterns?


They're not wrong, though - Rust really doesn't need implementation inheritance to be considered OO. It just needs some notion of object identity, and virtual dispatch - and it has both.


Indeed, that is why reducing OOP to implementation inheritance is a very constrained view of the paradigm.

Just like placing ECS against OOP, when they are discussed across OOP SIGPLAN papers and are the genesis of language features like Objective-C, CLOS/Flavor protocols and Smalltalk categories.

I guess, as always, the blame lies in how we teach these subjects and many don't do it properly.


They can, however, derive impls.

Which I consider a better approach than inheritance, ymmv.


Traits are just like Objective-C protocols, pretty much OOP to anyone that bothers to read about the various approaches how OOP concepts can be implemented.

There are plenty of ACM and IEEE papers if you want to see it being called OOP.


So typeclasses in Haskell are OOP as well? Sounds like a pretty meaningless definition.


typeclasses are definitely oo. just because it's compile-time polymorphism doesn't make it "not oop".


OOP is strictly run-time polymorphism. It may be that in some instances of OOP, what calls what is deducible at compile time. That subset alone is not OOP.

OOP means that an object which does not exist now can be written in the future, and loaded into code which has already been compiled and is already running now. The method calls in this existing code will correctly resolve to the method implementations in that object.


Then “OOP” is an entirely meaningless definition. Where exactly are the objects in Haskell?


GUI toolkits have been written in the OOP style since it's the paradigm available. If SML had become popular, I'm sure we'd be writing that.


I got the impression from what I saw (coming into the scene a little too late to say from direct experience) that languages like C++ and Java, intentionally or not, did a great job of capturing how procedural programmers implemented the thick, rich, stateful GUIs that were common at the time. GUI widgets were literally the textbook example that many books used to explain classes and inheritance in a way that procedural programmers could relate to. So, I would say that the OOP style of GUI programming was a continuation of the procedural style that brought the old way of thinking to new "heights" through the new OOP language constructs.


Yes, GUIs have both been greatly benefited by the availability of OOP and a great force on the popularization of that paradigm. I think nobody will disagree that GUIs are kinda hard to create in purely structured code, and OOP makes compares much better.

But we are not at the 80's anymore, and have more options now. There is very little you can do with OOP that you can't in Rust, and a whole lot of things Rust adds to it. Just because things evolved this way it does not mean they are optimal.


Rust is great, but it can't do very basic things that OOP offer. You can't make a simple observer in Rust without RC<RefCell<T>>, unsafe, global-ish mutable state, or being forced into some framework.


You can always copy the observer into the observed structure (and avoid a lot of complications - observers are best created with FP, not OOP). You can also carry the GUI and whatever else you want as a parameter when executing the observer.

But, of course you won't be able to mutate arbitrary global state.


React has been prototyped in SML


And note that it's not oop.


ML is from almost exactly the same time period as SmallTalk and it's work creating GUIs.


The point was that OOP was popular, ML wasn't.


ML was pretty popular in the day.

But my point is that it's pretty weird to bring up SML in particular around GUI programming. The GUI framework only example I know of is mGTK and SML/tk which are far from idiomatic and pretty much require you to write imperative OOP code in SML. Meanwhile SML has existed for decades. It's one thing to say "people aren't using this great model we've developed the basics off, please help make it better", but if you wanted to write an idiomatic GUI app in SML today, your first step would be to have to write the GUI framework itself because no one else has. They don't provide any real options even if you fully buy in and want to jump in with what they're saying.


I'm well aware, what's your point.


The paradigms have been available for pretty much exactly the same amount of time, down to the year.


I'm aware. What's your point?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: