I’ve always hated reduce(hcat,...)
. It’s unusual to specialize higher-order functions on specific other functions except when the higher-order function has a more commonly used alias (like sum
is implemented in terms of reduce(add_sum,...)
).
It’s rather undiscoverable, since knowledge of reduce
’s typical binary reduction would normally suggest that reduce(hcat,...)
is an awful way to do this. Also, the specializations only cover
julia> methods(reduce)
# 6 methods for generic function "reduce" from Base:
[1] reduce(::typeof(merge), items::Vector{<:Dict})
@ dict.jl:747
[2] reduce(::typeof(hcat), A::AbstractVector{<:AbstractVecOrMat})
@ abstractarray.jl:1721
[3] reduce(::typeof(vcat), A::AbstractVector{<:AbstractVecOrMat})
@ abstractarray.jl:1718
...
which misses a lot of (less common) cases and also any use with mapreduce
or a composed version of these functions. I would prefer a collection-oriented analog of cat
(like max
has maximum
) that operates on a collection rather than vararg, although there hasn’t been a lot of enthusiasm for this in the past. At least stack
covers a decent fraction of those cases now.
I suppose my suggestion (assuming the reduce
specializations don’t cover your needs) might be stack
into reshape
. The bummer is that this is the sort of tomfoolery I thought I left behind with MATLAB. It’s probably performant, at least.
julia> reshape(stack([reshape(1:8,2,2,2) for _ in 1:3]; dims=2), 2, :, 2)
2×6×2 Array{Int64, 3}:
[:, :, 1] =
1 1 1 3 3 3
2 2 2 4 4 4
[:, :, 2] =
5 5 5 7 7 7
6 6 6 8 8 8
This would probably look nicer if you made an explicit flattendim
function to compute the reshape for you:
"""
flattendim(x::AbstractArray; dim::Int)
Use `reshape` on `x` to combine dimensions `dim` and `dim`+1.
"""
function flattendim(x::AbstractArray{<:Any,D}; dim::Int) where D
1 <= dim <= D-1 || throw(ArgumentError(lazy"Cannot combine dimensions $(dim:dim+1) in $D-dimensional array"))
newsize = ntuple(Val{D-1}()) do d
d < dim ? size(x,d) : d == dim ? size(x,d)*size(x,d+1) : size(x,d+1)
end
return reshape(x, newsize)
end