Правильный способ использовать символы в качестве аксессоров - PullRequest
1 голос
/ 26 мая 2019

Как правильно обернуть матрицу и получить доступ с помощью символов?

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 Ответ

1 голос
/ 27 мая 2019

Если вы хотите, чтобы ваш тип был подтипом 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 выполнен, вы можете получить ошибки.

...