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?