julia - MutableNamedTuples - 可变命名元组的实现

假定你有一个命名元组
mytuple = (a = 1,b=2)

你可以读取 a 和 b的值,但是你不能修改 a和b的值

如果你想要修改a和b的值,如何实现呢?

关键点:利用Ref() 就是用引用

【一】github网址

链接:https://github.com/MasonProtter/MutableNamedTuples.jl

【二】简要介绍

MutableNamedTuples.jl

Sometimes you want a named tuple, but mutable. This works by wrapping a named tuple where all the elements are mutable Ref s and then pretending that it’s elements are that contents of the Ref s instead.

julia> using MutableNamedTuples

julia> mnt = MutableNamedTuple(a=1, b= 2)
MutableNamedTuple(a = 1, b = 2)

julia> mnt.a = 2
2

julia> mnt
MutableNamedTuple(a = 2, b = 2)
julia> const MNT = MutableNamedTuple
MutableNamedTuple

julia> A = [MNT(a = 1, b=2) MNT(a=3, b=6)
            MNT(a =-1, b=4) MNT(a=1, b=1)]
2×2 Array{MutableNamedTuple{(:a, :b),Tuple{Base.RefValue{Int64},Base.RefValue{Int64}}},2}:
 MutableNamedTuple(a = 1, b = 2)   MutableNamedTuple(a = 3, b = 6)
 MutableNamedTuple(a = -1, b = 4)  MutableNamedTuple(a = 1, b = 1)

julia> A[1, 1].a = 100
100

julia> A
2×2 Array{MutableNamedTuple{(:a, :b),Tuple{Base.RefValue{Int64},Base.RefValue{Int64}}},2}:
 MutableNamedTuple(a = 100, b = 2)  MutableNamedTuple(a = 3, b = 6)
 MutableNamedTuple(a = -1, b = 4)   MutableNamedTuple(a = 1, b = 1)   

【三】关键源码

module MutableNamedTuples

export MutableNamedTuple

struct MutableNamedTuple{N,T <: Tuple{Vararg{<:Ref}}}
    nt::NamedTuple{N, T}
end

MutableNamedTuple(;kwargs...) = MutableNamedTuple(NamedTuple{keys(kwargs.data)}(Ref.(values(kwargs.data))))

function MutableNamedTuple{names}(tuple::Tuple) where names
    MutableNamedTuple(NamedTuple{names}(Ref.(tuple)))
end

Base.keys(::MutableNamedTuple{names}) where {names} = names 
Base.values(mnt::MutableNamedTuple) = getindex.(values(getfield(mnt, :nt)))
refvalues(mnt::MutableNamedTuple) = values(getfield(mnt, :nt))

Base.NamedTuple(mnt::MutableNamedTuple) = NamedTuple{keys(mnt)}(values(mnt))
Base.Tuple(mnt::MutableNamedTuple) = values(mnt)


function Base.show(io::IO, mnt::MutableNamedTuple{names}) where {names}
    print(io, "MutableNamedTuple", NamedTuple(mnt))
end

Base.getproperty(mnt::MutableNamedTuple, s::Symbol) = getproperty(NamedTuple(mnt), s)

function Base.setproperty!(mnt::MutableNamedTuple, s::Symbol, x)
    i = findfirst(x -> x === s, keys(mnt))
    refvalues(mnt)[i][] = x
end

Base.length(mnt::MutableNamedTuple) = length(getfield(mnt, :nt))
Base.iterate(mnt::MutableNamedTuple, iter=1) = iterate(NamedTuple(mnt), iter)
Base.firstindex(mnt::MutableNamedTuple) = 1
Base.lastindex(mnt::MutableNamedTuple) = lastindex(NamedTuple(mnt))
Base.getindex(mnt::MutableNamedTuple, i::Int) = getfield(NamedTuple(mnt), i)
Base.getindex(mnt::MutableNamedTuple, i::Symbol) = getfield(NamedTuple(mnt), i)
function Base.indexed_iterate(mnt::MutableNamedTuple, i::Int, state=1) 
    Base.indexed_iterate(NamedTuple(mnt), i, state) 
end

end # module

你可能感兴趣的:(julia - MutableNamedTuples - 可变命名元组的实现)