Apparently, it was deemed worthwhile to implement hcat and vcat for numeric
and generic objects, but not cat. Is there a particular reason why?
Here is a prototype of what I have in mind for numbers:
function cat{T<:Number}( d::Integer, X::T... )
d <= 0 && throw(BoundsError())
X = T[ X... ]
d == 1 ? X : reshape( X, ones(Int,d-1)..., length(X) )
end
function cat( d::Integer, X::Number... )
d <= 0 && throw(BoundsError())
X = promote_type( map(typeof,X)... )[ X... ]
d == 1 ? X : reshape( X, ones(Int,d-1)..., length(X) )
end
Please forgive any style *faux pas, *though please correct me as well!
I know that hcat and vcat are more common, but it doesn't seem that
difficult to be a completist here...
A few other notes when studying promotion.jl and abstractarray.jl:
- hcat and vcat have separate implementations for the fully generic case
and the numeric case, even though the implementations are identical. For
example:
vcat{T}(X::T...) = T[ X[i] for i=1:length(X) ]
vcat{T<:Number}(X::T...) = T[ X[i] for i=1:length(X) ]
Is there a reason for this? Obviously, if there is a good one, the cat
function above can be done in the same way.
-
For the generic Number... implementations, hcat and vcat use the
following code to determine the promoted type:
T = None
for x in X
T = promote_type(T,typeof(x))
end
Is there a reason to prefer this to a single-line implementation
promote_type(
map(typeof,X)... )?
-
On a related note, the promote_typeof function looks awfully useful. It
would be nice to see it exported and documented.
-
Finally: can we trust Julia to evaluate promote_typeof just once here?
This is right from promotion.jl:
Thanks for your time.
Michael