julia - 参考不带点符号的结构字段(在 Julia 中)
问题描述
在 Julia 中,我定义了一个类型,我需要编写一些函数来处理该类型的字段。一些函数包含复杂的公式,并且到处使用字段访问点表示法会变得很混乱。所以我最终将字段值放入局部变量中以提高可读性。它工作得很好,但是有没有一些聪明的方法可以避免输入所有的a=foo.a
行或让 Julia 解析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
解决方案
因为 Julia 通常鼓励使用通用接口与字段进行交互,而不是直接访问字段,所以实现这一点的一种相当自然的方法是通过迭代解包。在 Julia 中,可以通过迭代将对象“解包”为多个变量:
julia> x, y = [1, 2, 3]
3-element Array{Int64,1}:
1
2
3
julia> x
1
julia> y
2
我们可以为自定义对象实现这样的迭代协议,例如Foo
. 在 v0.7 中,这看起来像:
Base.iterate(foo::Foo, state = 1) = state > 3 ? nothing : (getfield(foo, state), state + 1)
请注意, 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
这可能是函数开始时的“聪明的东西”。此外,从 v0.7 开始,您可以解压缩函数参数本身中的字段:
function bar((a, b, c)::Foo)
a + b + c + a*b - b*c
end
尽管这确实需要您再次提及字段名称,但它具有两个潜在的优势:
- 如果您
struct
被重构并且字段被重命名,所有访问字段的代码都将保持不变(只要字段顺序没有改变或iterate
实现被改变以反映新的对象内部)。 - 较长的字段名称可以缩写。
apples
(即,您可以选择使用,而不是使用完整的字段名称a
。)
如果字段名称不重复很重要,您可以定义一个宏来生成所需的变量(a = foo.a; b = foo.b; c = foo.c
);但是,这可能会让您的代码的读者更加困惑,并且缺乏上面列出的优势。
推荐阅读
- mongodb - 在 ubuntu 中将 .zip 文件导入 mongoDB
- javascript - window.location.reload() 只刷新主页,为什么不刷新专门使用angular的其他页面?
- javascript - FFmpeg 将视频结果流式传输到 net::ERR_CONTENT_LENGTH_MISMATCH 206
- graphviz - 有没有办法让边长从节点的边界开始?
- ruby - 如何将嵌套数组转换为一维?
- reactjs - useCallback 钩子:依赖变量的行为与 2 声明方法不同
- python-xarray - 如何匹配xarray编码中的所有变量(blosc,zarr压缩)
- javascript - 如何使用 ListView 动态过滤
- php - 想测试 laravel 中某个工厂创建的特定方法的调用
- python - BeautifulSoup 没有返回网站的完整 HTML