命名元组的 Setindex
Setindex for named tuple
我正在尝试为命名元组编写一个非变异 setindex
,其中给定名称 var
的值类型,它会在 x.var = y
处创建一个新的命名元组。我现在拥有的是:
function setindex(nt::T,x,v::Val{var}) where {T,var}
if var ∉ fieldnames(T)
return x
else
typeof(x)(s == var ? y : w for (s,w) in nt)
end
end
但我的主要问题是我不确定迭代命名元组以获得 (name,value)
对的好方法。
您可以使用 pairs
为键值对提供迭代器,或者使用类型为 T
的 fieldnames
并使用 nt[name]
或(使用keys
与命名的元组变量以相同的方式)。我想你更喜欢 pairs
.
function setindex(nt::T,y,v::Val{var}) where {T,var}
if var ∉ fieldnames(T)
return nt
else
T(s == var ? y : w for (s,w) in pairs(nt))
end
end
或
function setindex(nt::T,y,v::Val{var}) where {T,var}
if var ∉ fieldnames(T)
return nt
else
T(k == var ? y : nt[k] for k in fieldnames(T))
end
end
这是@generated
版本。生成的代码非常简单并且类型稳定。
julia> @generated function setindex(x::NamedTuple,y,v::Val)
k = first(v.parameters)
k ∉ x.names ? :x : :( (x..., $k=y) )
end
julia> @code_warntype setindex((a=2, b=3), 4, Val(:b))
Body::NamedTuple{(:a, :b),Tuple{Int64,Int64}}
2 1 ─ %1 = (Base.getfield)(x, :a)::Int64 │╻╷╷ macro expansion
│ %2 = %new(NamedTuple{(:a, :b),Tuple{Int64,Int64}}, %1, y)::NamedTuple{(:a, :b),Tuple{Int64,Int64}}│┃││╷ merge
└── return %2 ││
julia> @code_warntype setindex((a=2, b=3), 4, Val(:c))
Body::NamedTuple{(:a, :b),Tuple{Int64,Int64}}
2 1 ─ return x
我正在尝试为命名元组编写一个非变异 setindex
,其中给定名称 var
的值类型,它会在 x.var = y
处创建一个新的命名元组。我现在拥有的是:
function setindex(nt::T,x,v::Val{var}) where {T,var}
if var ∉ fieldnames(T)
return x
else
typeof(x)(s == var ? y : w for (s,w) in nt)
end
end
但我的主要问题是我不确定迭代命名元组以获得 (name,value)
对的好方法。
您可以使用 pairs
为键值对提供迭代器,或者使用类型为 T
的 fieldnames
并使用 nt[name]
或(使用keys
与命名的元组变量以相同的方式)。我想你更喜欢 pairs
.
function setindex(nt::T,y,v::Val{var}) where {T,var}
if var ∉ fieldnames(T)
return nt
else
T(s == var ? y : w for (s,w) in pairs(nt))
end
end
或
function setindex(nt::T,y,v::Val{var}) where {T,var}
if var ∉ fieldnames(T)
return nt
else
T(k == var ? y : nt[k] for k in fieldnames(T))
end
end
这是@generated
版本。生成的代码非常简单并且类型稳定。
julia> @generated function setindex(x::NamedTuple,y,v::Val)
k = first(v.parameters)
k ∉ x.names ? :x : :( (x..., $k=y) )
end
julia> @code_warntype setindex((a=2, b=3), 4, Val(:b))
Body::NamedTuple{(:a, :b),Tuple{Int64,Int64}}
2 1 ─ %1 = (Base.getfield)(x, :a)::Int64 │╻╷╷ macro expansion
│ %2 = %new(NamedTuple{(:a, :b),Tuple{Int64,Int64}}, %1, y)::NamedTuple{(:a, :b),Tuple{Int64,Int64}}│┃││╷ merge
└── return %2 ││
julia> @code_warntype setindex((a=2, b=3), 4, Val(:c))
Body::NamedTuple{(:a, :b),Tuple{Int64,Int64}}
2 1 ─ return x