假定你有一个命名元组
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