4 ms·
It was rather confusing and I consider myself well-informed about the expression problem. But to give you some constructive feedback, your understanding, or yo
by choeger 6y ago
It was rather confusing and I consider myself well-informed about the expression problem.
But to give you some constructive feedback, your understanding, or your writing, of the expression problem lacks two fundamental concepts:
First of all, in functional languages it is as simple as in object-oriented languages to add new data types. It hard to add a variant of an existing datatype. In object-oriented languages it is also trivial to add new functions, but it is hard to add a new function for all derivates of a class. So it would be more like having a table for perfectly cooking all variants of fish.
And secondly, the solution offered by Julia is also incomplete. Both functional and object-oriented languages give you completeness guarantees. So the compiler will warn you when you miss a variant of fish (functional) for a method or a method for a particular fish (object-oriented) At least to my understanding the completeness of methods (that's the right term, no?) in Julia is unchecked. You can extend, but you can easily miss a case.
The same (unchecked extensions) can be done in functional languages with open algebraic datatypes and in object-oriented languages with default methods that throw exceptions.
- leephillips 6y agoThanks for this detailed criticism, it’s quite useful. My understanding is that for functions with more than a few arguments, it is expected in Julia that only a small subset of the possibly thousands of combinations will be covered. Thousands, because with multiple dispatch you dispatch on the types of all the arguments. The binary operator “*” in Julia has 364 methods, and that just takes two arguments. So you define the ones that are useful.
- choeger 6y agoSure, that is an absolutely sensible design decision. But for other cases completeness is vital. Consider for instance the trivial case of the map function over lists (constructed by :: and []), often abbreviated as * : f * [ ] = [ ] f * a::as = (f a)::(f * as) Even if that is a nearly trivial case, it is easy to see that one could forget the first case, as all the interesting bits happen elsewhere. Now imagine, I would want to have a lazy reversal of lists, that I store as an alternative until I need to deconstruct it. I write that x~xs, meaning "x added to the end of xs". Now I have to expand my map function as follows (because map does not care about ordering): f * a~as = (f a) ~ (f * as) If I miss that case (or method on Julia's case) my extension of the datatype is plain wrong.