在Julia我已经定义了一个类型,我需要编写一些与该类型的字段一起使用的函数.某些函数包含复杂的公式,并且在整个地方使用字段访问点表示法会变得混乱.所以我最终将字段值放入局部变量中以提高可读性.它工作正常,但有一些聪明的办法,以避免键入了所有的a=foo.a
线或有朱莉娅解析a
为foo.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)
因为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)
虽然这确实需要您再次提及字段名称,但它具有两个潜在优势:
struct
被重构并且字段被重命名,则访问字段的所有代码将保持不变(只要字段顺序不改变或iterate
实现被更改以反映新对象内部).apples
字段名称,您可以选择使用a
.)如果不重复字段名称很重要,可以定义一个宏来生成所需的变量(a = foo.a; b = foo.b; c = foo.c
); 但是,对于您的代码的读者而言,这可能会更加令人困惑,并且缺乏上面列出的优势.