August 30, 2017
On Monday, 28 August 2017 at 13:19:19 UTC, Jean-Louis Leroy wrote:
> On Thursday, 24 August 2017 at 23:50:21 UTC, data pulverizer wrote:
>> I find OOP-polymorphic types ultimately unsatisfying, but I don't know of anyway to write, compile and load a D script with new types and methods on the fly into the same session.
>
> That is why binding membership and polymorphism together is a historical wrong turn. CLOS had it right but the world followed the Simula/Smalltalk path because of a nice metaphor (objects sending messages to each other).
>
> My openmethods library allows you to add methods "from outside" and also supports dynamic loading: you can add new methods to existing classes and new classes to hierarchies that have methods. See the blog post that just came up.

Thanks, just read it. Looks like a useful package. As you said it is about being able to dispatch with polymorphism ... where implicit promotions occur or explicit polymorphism is required.

One thing that confused me was examples like this ...

@method
Matrix _plus(DiagonalMatrix a, DiagonalMatrix b)
{
  // just add the elements on diagonals
  // return a DiagonalMatrix
}

Which is marked as returning a DiagonalMatrix rather than a Matrix by polymorphism however the function is marked Matrix return type.

You mentioned Julia in your article, however for clarity I would point out that Julia doesn't have OOP-type polymorphism. There is no notion of being able to do something like:

Animal snoopy = new Dog();

It's dispatch method is more like compile-time over as discussed here https://github.com/dataPulverizer/dispatch-it-like-julia - but you can recompile 'online' which I guess is what they mean by "dynamic dispatch" - but there's no polymorphism. Type hierarchies are basically for dispatching methods with varying amounts of specificity which can be accomplished using templates and only explicitly defined type conversions from one concrete type to another are allowed.

August 30, 2017
On Wednesday, 30 August 2017 at 16:45:19 UTC, data pulverizer wrote:
> You mentioned Julia in your article, however for clarity I would point out that Julia doesn't have OOP-type polymorphism. There is no notion of being able to do something like:
>
> Animal snoopy = new Dog();

p.s. my bad, I was wrong about that! Turns out you can do something like this in Julia (apologies for the Julia code in a D forum):

abstract type Animal end
struct Dog <: Animal end
struct Cat <: Animal end

x = Array{Animal}(3)
x[1] = Cat(); x[2] = Dog(); x[3] = Cat();
x # returns
3-element Array{Animal,1}:
 Cat()
 Dog()
 Cat()

Which is polymorphism
August 30, 2017
On Wednesday, 30 August 2017 at 17:14:37 UTC, data pulverizer wrote:
> On Wednesday, 30 August 2017 at 16:45:19 UTC, data pulverizer wrote:
>> You mentioned Julia in your article, however for clarity I would point out that Julia doesn't have OOP-type polymorphism. There is no notion of being able to do something like:
>>
>> Animal snoopy = new Dog();
>
> p.s. my bad, I was wrong about that! Turns out you can do something like this in Julia (apologies for the Julia code in a D forum):
>
> abstract type Animal end
> struct Dog <: Animal end
> struct Cat <: Animal end
>
> x = Array{Animal}(3)
> x[1] = Cat(); x[2] = Dog(); x[3] = Cat();
> x # returns
> 3-element Array{Animal,1}:
>  Cat()
>  Dog()
>  Cat()

p.p.s

typeof(x[1]) # returns Cat

so it isn't really polymorphism - the object is never converted to the "parent" type! Lol ... sorry for the confusion!
> Which is polymorphism


August 30, 2017
On Wednesday, 30 August 2017 at 16:45:19 UTC, data pulverizer wrote:
> One thing that confused me was examples like this ...
>
> @method
> Matrix _plus(DiagonalMatrix a, DiagonalMatrix b)
> {
>   // just add the elements on diagonals
>   // return a DiagonalMatrix
> }
>
> Which is marked as returning a DiagonalMatrix rather than a Matrix by polymorphism however the function is marked Matrix return type.

Indeed returning a DiagonalMatrix would work, and is marginally more useful (in case you want to call the specialization directly). I'll update the example. Thanks.

August 30, 2017
On Wednesday, 30 August 2017 at 17:16:59 UTC, data pulverizer wrote:
>
> p.p.s
>
> typeof(x[1]) # returns Cat
>
> so it isn't really polymorphism - the object is never converted to the "parent" type! Lol ... sorry for the confusion!
>> Which is polymorphism

Haha what I know of Julia is what wikipedia says. Confusing indeed...
August 30, 2017
On Wednesday, 30 August 2017 at 17:29:42 UTC, Jean-Louis Leroy wrote:
> On Wednesday, 30 August 2017 at 17:16:59 UTC, data pulverizer wrote:
>>
>> p.p.s
>>
>> typeof(x[1]) # returns Cat
>>
>> so it isn't really polymorphism - the object is never converted to the "parent" type! Lol ... sorry for the confusion!
>
> Haha what I know of Julia is what wikipedia says. Confusing indeed...

