[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

Reply via email to