返回一个在 Julia 中更改了字段的新结构
Returning a new structure with fields changed in Julia
我在尝试创建一个结构时遇到了这个问题,该结构是更改了特定字段的现有结构的新副本。我知道大概可以通过元编程来实现。但是,这是正确的方法还是我会重新发明轮子?
例如:
struct A
a
b
end
var = A(1,2)
var.b = 4 # This means var = A(1,4)
我不确定是否已经有类似的或更好的实现,但这有效并且不依赖于任何元编程:
struct A
a
b
end
var = A(1,2)
function reinstantiate(old, pairs::Pair...)
T = typeof(old)
field_values = [getfield(old, field) for field in fieldnames(T)]
for pair in pairs
index = findfirst(fieldnames(T) .== pair.first)
@assert index != nothing "$(pair.first) is not a field of $(T)"
field_values[index] = pair.second
end
return T(field_values...)
end
var2 = reinstantiate(var, :a=>3, :b=>4)
我通常使用 Base.@kwdef
定义 struct
,然后定义一个外部构造函数,如
Base.@kwdef struct A
a
b
end
Base.convert( ::Type{NamedTuple}, a::A ) = NamedTuple{propertynames(a)}(a)
function A( a::A; kwargs... )
nt = convert(NamedTuple, a)
nt = merge( nt, kwargs.data )
return A(;nt...)
end
然后你可以做
var = A(1, 2)
var2 = A(var, b = 4)
您还可以定义 setindex!
以获取您在 OP 中的语法,但那样一次只能更改一个字段。
更新:检查Accessors.jl,继任者:
Setfield.jl 就是一个可以做到这一点的软件包。
我在尝试创建一个结构时遇到了这个问题,该结构是更改了特定字段的现有结构的新副本。我知道大概可以通过元编程来实现。但是,这是正确的方法还是我会重新发明轮子?
例如:
struct A
a
b
end
var = A(1,2)
var.b = 4 # This means var = A(1,4)
我不确定是否已经有类似的或更好的实现,但这有效并且不依赖于任何元编程:
struct A
a
b
end
var = A(1,2)
function reinstantiate(old, pairs::Pair...)
T = typeof(old)
field_values = [getfield(old, field) for field in fieldnames(T)]
for pair in pairs
index = findfirst(fieldnames(T) .== pair.first)
@assert index != nothing "$(pair.first) is not a field of $(T)"
field_values[index] = pair.second
end
return T(field_values...)
end
var2 = reinstantiate(var, :a=>3, :b=>4)
我通常使用 Base.@kwdef
定义 struct
,然后定义一个外部构造函数,如
Base.@kwdef struct A
a
b
end
Base.convert( ::Type{NamedTuple}, a::A ) = NamedTuple{propertynames(a)}(a)
function A( a::A; kwargs... )
nt = convert(NamedTuple, a)
nt = merge( nt, kwargs.data )
return A(;nt...)
end
然后你可以做
var = A(1, 2)
var2 = A(var, b = 4)
您还可以定义 setindex!
以获取您在 OP 中的语法,但那样一次只能更改一个字段。
更新:检查Accessors.jl,继任者:
Setfield.jl 就是一个可以做到这一点的软件包。