Earlier I posted a statement in this thread that object-oriented 
programming is in many cases not suitable for scientific software because 
it forces the designer to make decisions too early in the design process 
that become unwelcome constraints as the project progresses.  

If I understand what people are saying about traits, they may pose the same 
danger.  Just to give a simple example, suppose you are designing a class 
for univariate polynomials over a ring K.  You might expect that you will 
need both dense and sparse (i.e., most coefficients=0) polynomials, so you 
might create an abstract class for both dense and sparse polynomials.  In 
current Julia you might write:

abstract UnivariatePolynomial{T}

where T is the underlying ring.  You would specify nothing else.  Now if 
'traits' were available as a language feature, you might create a member 
function "obtainCoefficient" that would work properly for both sparse and 
dense polynomials.

But the next week, someone asks whether you can handle polynomials 
specified as p(x)=det(A-x*B), where A and B are n-by-n matrices.  For 
polynomials in this format, "obtainCoefficient" is expensive and would not 
be regarded as a simple "getter" operation.  If many people had already 
written functions invoking the 'obtainCoefficient' method, then you would 
be stuck.  You would retrospectively realize that the obtainCoefficient 
member function was not a good idea.  This example is typical of open-ended 
scientific software projects.

So again, I would be wary of adding object-oriented features to Julia, at 
least until the language matures a bit more mature.

I have been on the other side of this fence already: I wrote the code for 
SortedDict in DataStructures.jl.  I had a mandate from Kevin Squire to make 
SortedDict a drop-in replacement for Dict.  Since there is no formal 
interface for 'Dict' defined, and indeed, Julia does not have a  means to 
specify interfaces, this means that I actually have to read all the code in 
associative.jl and dict.jl in order to carry out Kevin's mandate.  But this 
turns out to be not so hard!

-- Steve Vavasis






On Wednesday, October 21, 2015 at 1:00:25 PM UTC-4, Tom Breloff wrote:
>
> I think this discussion shows complementary definitions of traits:
>
>    - verb-based traits: a type agrees to implement all the verbs 
>    appropriate to the given "verb trait"
>    - noun-based traits: a type agrees to contain certain underlying data 
>    (and thus the getter/setter verbs could be implicitly defined for those 
>    fields)
>
> Whatever the final implementation of traits in Julia, I think keeping in 
> mind this distinction could be helpful.
>
> On Wed, Oct 21, 2015 at 12:42 PM, Stefan Karpinski <[email protected] 
> <javascript:>> wrote:
>
>> On Tue, Oct 20, 2015 at 7:00 PM, Brendan Tracey <[email protected] 
>> <javascript:>> wrote:
>>
>>>
>>> > 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".
>>>
>>> As Stefan mentioned, Go is not traditional OO. This "composition-based" 
>>> approach is part of Go's OO approach. In go, a type can have named fields 
>>> of different types (like most OO languages), but also has "embedding". For 
>>> example, if one declared
>>>
>>> type Unicycle struct {
>>>     Wheel
>>>     Frame
>>>     Seat
>>> }
>>>
>>> then you could access the individual fields directly. So, if "u' is of 
>>> type Unicycle, then you could access/set u.Cushiness directly. Similarly, 
>>> if the embedded types had methods, i.e. frame.Color(), they can be called 
>>> directly through unicycle, u.Color(). This is similar to, but distinct 
>>> from, inheritance (the difference is that the Unicycle type doesn't 
>>> actually have these fields, just the ability to call them easily, which is 
>>> significant because of interfaces). In the case of clashes, the program 
>>> must specify which is meant, so if both Seat and Frame had a Color() 
>>> method, the user would have to specify u.Frame.Color vs. u.Seat.Color. In 
>>> Go, this is handled by the compiler, and would need to be handled somewhere 
>>> in the Julia runtime/REPL. It's a very nice paradigm, but would have to be 
>>> made to fit within the broader Julia context.
>>>
>>
>> I do like this approach to composition/delegation, but it requires 
>> automatically adding a lot of methods to the delegator, i.e.  Unicycle in 
>> this example, from all of its components, which feels kind of nasty and 
>> dangerous, especially since we allow dynamic addition of methods 
>> after-the-fact. In other words, you might add a method to Wheel, Frame or 
>> Seat at any time, which would presumably then also apply to Unicycle 
>> objects, potentially with unexpected consequences. It would be nice if the 
>> delegation was more limited than that. Go doesn't have this problem since 
>> you can't dynamically add methods – everything is known at compile time.
>>
>
>

Reply via email to