The Julia manual uses a type ArrayAndChar
as its example of how to customise broadcasting.
Following a suggestion from @mcabbott, I’m implementing this for real. I’m running into a bunch of complications that the manual doesn’t discuss, and I was hoping someone could point me to a fully implemented array subtype that is similar to this example.
My type is actually ArrayAndTensorShape
instead of ArrayAndChar
, but that is a minor detail.
I have found two major complications so far.
Firstly, a function might be broadcast over multiple ArrayAndChar
arguments. Suppose I want to do the obvious thing if the chars are the same, and throw an error if they differ. Should I tinker with the rather brittle find_aac
function in the manual, or is there a neater and more reliable way that puts the char into a special subtype of BroadcastStyle
and specializes the two-argument BroadcastStyle
constructor?
Secondly, view types. Let’s say I have a method
return_char(A::ArrayAndChar) = A.char
I want things like return_char(Diagonal(A))
and return_char(reshape(A', ...))
to work, even though the view types might be nested arbitrarily deeply. I can see two ways of doing this.
The first way is a kludge:
const ChildArray =
let
Ts = [m.sig.parameters[2] for m in methods(parent)]
filter!(T -> T != AbstractArray, Ts)
Union{Ts...}
end
return_char(A::ChildArray) = return_char(parent(A))
That solves the immediate problem, but what about A .+ B'
where A
and B
are ArrayAndChar
?
The second way puts the view type on the inside, along the lines of
for T = [m.sig.parameters[2] for m in methods(parent)]
@eval ($T)(A::ArrayAndChar, args...) =
ArrayAndChar($T(A.data, args...), A.char)
end
That seems like a total hack, whose compatibility with the Julia interpreter would have to be very carefully managed. Also, how will A*B
know to use the customized method *(::Diagonal, ::Diagonal)
when A.data
and B.data
are Diagonal
?