很难抽象地谈论这个。这是一个具体的例子:
struct ReversedRowMajor{T,A} <: AbstractMatrix{T}
data::A
end
ReversedRowMajor(data::AbstractMatrix{T}) where {T} = ReversedRowMajor{T, typeof(data)}(data)
Base.size(R::ReversedRowMajor) = reverse(size(R.data))
Base.getindex(R::ReversedRowMajor, i::Int, j::Int) = R.data[end-j+1, end-i+1]
这个简单的数组访问父数组,它的索引被置换(主要是行)和转换(被反转)。请注意,此数组自动支持所有预期的索引形式:
julia> R = ReversedRowMajor([1 2; 3 4; 5 6])
2×3 ReversedRowMajor{Int64,Array{Int64,2}}:
6 4 2
5 3 1
julia> R[:, isodd.(R[1,:].÷2)]
2×2 Array{Int64,2}:
6 2
5 1
julia> @view R[[1,4,5]]
3-element view(reshape(::ReversedRowMajor{Int64,Array{Int64,2}}, 6), [1, 4, 5]) with eltype Int64:
6
3
2
请注意,我们不会使用置换和计算的索引重新索引到 R — 新索引直接提供给父数组 R.data。
现在,另一方面,to_indices 将以前不受支持的索引 types 简单转换为 Int 或 Int 数组,然后重新索引到 R 本身与那些转换的索引。注意当你调用R[Int8(1),Int8(1)]时会发生什么:
julia> @which R[Int8(1),Int8(1)]
getindex(A::AbstractArray, I...) in Base at abstractarray.jl:925
这并没有调用你定义的任何方法——还没有。你没有定义如何getindex(::ReversedRowMajor, ::Int8, ::Int8)。所以朱莉娅正在为你处理这个案子。它使用to_indices 将Int8 转换为Int,然后再次调用R[1,1]。现在它达到了您定义的方法。
简而言之:这个数组有一个简单的getindex 方法,带有Int 索引,可以重新计算对父数组的访问。另一方面,to_indices 在您未定义匹配方法的情况下将所有其他类型的索引转换为支持的索引到同一个数组。您根本无法使用 to_indices 进行您想要的转换,因为不清楚 R[1, 2] 是使用转换前的索引还是转换后的索引。