类似的东西
struct MyStruct
x
y
z
end
x = MyStruct(1, 2, 3)
a, b, c = ntuple(i -> getfield(x, fieldnames(MyStruct)[i]), length(fieldnames(MyStruct)))
但是我忍不住想我只是在重新发明轮子。
答案 0 :(得分:0)
除了现有的答案,还有两种选择:ntuple
和生成的函数。基线是手动编写代码(可以由宏生成)。
ntuple
通常会生成更好的代码,在这种情况下速度要快 20 倍以上。
struct Foo{A, B}
a::A
b::B
end
dump0(x) = getfield.(Ref(x), fieldnames(typeof(x)))
dump1(x) = ntuple(i -> getfield(x, i), fieldcount(typeof(x)))
# Based off https://discourse.julialang.org/t/slowness-of-fieldnames-and-propertynames/55364/2
@generated function dump2(obj::T) where {T}
return :((tuple($((
:(getfield(obj, $i)) for i in 1:fieldcount(obj)
)...))))
end
# hardcoded
dump3(x::Foo) = (x.a, x.b)
@code_llvm dump3(Foo(1,2))
和 @code_llvm dump2(Foo(1,2))
相同,而 @code_llvm dump1(Foo(1,2))
和 @code_llvm dump0(Foo(1,2))
复杂得多。
要获取时间,请定义
eq0(a, b) = ==(dump0(a), dump0(b))
eq1(a, b) = ==(dump1(a), dump1(b))
eq2(a, b) = ==(dump2(a), dump2(b))
eq3(a, b) = ==(dump3(a), dump3(b))
(对于 Foo
和 missing
,这些相等函数的行为将与 NaN
上定义的默认值不同。转储到元组的另一个动机是定义例如 {{1} }
我无法找到显示 hash(x::Foo, s::UInt) = hash(dump(x), hash(Foo, s))
和 dump1
之间显着差异的性能基准,尽管为 dump2
生成的代码似乎更高效。 dump2
慢得多:
dump0