I think maintainers of C++ have a case of "functional programming" envy.
I think maintainers of C++ have a case of "functional programming" envy.
If you want to make a closed set of subtypes that's usually possible only by writing a class hierarchy with private subtypes and an abstract outer type with factory methods for the inner types. That takes hundreds of lines for even just a couple of variants, and then there is still no compiler help for exhaustive switch/match.
FP doesn't have many things C++/D etc. have. Should we insist on every FP to have assembly-level access, custom memory managers etc. because they are cool as well?
It's already possible to make the class hierarchy in most/all OO languages but it takes 150 lines for what can be expressed in 5 with some help from the language. Most importantly, without lang support the compiler can't validate exhaustive matching.
More importantly it's the second category of type relations. There are product types and there are sum types, if you only have product types, you're missing an entire half of expressible type relations/compositions.
It's not a matter of functional versus imperative, there's nothing inherently functional about sum types.
In OO it's "abstract class PaymentMethod" and then another 100 lines, plus probably a horrible visitor pattern (because you don't want the payment method handling the payment). This to just define the type, no actual payment logic.
Huge amounts of boilerplate, and very little power if the compiler can't ensure exhaustive matching.
yes. all the languages should converge (and the relevant ones actually do)
In object oriented languages this pattern is mostly unnecessary, because inheritance is usually better solution for the same problem. Only reason to use something like this in C++ is (maybe even only perceived) efficiency gained by removing level of pointer indirection.
It really comes from functional languages like ML, and is extremely useful and convenient when combined with pattern matching. In fact, attempts to emulate it in OOP using interfaces and visitor pattern tend to bring a lot of boilerplate, and obscure the actual logic, which is exactly what the author is complaining about.
There's definitely more reason to use it than just "efficiency gain", which is why many languages introduced in the last decade have it built in (e.g. Rust, Scala or Swift).
Could you say something about the difference between the two? I'm not aware what it is.
Edit: wow I accidentally a word.
data Choices = Good | Bad | Ugly
like I can do in haskell, where a value of type `Choices` can only ever be one of those options. But there doesn't seem to be any reasonable approximation in python. class AbstractChoice:
# defines all common operations on choices
# plus potentially some useful stuff on top of those
pass
class Good(AbstractChoice):
# conatins the code specific to good things
pass
class Bad(AbstractChoice):
pass
class Ugly(AbstractChoice):
pass
This isn't a straight-on replacement though. It's especially bad when you want to separate your concerns not along the good-bad-ugly-axis but something different (which is when you'd e.g. go on to use mixins, or that ugly visitor pattern we've seen in the OP).