3 ms·
Julia's function polymorphism shines in a lot of cases, but in general it is less powerful than the OOP solution and also I find it much more difficult to read.
by smabie 6y ago
Julia's function polymorphism shines in a lot of cases, but in general it is less powerful than the OOP solution and also I find it much more difficult to read.
For example, I recently ran into this problem when prototyping a new Julia library. Without going too into the specifics, I can only match on a type of a object. With Scala say, I can override the method of an object at creation without actually defining a class.
In order to do a similar thing with Julia, I have to package the function as a field of the struct, I can't do multiple dispatch on it.
In general I think multiple dispatch is great for the incremental adding of new functionality without modifying the original source but bad at dynamically augmenting functionality at runtime.
A common example in Scala is creating an iterator. I can override the next and hasNext methods at object creation instead of creating a whole new class with a name. With Julia I would have to define a new kind of iterator at the top-level and then implement the necessary functions.
Let's say I want to have an iterator type of numbers in which I want to multiply or add constants to. In Scala I can easily return a new iterator that wraps the old one with overridden methods that adds or multiples by the constant. I could write
val newIter = 2 + iter
Or whatever and with the right definition of +, everything would work correctly. In Julia I belive the only way to make this work would be to package the next and hasNext functions (or their Julia equivalents) inside the struct itself, which is unidiomatic I believe.
Also the amount of type-piracy can get a little annoying. A lot of libraries end up defining alternative dispatches that are inappropriate.
For Julia's problem domain, I do think this approach makes more sense than OOP and leads to saner scientific code. A lot of Python scientific computing libraries have these crazy baroque mutation heavy brain dead OOP interfaces that serve no purpose. It's just that in some cases, the packaging of data and functions together is really the only way to sanely solve a given problem.
- ChrisRackauckas 6y ago>Julia's function polymorphism shines in a lot of cases, but in general it is less powerful than the OOP solution and also I find it much more difficult to read. Given that OOP is single dispatch and multiple dispatch is a strict generalization, that's not just wrong or an opinion but it's a statement that can't be true. a.b(x) is equivalent to b(a,x) where b is a (possibly callbale struct) function you allow dispatching on a but not x. Multiple dispatch is the case where you can, well, dispatch on both. >Without going too into the specifics, I can only match on a type of a object. With Scala say, I can override the method of an object at creation without actually defining a class. You could also just drop to Val to dispatch on values or even define calls from the parameters like GeneralizedGenerated. That's pretty much the behavior you're trying to recreate so that would just do it directly. It's not the most common thing to do since you will hit dynamic dispatch, but of course if you're trying to dynamically add or change functions that's bound to happen. >Also the amount of type-piracy can get a little annoying. A lot of libraries end up defining alternative dispatches that are inappropriate. Interesting. Can you please make a list?
- snicker7 6y agoYour example is specific to not all OOP languages, only those that have prototypical inheritance.