使用符号作为访问器的正确方法

时间:2019-05-26 00:58:10

标签: julia

包装矩阵和使用符号访问的正确方法是什么?

S = OhlcSeries{Float64}(100)
lastClose = S[:close, 0]

struct OhlcSeries{T} <: AbstractArray{T,2}
    data::Matrix{T}

    function OhlcSeries{T}(length::Int) where T
        data = Matrix{T}(4, length)
        new{T}(data)
    end
end

# Base.parent(A::OhlcSeries) = A.data
getindex(s::OhlcSeries,sym::Symbol) = getindex(s,Val{sym})
getindex(s::OhlcSeries,::Type{Val{:close}}) = view(s.data, 4, :)

# @inline function getindex(S::InputOhlcSeries, r::Symbol, col::Int)
#     @match r begin
#         :open => S.data[1, col]
#         :high => S.data[2, col]
#         :low  => S.data[3, col]
#         :close  => S.data[4, col]
#         _      => throw(ArgumentError("Expected one of :open, :high, :low, :close"))
#     end
# end

@inline function setindex!(S::InputOhlcSeries, value, r::Symbol, col::Int)
    @match r begin
        :open => S.data[1, col] = value
        :high => S.data[2, col] = value
        :low  => S.data[3, col] = value
        :close  => S.data[4, col] = value
        _      => throw(ArgumentError("Expected one of :open, :high, :low, :close"))
    end
end

@inline Base.getindex(S::OhlcSeries, i::Int, j::Int) = S.data[i, j]
@inline Base.setindex!(S::OhlcSeries, value, i::Int, j::Int) = S.data[i, j] = value
Base.size(S::OhlcSeries) = size(S.data.data)
Base.eltype(::Type{OhlcSeries{T}}) where {T} = T
Base.IndexStyle(::Type{<:OhlcSeries}) = IndexCartesian()

1 个答案:

答案 0 :(得分:1)

如果希望您的类型是AbstratArray的子类型,则应最少实现https://docs.julialang.org/en/latest/manual/interfaces/#man-interface-array-1 API规范中指定的方法。特别是,您应该决定使用IndexStyle(查看您的结构IndexLinear应该是有效的)。

然后,您可以在其之上添加自定义索引。如何完成此操作的示例最好在https://github.com/JuliaArrays/AxisArrays.jl软件包或https://github.com/davidavdav/NamedArrays.jl中查找。我会向您介绍源代码,因为代码可能会很棘手,因此最好对其进行全面检查。

如果您不想允许仅通过符号而不是数字来索引数据结构的列,那么这也是完全可行的,但是此类型将不支持AbstractArray API,因此如果将其传递给标准假定该API已实现的库函数,您会出错。