Julia中是否有一个函数可以将类型的字段值转储到元组中?

时间:2019-07-24 14:37:34

标签: types julia

类似的东西

struct MyStruct
    x
    y
    z
end

x = MyStruct(1, 2, 3)

a, b, c = ntuple(i -> getfield(x, fieldnames(MyStruct)[i]), length(fieldnames(MyStruct)))

但是我忍不住想我只是在重新发明轮子。

1 个答案:

答案 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))

(对于 Foomissing,这些相等函数的行为将与 NaN 上定义的默认值不同。转储到元组的另一个动机是定义例如 {{1} }

我无法找到显示 hash(x::Foo, s::UInt) = hash(dump(x), hash(Foo, s))dump1 之间显着差异的性能基准,尽管为 dump2 生成的代码似乎更高效。 dump2 慢得多:

dump0