@Stefan First of all, thank you very much for your detailed comments. As I said I find Julia great and I would like to see if I can gradually use it in my workflow. My intention with my questions was only to get some clarity from the experts on some points that I failed to understand just by reading docs and previous discussions.
Let me just make some brief friendly comments on your points :) 1,2) Regarding the multiple dispatch topic: I've got your point, multiple dispatch in Julia is easier and natural, not an afterthought as in C++/Java etc. 3) Encapsulation: > External dispatch does make it non-obvious how to enforce encapsulation True, but for example, there are some proposals (Scott's one) where you can explicitly indicate that some fields are private to the module where the type is defined. This is just a proposal that, as Scott pointed out, is opt in, will not break anybody's code and I honestly do not think adds any significant complexity to the language. But, hey, this is just 'a' proposal. > Python, for example, doesn't have private members, and this doesn't seem to lead to any kind of orgy that I've ever noticed. True, I am happy to have everything public like in Python. But at least like in Python you have a clearly defined policy that everybody follows and even more, the language helps with name mangling. So even for newbies, is it almost impossible to breach the policy because they will get errors and if they take the time to understand what is going one and mangle the name to get access then they are painfully aware of what they are doing. So may be, doing something similar in Julia could be just another proposal. > You may find it strange for a language not to have class-based single-dispatch object-orientation because both of the languages you've used happen to have this model. Actually I do not find this strange, I played with Haskell for some time, and even Mathematica and Fortran in ancient times so I more than happy to use a functional style or any other style. So more than happy with Julia here :) Cheers, Julian On Wednesday, July 8, 2015 at 12:38:01 PM UTC+2, Stefan Karpinski wrote: > > On Sun, Jul 5, 2015 at 7:30 PM, Julian Manzano <[email protected] > <javascript:>> wrote: > >> Hi All, >> >> I have been using C++ and Python for several years >> > > I'll comment on this later... > > >> and I am very curious about Julia, I've got the REPL working on my >> workstation and I am really impressed so far with what I've seen. >> > > Thanks :-) > > >> However there are some design decisions in the language that I fail to >> understand and I would really appreciate if someone could explain the >> rationale: >> >> The main point that I fail to understand is the decision not to allow >> member functions. >> The typical explanation that I find everywhere is that Julia designers >> have chosen all the methods to be external because this is cleaner >> (specially for mathematical methods where there is no clear owner) and >> allows for multiple dispatch. >> This explanation does not convince me for the following reasons: >> >> 1) We can have multiple dispatch a la Julia and still allow types to have >> methods. These two things seeem independent to me. >> > > These things are distinct but not orthogonal. Multiple dispatch is a > generalization of single dispatch. As such, it is strictly more expressive, > and having two separate dispatch mechanisms – a weak one for "internal" > methods and a more powerful one for external methods – would be > non-orthogonal while not increasing the overall expressive power of the > language at all. That's lose-lose from a language design perspective. > > >> 2) Dynamic multiple dispatch can also be done as a byproduct of single >> dispatch using the visitor pattern (C++, Java, etc.), so in that sense, >> multiple dispatch is not a new feature. >> > > This isn't really true – or at least double dispatch requires an > unacceptable amount of coupling between classes that should be unrelated to > emulate proper multiple dispatch. This article > <https://www.rconconi.com/csblog/2013/double-dispatch-the-visitor-pattern-the-expression-problem-java> > > has a pretty lucid explanation of the issues. In particular note the bit > about the price of double dispatch: > >> >> - Adding new shapes will be cumbersome: we will have to change all >> existing visitors to add the new case. >> >> >> - Dangerous for bugs too: when adding new subtypes of Shape, one >> might easily forget to override the accept method which will lead to >> unwanted behaviour: All visitors would treat instances of the newly >> created >> type like its super type. >> >> So, single dispatch allows you to emulate multiple dispatch, but only > awkwardly and in a way that makes any instance of the expression problem > (and they are not uncommon at all) a maintenance nightmare. > > Consider how to make `1 + obj` work just as well as `obj + 1` – i.e. how > to make dispatch symmetric for a new type with a pre-existing type. In > Python you can use __radd__ methods, but this is clearly a hack that just > addresses this one particular instance of the expression problem in a > non-general way. What you really need here is precisely multiple dispatch – > with it, this is completely trivial to do. In fact, with Julia's promotion > and conversion system > <http://julia.readthedocs.org/en/latest/manual/conversion-and-promotion/> > (which is really just a clever application of multiple dispatch), you don't > have to explicitly handle this case, you just provide the appropriate > promotion rules and you can solve this entire class of promotion problems > all at once in a completely general and extensible way. This is, in fact, > how mixed-type arithmetic between built-in types are defined: > > julia> @less 1 + 2.3 > +(x::Number, y::Number) = +(promote(x,y)...) > > If you define your own type, you hook into the same system and it just > works. And it's efficient. Despite the fact that really basic mathematical > operations like + are generic functions and mixed type addition > conceptually goes through many layers of dispatch, it still boils down to > the minimal two instructions: > > julia> @code_llvm 1 + 2.5 > > define double @"julia_+_21457"(i64, double) { > top: > %2 = sitofp i64 %0 to double > %3 = fadd double %2, %1 > ret double %3 > } > > > Compare this with the cost of dynamic dispatch through a vtable even in a > fast language like C++ – if you had to do addition with two jumps through > vtables, it would be a performance disaster. Perhaps you could backport > some of the technology from Julia to a single dispatch design. In fact, > modern C++ compilers rely heavily on devirtualization, which is essentially > a mild form of how Julia's compiler manages this, but I'm really not sure > if it would work in the large – there's a strangely nice synergy between > dynamic type inference and multiple dispatch. Expressing complex > polymorphic behaviors using dispatch is not only convenient, it also gives > the compiler a huge amount of type information in a form that it can reason > quite effectively about. > > >> 3) Lack of member functions forces all field to be public and therefore I >> cannot understand how Julia will avoid the object orgy anti-pattern ( >> https://en.wikipedia.org/wiki/Object_orgy) >> > > External dispatch does make it non-obvious how to enforce encapsulation. > However, lots of languages don't enforce member encapsulation and get by > just fine. Python, for example, doesn't have private members, and this > doesn't seem to lead to any kind of orgy that I've ever noticed. They have > a convention that members starting with _ are private and that works pretty > well – if you access one of those and your code breaks in the future, you > have only yourself to blame. In Julia, we take this attitude a bit further > and consider all fields private unless otherwise indicated in the > documentation of a type. So far this hasn't caused trouble. > > You may find it strange for a language not to have class-based > single-dispatch object-orientation because both of the languages you've > used happen to have this model. While it's been fairly successful, this > model hasn't been the panacea that it was touted to be in the 1990s and > early 2000s. There are many programming languages that don't work this way > at all and don't miss it. C is still the most popular language and doesn't > do this. Almost all the functional languages don't do things this way. Give > the multiple dispatch paradigm a try for a while. I think you'll find that > it grows on you. Fair warning: after getting used to it, it's hard to go > back. >
