On Monday, October 19, 2015 at 12:17:16 PM UTC-4, Tom Breloff wrote: > > Here's an example where there would normally be a strict hierarchy in > classic OOP: Square <: Rectangle <: Shape > > But it actually makes much more sense in Julia (why have 2 fields for > Square??): >
Unfortunately most of the classic examples are simplified to the point of not being informative. A previous example I gave was the NN design of Torch7, where each module has an `output` and a `grad_input` parameter. The forward/backward ops of each module is different, but it's important to have those common variables. > > Now I completely agree that ensuring a compile-time agreement of interface > is a valuable part of the language (but should ideally be optional). > People do see value in this, and it's an active design discussion. (search > for "traits") > I did take a look at what the Traits people were doing. Unfortunately, at least last time I looked at it, it still seemed to require a lot of code copying. > > For composition vs inheritance, I completely agree that sometimes it's > nice to save code/typing when you have structures with a bunch of fields > that are mostly the same. I'd argue you don't actually care about > inheritance, you just want composition but without the extra layer of > structure. > I strongly agree with this. If you hide all direct access to variables and only allow access via an interface, you can define a type as a composition of other types and a list of supported interfaces: @compose C(protocol1, protocol2) <| (A, B) other::AbstractString end Above, a relatively simple macro can replace all the "Type..." with the > fields of the composed types, applying multiple inheritance of the > structures without the baggage required in classic OOP. Then you can > compose your type from other types, but without having to write > "unicycle.wheel.radius"... you can just write "unicycle.radius". > I suggested such a macro awhile ago (maybe a year?), and it was met with disapproval. Not that that should stop anyone from writing it, but it was deemed un-Julian (at least my take on people's responses). I think this can be seen as a type of mix-in similar to what Ruby and Scala do. > > On Mon, Oct 19, 2015 at 11:32 AM, Abe Schneider <[email protected] > <javascript:>> wrote: > >> I think I agree with 90% of what you wrote. I also don't know if anyone >> is arguing about single or multiple dispatch. Also, while Java and >> Borland's Object Pascal claimed a strong OO paradigm, C++ does does not (if >> you read Bjarne's design guide, he felt strongly that both OOP and >> functional were important). I'll note too, Java has slowly been moving >> towards a multi-paradigm approach by including Lambdas in the latest >> version. >> >> Two of the languages you list below, Swift and Scala, also mix OO and >> functional programming. While Scala has a huge push for functional >> programming, it also provides the necessary constructs to talk about >> inheritance of data (while it doesn't provide multi-inheritance, it does >> have mix-ins). >> >> I really like Julia's multi-dispatch approach, and have made great use of >> it in my own libraries. I don't think there should be any reason that >> classes should have to "own" the methods. However, what it currently >> doesn't do, is provide a method to specify the relationship of data within >> types between each other. You stated in the past this is because you want >> to keep dispatch-type separate from representation type. However, I think >> that's actually one of the most important aspects of OOP. Yes, you can >> always write an interface that assumes that each type has variable X, but I >> would claim ultimately that creates less maintainable code (partially >> because of DRY and partially because it turns what should be a compile-time >> error into a run-time error). >> >> On Sunday, October 18, 2015 at 11:28:20 PM UTC-4, Stefan Karpinski wrote: >>> >>> It's a highly debatable claim that single dispatch class-based OO leads >>> to better or more maintainable software designs. I grew up on these kinds >>> of languages – Object Pascal, C++, Ruby, Java. Despite the ongoing rhetoric >>> that this paradigm solves all sorts of program design problems, that's just >>> not what I've seen. I think this style of programming has failed to be the >>> panacea that it was promised to be. If it was really such a success, then >>> we wouldn't be seeing a fresh crop of promising new programming languages – >>> Julia, Rust, Go, Clojure, Scala, Elixir, Elm, Swift, etc. – not a single >>> one of which is a traditional class-based OO language. The message is >>> clear: we need more effective solutions. So far, Julia's multiple dispatch >>> approach seems to me far better at addressing program maintainability and >>> extensibility than classes ever were. Julia does still need a way of >>> talking about interfaces and protocols in the language itself, but that's >>> ongoing design problem, not a fundamental issue. >>> >>> On Mon, Oct 19, 2015 at 8:18 AM, Abe Schneider <[email protected]> >>> wrote: >>> >>>> >>>> >>>> On Sunday, October 18, 2015 at 9:44:21 PM UTC-4, [email protected] >>>> wrote: >>>>> >>>>> Going a bit on a tangent, I claim that object-oriented programming, at >>>>> least as embodied in C++, is not really suitable for scientific computing >>>>> and in fact has led certain codes to go astray. >>>>> >>>> >>>> C++ is purposefully a multi-paradigm language for this reason. C++11 >>>> added a lot of features specifically for functional aspects of the >>>> language. >>>> >>>> >>>>> >>>>> To give a simple example, suppose you are told to write a 'matrix' >>>>> class in C++ that contains all the usual operations. You finish writing >>>>> your class, and a week later, you are told to derive 'symmetric matrices' >>>>> as a subclass of 'matrices'. This is trouble! Unless you wrote your >>>>> original matrix class in a very particular way, you will have a hard time >>>>> writing a symmetric matrix class that inherits from a matrix base class. >>>>> This is not just a theoretical example; I saw someone try to do this >>>>> (unsuccessfully) in a code he had written. >>>>> >>>> >>>> >>>> Sure, you always have the option to write bad code, but that doesn't >>>> make a particular paradigm good or bad. I think Torch7 has a good example >>>> of using object oriented programming for scientific programming. >>>> >>>> >>>>> >>>>> The problem with object-oriented programming is that you have make >>>>> design decisions when you write the base classes that lock you into a >>>>> certain path. This path may not be compatible with the flexibility >>>>> needed >>>>> for scientific software projects. >>>>> >>>> >>>> I think that's true with any language. In Julia you still have to >>>> define an interface to access the variables. Yes, there are fewer >>>> mechanisms in place that restrict access, but that isn't always a good >>>> thing. You end up trading compile-time errors for run-time errors. I much >>>> rather deal with compiler-time errors. >>>> >>>> >>>>> >>>>> I for one am glad that the designers of Julia decided not to make >>>>> Julia an object-oriented language, at least not in the C++ sense of the >>>>> term. >>>>> >>>>> >>>> I think there is a lot to be gained from a multi-paradigm approach. >>>> Having a language that is scientific-code friendly is important, but so is >>>> integrating it into larger systems. >>>> >>>> >>>>> >>>>> >>>>> >>>>> On Sunday, October 18, 2015 at 8:41:58 AM UTC-4, Sisyphuss wrote: >>>>>> >>>>>> When I'm learning Julia, I am always thinking what is the correct way >>>>>> to do OOP in this language. It seems to me that what I learned in C++ >>>>>> does >>>>>> not apply in Julia. >>>>>> >>>>>> It took me long to realize that the equivalent of Class of C++ in >>>>>> Julia is not Type, but Module. Module is the basic function unit in >>>>>> Julia. >>>>>> >>>>>> Thus, a Class in Julia is like >>>>>> module ClassName # class Name { >>>>>> using # include<> // should be outside >>>>>> import # include<> >>>>>> export function # public function; >>>>>> var = 1 # private static var; >>>>>> end # } >>>>>> This provides the same structure as C++. >>>>>> >>>>>> However, this design has two issues: >>>>>> 1) The visit control is not as fine-grained as in C++, the >>>>>> encapsulation is not strict; >>>>>> 2) Variables at the top level of a module are global variables. >>>>>> >>>>>> These two points are closely correlated. If we let module have >>>>>> private variables, then they are not too different from local variables, >>>>>> ans thus can be type inferred. >>>>>> I think this is a natural way to do OOP with Julia. >>>>>> >>>>>> >>>>>> >>>>>> >>> >
