请参阅没有点表示法的结构字段(在Julia中)

Sim*_*ods 2 julia

在Julia我已经定义了一个类型,我需要编写一些与该类型的字段一起使用的函数.某些函数包含复杂的公式,并且在整个地方使用字段访问点表示法会变得混乱.所以我最终将字段值放入局部变量中以提高可读性.它工作正常,但有一些聪明的办法,以避免键入了所有的a=foo.a线或有朱莉娅解析afoo.a等?

struct Foo
    a::Real
    b::Real
    c::Real
end

# this gets hard to read
function bar(foo::Foo)
    foo.a + foo.b + foo.c + foo.a*foo.b - foo.b*foo.c
end

# this is better
function bar(foo::Foo)
    a = foo.a
    b = foo.b
    c = foo.c
    a + b + c + a*b - b*c
end

# this would be great
function bar(foo::Foo)
    something clever
    a + b + c + a*b - b*c
end
Run Code Online (Sandbox Code Playgroud)

Har*_*din 6

因为Julia通常鼓励使用通用接口与字段交互而不是直接访问字段,所以实现此目的的一种相当自然的方法是通过迭代解包.在Julia中,可以通过迭代将对象"解包"为多个变量:

julia> x, y = [1, 2, 3]
3-element Array{Int64,1}:
 1
 2
 3

julia> x
1

julia> y
2
Run Code Online (Sandbox Code Playgroud)

我们可以为自定义对象实现这样的迭代协议,比如Foo.在v0.7中,这看起来像:

Base.iterate(foo::Foo, state = 1) = state > 3 ? nothing : (getfield(foo, state), state + 1)
Run Code Online (Sandbox Code Playgroud)

请注意,3是硬编码的(基于字段数Foo),可以替换为fieldcount(Foo).现在,您可以简单地"解压缩"一个实例,Foo如下所示:

julia> a, b, c = Foo("one", 2.0, 3)
Foo("one", 2.0, 3)

julia> a
"one"

julia> b
2.0

julia> c
3
Run Code Online (Sandbox Code Playgroud)

这可能是你功能开始时"聪明的东西".此外,从v0.7开始,您可以在函数参数本身中解压缩字段:

function bar((a, b, c)::Foo)
    a + b + c + a*b - b*c
end
Run Code Online (Sandbox Code Playgroud)

虽然这确实需要您再次提及字段名称,但它具有两个潜在优势:

  1. 如果您struct被重构并且字段被重命名,则访问字段的所有代码将保持不变(只要字段顺序不改变或iterate实现被更改以反映新对象内部).
  2. 较长的字段名称可以缩写.(即,而不是使用完整的apples字段名称,您可以选择使用a.)

如果不重复字段名称很重要,可以定义一个宏来生成所需的变量(a = foo.a; b = foo.b; c = foo.c); 但是,对于您的代码的读者而言,这可能会更加令人困惑,并且缺乏上面列出的优势.