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.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>
>

Reply via email to