To be fair they say it is parametric polymorphism - dispatching basically template style, rather than subtyping polymorphism (OOP type), (more wikipedia https://en.wikipedia.org/wiki/Polymorphism_(computer_science)).

The reason I have never really been comfortable with sub-typing is that the polymorphic types are a black-box, my preference is certainly for parametric type polymorphism. The main disadvantage with parametric polymorphism in compiled languages is that array containers only operate under subtyping polymorphism. In the above Julia example the array container is essentially acting exactly like a compile-time dispatch (overloaded) function - the array is dispatching on a specific set of types defined by the abstract parent type. That kind of construct would be very desirable to me in D. The closest such thing you can have to that in D are tuples.
August 30, 2017
On Wednesday, 30 August 2017 at 17:57:49 UTC, data pulverizer wrote:
> The reason I have never really been comfortable with sub-typing is that the polymorphic types are a black-box, my preference is certainly for parametric type polymorphism. The main disadvantage with parametric polymorphism in compiled languages is that array containers only operate under subtyping polymorphism. In the above Julia example the array container is essentially acting exactly like a compile-time dispatch (overloaded) function - the array is dispatching on a specific set of types defined by the abstract parent type. That kind of construct would be very desirable to me in D. The closest such thing you can have to that in D are tuples.

I suspect the reason you can't have parametric typed array containers in statically typed compiled languages is that underneath, they are doubly/linked lists, and there is no way of resolving the types at the end of the array, and allowing appending at the same time ... someone correct me if I am wrong.

August 30, 2017
On Wednesday, 30 August 2017 at 18:48:58 UTC, data pulverizer wrote:
> I suspect the reason you can't have parametric typed array containers in statically typed compiled languages is that underneath, they are doubly/linked lists, and there is no way of resolving the types at the end of the array, and allowing appending at the same time ... someone correct me if I am wrong.

The only other way would be to create a wrapper interface and classes for each type you want to include in the array, which takes you back to sub-type (OOP) polymorphism.
August 30, 2017
On Wednesday, 30 August 2017 at 17:16:59 UTC, data pulverizer wrote:
> On Wednesday, 30 August 2017 at 17:14:37 UTC, data pulverizer wrote:
>> On Wednesday, 30 August 2017 at 16:45:19 UTC, data pulverizer wrote:
>>> You mentioned Julia in your article, however for clarity I would point out that Julia doesn't have OOP-type polymorphism. There is no notion of being able to do something like:
>>>
>>> Animal snoopy = new Dog();
>>
>> p.s. my bad, I was wrong about that! Turns out you can do something like this in Julia (apologies for the Julia code in a D forum):
>>
>> abstract type Animal end
>> struct Dog <: Animal end
>> struct Cat <: Animal end
>>
>> x = Array{Animal}(3)
>> x[1] = Cat(); x[2] = Dog(); x[3] = Cat();
>> x # returns
>> 3-element Array{Animal,1}:
>>  Cat()
>>  Dog()
>>  Cat()
>
> p.p.s
>
> typeof(x[1]) # returns Cat
>
> so it isn't really polymorphism - the object is never converted to the "parent" type! Lol ... sorry for the confusion!
>> Which is polymorphism

After mulling over this example, I don't see how this proves that Julia does *not* support run time polymorphism. On the contrary. If you translate this to D you get the same result by the way:

import std.stdio;

class Animal {}
class Cat : Animal {}

void main()
{
  Animal[] array;
  array ~= new Cat();
  writeln(typeid(array[0])); // typeid.Cat
}

August 30, 2017
On Wednesday, 30 August 2017 at 20:40:38 UTC, Jean-Louis Leroy wrote:
>
> After mulling over this example, I don't see how this proves that Julia does *not* support run time polymorphism. On the contrary. If you translate this to D you get the same result by the way:
>
> import std.stdio;
>
> class Animal {}
> class Cat : Animal {}
>
> void main()
> {
>   Animal[] array;
>   array ~= new Cat();
>   writeln(typeid(array[0])); // typeid.Cat
> }

writeln(typeof(array[0]).stringof); // this is an Animal

The return type of any item in the array would be of type Animal. You would have to do a type cast to really get type Cat.

In Julia there is no real notion that any item in Array{Animal, 1} is an Animal. Their types are never masked by Animal, which only really serves as a way of dispatching types to the array, unlike in D where the actual type is Animal. However if your multi-methods is dispatching methods using typeid (which I am guessing is the case) this distinction no longer matters.

It may be better to say that typeof() in Julia is a run-time type and there is no notion of typeof() as in D.

In the light of this I think your package just became more interesting to me.