5 ms·
You’re always going to be on one side of the expression problem [0]: either your operations live with your datatype (classes), which makes it inconvenient to ad
by tomstuart 7y ago
You’re always going to be on one side of the expression problem [0]: either your operations live with your datatype (classes), which makes it inconvenient to add a new operation, or they live somewhere else (“functional modules”), which makes it inconvenient to add a new case to the datatype. This choice is probably informed by your expectations of how often you intend to do either of those things, but there’s going to be inconvenience regardless.
The big benefit of objects, and therefore classes (or something like them), is polymorphism via dynamic dispatch; it seems a shame to throw the baby out with the bathwater because you don’t like inheritance or mutable state, both of which are independent of the choice to use classes.
[0] https://en.wikipedia.org/wiki/Expression_problem https://en.wikipedia.org/wiki/Expression_problem
- bcrosby95 7y agoThere are languages that solve the expression problem, such as Clojure. But they aren't very popular.
- Scarbutt 7y agoIn some languages runtime polymorphism is not tied to types.
- keymone 7y agohttps://clojure.org/reference/multimethods https://clojure.org/reference/multimethods
- CuriousSkeptic 7y agoI’m not sure dynamic dispatch is that much of a killer feature. Take C# it default to static dispatch of method and you tend to get very far without explicitly making things virtual. Event when using interfaces many times it’s seems possible to arrange things such that parametric polymorphism would be able to use a static type. There are some boiling proposals for future versions that will help with exactly this, and indeed some of the latest changes to the languages have included allowing more static dispatching in polymorphic constructs like disposal and enumeration. I’m beginning to suspect that dynamic dispatch could be entirely dropped without losing to much expressiveness. Have no experience with Rust but isn’t that kind of the conclusion from that community?
- meheleventyone 7y agoI think that's broadly true but it should at least be pointed out that static dispatch tends to end up inflating binary size and compilation time. Rust also supports dynamic dispatch so you can make a context dependent choice.
- hashmal 7y agoStatic dispatch or monomorphization?
- meheleventyone 7y agoIsn’t using parametric polymorphism to get static dispatch reliant on monomorphization? That’s at least the common case in Rust.
- everettwilson 7y agoNot really anything of an expert with Rust, but I'd say that the language tries to dispatch function calls statically whenever possible, though it certainly has the capacity to provide polymorphism when needed, through the use of trait objects [0]. From using it personally, I've found that I can usually get by with generics and the static dispatch that they provide, but having the option to use trait bounds can be a real boon when you need the flexibility to call on shared pieces of functionality between separate complicated systems. [0] https://doc.rust-lang.org/1.30.0/book/2018-edition/ch17-02-trait-objects.html#trait-objects-perform-dynamic-dispatch https://doc.rust-lang.org/1.30.0/book/2018-edition/ch17-02-t...
- jbjohns 7y agoWhat's more, languages like Smalltalk which only have "virtual" dispatch achieve their performance by recognising that most dispatch is just to one type. And of the remaining cases, most of those are just to 2 types, etc. Pushing this further resulting in Strongtalk which lead to the Hotspot JVM [1]. [1] http://strongtalk.org/index.html http://strongtalk.org/index.html
- AnimalMuppet 7y ago
- ledauphin 7y agoOTOH, classes are just one way of doing polymorphism/dynamic dispatch. see Clojure's multimethods.