dispatch on typealias-like thing

340 views
Skip to first unread message

Mauro

unread,
Feb 7, 2014, 9:45:21 AM2/7/14
to juli...@googlegroups.com
I think sometimes it would be nice to be able to dispatch on a
typealias-like thing, let's call it a typecopy. For example, I need an
array which behaves like an Array except for a few methods. Currently
(I think), I would need to wrap the Array in a new type which subtypes
AbstractArray:

type MyArr <: AbstractArray
val::Array
end

Then I'd need to newly define all methods which are (re-)defined for
concrete Array (array.jl has 1300 lines). Lot's of work and/or
metaprogramming. Wouldn't it be much easier if this was possible:

typecopy MyArr Array
+(ma::MyArr, ma::MyArr) = convert(super(ma), ma) + convert(super(ma), ma) + 5

If I recall correctly, subtyping of concrete types is not possible
because a type needs to keep its memory-footprint. But for typecopy
this would not be a problem because the size is identical, or would it?
Or are there other problems? Just a thought.

Mauro

Steven G. Johnson

unread,
Feb 7, 2014, 10:28:05 AM2/7/14
to juli...@googlegroups.com

Mauro

unread,
Feb 7, 2014, 12:21:51 PM2/7/14
to juli...@googlegroups.com
Thanks, that looks interesting. But still more cumbersome than just
typecopy-ing: one would have to list all the methods applicable to
the wrapped type.

On Fri, 2014-02-07 at 15:28, steve...@gmail.com wrote:
> See:
>
> https://github.com/JuliaLang/julia/pull/3292

Jeff Bezanson

unread,
Feb 7, 2014, 12:48:48 PM2/7/14
to juli...@googlegroups.com
With all the magical things julia does, you have to pay the piper at
some point :) Hence some things are difficult.

I believe the best we could do here is automatically copy all methods
naming Array, replacing Array with MyArr. There are two separate
issues: (1) type behavior: is MyArr a subtype of Array? (2) available
methods: what methods exist for MyArr?

For part (2) we can do absolutely anything. Part (1) is impossible; if
isa(x,Array) is true then x must behave like an Array and nothing
else.

convert(super(ma), ma) is always a no-op. Anything of type X is
already of type super(X). Instead for this we use `invoke`, which
performs dispatch differently, which is what you really want here
AFAICT.

Steven G. Johnson

unread,
Feb 7, 2014, 3:27:57 PM2/7/14
to juli...@googlegroups.com


On Friday, February 7, 2014 12:21:51 PM UTC-5, Mauro wrote:
Thanks, that looks interesting.  But still more cumbersome than just
typecopy-ing: one would have to list all the methods applicable to
the wrapped type.

No, because as I suggested in the issue, it would be possible to implement the macro using methodswith(WrappedType) in order to automatically get the list of methods.

Mauro

unread,
Feb 7, 2014, 4:37:17 PM2/7/14
to juli...@googlegroups.com
On Fri, 2014-02-07 at 17:48, jeff.b...@gmail.com wrote:
> With all the magical things julia does, you have to pay the piper at
> some point :) Hence some things are difficult.

Well, you have to pay the piper by having to answer all these questions
of newbies coming up with "clever" ideas ;-)

> I believe the best we could do here is automatically copy all methods
> naming Array, replacing Array with MyArr. There are two separate
> issues: (1) type behavior: is MyArr a subtype of Array? (2) available
> methods: what methods exist for MyArr?
>
> For part (2) we can do absolutely anything. Part (1) is impossible; if
> isa(x,Array) is true then x must behave like an Array and nothing
> else.

I see, if the second argument to `isa` is a concrete type then x must be
exactly of that type. If that is a hard requirement then there is
indeed no way around.

As I wrote, I was only aware of one argument against allowing subtypes
of concrete types, which had to do with memory layout. (Which would
be fine in this case) But it looks like there are other reasons too.

> convert(super(ma), ma) is always a no-op. Anything of type X is
> already of type super(X). Instead for this we use `invoke`, which
> performs dispatch differently, which is what you really want here
> AFAICT.

Yes, I didn't know of `invoke`.

Cheers!

Mauro

unread,
Feb 7, 2014, 4:44:57 PM2/7/14
to juli...@googlegroups.com
>> Thanks, that looks interesting. But still more cumbersome than just
>> typecopy-ing: one would have to list all the methods applicable to
>> the wrapped type.
>>
>
> No, because as I suggested in the issue, it would be possible to implement
> the macro using methodswith(WrappedType) in order to automatically get the
> list of methods.

I should read more carefully, sorry! And yes, that'd be awesome and
would take care of most (all?) of the hassle of making your own types
based on concrete types. But from the comments in the issue it sounds
like it may not be all straight sailing either...

Kevin Squire

unread,
Feb 7, 2014, 6:44:50 PM2/7/14
to juli...@googlegroups.com
One small problem with using methodswith(WrappedType) is that it would only allow redefinition of existing methods.   Any methods defined in the future using the wrapped type would still not work with the wrapper type.

Cheers,
   Kevin

Jameson Nash

unread,
Feb 7, 2014, 10:11:19 PM2/7/14
to juli...@googlegroups.com
I would like to point out that there are CS schools of thought that
extending concrete classes is just a bad idea, even if (when) it was
(is) easy to implement. The example I often like to use is the the
fragile-base-class problem (the isa-AbstractArray trouble many people
have encounted when they try to extend it is perhaps a classic example
of this). However, rather than try to rehash those arguments in an
email, I'll point you to a web link which makes those points in
sufficient detail for you to do your own research:
http://www.javaworld.com/article/2073649/core-java/why-extends-is-evil.html

Mauro

unread,
Feb 10, 2014, 6:53:24 AM2/10/14
to juli...@googlegroups.com
Thanks for that link, that was a good read. The discussion about
whether to allow fields in abstract types also moved in the direction of
not having fields and to instead rely on the interface:
https://github.com/JuliaLang/julia/issues/4935

Stefan Karpinski

unread,
Feb 10, 2014, 12:26:59 PM2/10/14
to Julia Dev
Good article, Jameson. In Julia, you're forced to use the interface approach, and one would typically call the abstract type something like AbstractStack and then provide various implementations. One big difference, however, is that unlike interfaces in Java, you can program to abstract types in Julia, so you can provide a default implementation of push_many that just calls push a bunch of times. This doesn't fall into the fragile base class trap because it only gets called if the concrete type doesn't have a custom implementation of push_many, and since each implementation is independent – instead of some inheriting from others – changing one won't break any others.
Reply all
Reply to author
Forward
0 new messages