Problem is, some fields for some cases should be public, because this is 
the most natural option...

On Wednesday, July 8, 2015 at 1:56:37 PM UTC+2, Milan Bouchet-Valat wrote:
>
> Le mercredi 08 juillet 2015 à 12:37 +0200, Stefan Karpinski a écrit : 
> > 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 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 (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. 
> Then maybe this fact should be stressed more in the documentation. For 
> example, in the manual, nothing implies that fields should be 
> considered private at all: 
> http://docs.julialang.org/en/latest/manual/types/#composite-types 
>
> In the recent discussions, I had the feeling that many contributors 
> weren't clear on whether fields are considered private or not. 
>
> Also, to me the project of being able to overload the a.b field access 
> syntax [1] goes against the idea that fields are private. In that 
> issue, that feature was even considered as a way of implementing an 
> abstraction on top of a given structure. That's probably fine as long 
> as it's only used by packages interacting with other languages where 
> the convention is different, but beyond that it would really blur the 
> message about private fields. 
>
> So basically, I think we should be absolutely clear about whether 
> accessing fields from external code is subject to breaking at any point 
> or not. (Other than that, I agree with all of your points.) 
>
>
> Regards 
>
>
> 1: https://github.com/JuliaLang/julia/issues/1974 
>
> > 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. 
>

Reply via email to