[This is a continuation/update on a previous question, but with new
problem... click this link
<https://groups.google.com/d/msg/julia-users/icTP-l-odtw/grlc4pyXWZoJ> to
see the original post.]
To briefly review, I have an abstract matrix class that is derived from
Base.AbstractArray{Scalar{T},N}, where Scalar{T<:Number} is an object of my
own design. The array is truly abstract: it is *not *a contiguous/dense
array of Scalars. In fact, the storage format resembles a compressed sparse
matrix, except that each column represents a Scalar. Because of this
compressed storage format, the default implementations of cat/vcat/hcat are
quite
suboptimal, so I need to override them.
Now, this is not a problem, if I define methods that take *only *my
arrays. Unfortunately, I need to be able to accept arbitrary mixtures of *my
*arrays and standard numeric AbstractArrays. What I need is a way to
override, say, vcat in such a way that my methods are called when *at least
one *of the arguments is mine. With the help of Miles Lubin, I've been
experimenting with invoke; for instance:
# vcat{T}(V::AbstractVector{T}...) (abstractarray.jl:541)
vcat{T}( X::Union(Base.AbstractVector{T},CVX.AbstractVector{T})... ) =
any(iscvx,X) ? cat_cvxa( 1, X ) :
invoke( vcat, (Base.AbstractVector{T}...), X... )
The any(iscvx,X) test returns true if at least one of the arguments is an
object of mine, and false otherwise. In this way, the standard
Base.AbstractVector version of the method can be called if none of my
objects are present.
Astute readers already know the problem. In theory, Union(Base.
AbstractVector{T},CVX.AbstractVector{T}) is actually just the same as Base.
AbstractVector{T}, since my arrays are derived from the base abstract
array. So there's an ambiguity here; a potential for a stack overflow, too.
The funny thing is: *sometimes this works exactly the way I want it to! *That
is, if I feed vcat a mix of array types, this is the function that is
called. But then, I've rearranged my code a bit more, and now it *never *calls
this modified form of the function. What has *never* happened, at least not
yet, is a infinite loop/stack overflow. But nor has there ever been a *warning
*about the potential ambiguity.
What I'm really looking for, I suppose, is a way to *override *the previous
definition of this method, but somehow be able to invoke the overridden
version if my test demands it.
Honestly, I think part of the problem is that Base.AbstractArray is not
taking its status as an abstract class seriously. Many of the
implementations of vcat, hcat, cat, and other functions assume a storage
format and proceed as if they know best how *every *possible subclass would
want to handle heterogenous sets of arrays. Honestly, I think that most of
the implementations in abstractarray.jl ought to be relegated to the Array
class; let ever concrete class determine for itself how to efficiently
navigate its storage when concatenating matrices. Alas, I think that
attempting to do that would run into some of the very problems I'm facing
here.
Any suggestions would be welcome! The one thing I am considering that I
know would work is to remove Base.AbstractArray as as subclass of mine.
Then the Union above would no longer be trivial, and there would be no
ambiguities to deal with. Unfortunately, that would mean I'd have to
reimplement a lot of the convenience functions that *do *work well in
abstractarray.jl and elsewhere; including, for instance, showarray.
Thanks for listening
Michael