Julia中的结构体字面量

3
我正在开发一个项目,能够初始化匿名结构体(即不关心它们的类型),这些结构体有任意数量的字段和类型为Any的值,而且只需一行代码即可完成。本质上我需要一个字典,但需要使用点标记法访问值(我知道我可以直接使用字典,但我不是最终用户)。
在Julia中,是否有一种方法可以做到这一点,或者我是否可以定义一种神奇的类型(现在称为mutable struct),其中包含一个疯狂的getfield()重载?我看到Github上的PR关于重载 . 这也很酷,但似乎不会很快出现。
谢谢!

1
你能否举个例子,展示一下你设想的代码可能是什么样子? - Tasos Papastylianou
2个回答

3
如果你满意于你的“匿名结构体”是不可变的(我假设这是正确的,因为你使用了“字面量”这个词),那么你可以通过闭包来模拟它,这可以通过let关键字非常简单地构造:
julia> D = let a=1, b=2; () -> Any[a,b]; end
(::#1) (generic function with 1 method)

julia> fieldnames(D)
2-element Array{Symbol,1}:
 :b
 :a

julia> D()
2-element Array{Any,1}:
 1
 2

julia> D.a
1

julia> D.b
2

julia> (let a=1, b=2; () -> Any[a,b]; end).a
1

julia> (let a=1, b=2; () -> Any[a,b]; end).b
2

This works because closures capture their 'closed' variables as fields.


PS. More specifically, closures are implemented under the hood as callable types (or so I'm told :p)

PPS. For some reason, the fields in the closure are introduced in reverse order. If order matters to you (such that elements in fieldnames(D) and D() are in equivalent order), introduce the 'fields' in reverse order within the let declaration, e.g.: D = let c=3, b=2, a=1; () -> Any[a,b,c]; end.

PPPS. Alternatively, if you find this syntax ugly, you could always implement a "createAnonymousStruct" function that takes a Dictionary or something and returns such a closure


嗯,我感觉我们很快就要陷入XY 问题的领域了...你开始提出一个模糊的问题,现在又试图引导我的回答走向你真正想要的方向,但我仍然不清楚那是什么!:p这就是为什么我问你是否能通过一个例子来澄清你所设想的最终结果!我可以建议几十种方法,其中大多数对你来说都不相关,我们可能会浪费时间通过一些繁琐的排除过程来找到你想要的东西... - Tasos Papastylianou
无论如何,我不明白你关于使用const而不是let的评论,因为它们是完全不同的东西。请查看文档中的let块部分以了解此处发生了什么。此外,考虑到您计划将它们用作“匿名”结构,建议首先避免可变性(如果您计划分配给命名变量,则可以使用命名类型)。如果您想要将其转换为字典以操纵字段,则可以轻松地完成:例如Dict(zip(fieldnames(D), D())) - Tasos Papastylianou
我想邀请您在这里加入聊天室,以了解您的用例和您的具体需求,并让您相应地重新表达问题,但不幸的是,您需要 rep > 20 才能参加此处的聊天室。您可以加入 https://gitter.im/JuliaLang/julia 并在那里聊天。(我的用户名是 @tpapastylianou) - Tasos Papastylianou
这个问题的背景是我需要在一行代码中进行函数调用,而这些函数调用可能包括通常被称为“结构体”的东西。不幸的是,我没有将需要构造以适应指定结构的任意类型污染到父范围的奢侈品。此外,运行在函数调用中的代码超出了我的控制范围。因此,我需要生成一个直接生成值(即文字),不需要为更改字段名称而声明新类型,并且最后生成具有可变值的对象的东西。 - Joe Murphy
谢谢,这很有帮助。XY问题之所以重要,是因为例如您提到了“可变”,但是通过已接受的答案我确认,这不是一个要求(NamedTuples不可变)。您所需要的只是一个setter函数,而NamedTuples通过特殊的setindex函数实现了这一点(与D.a = 1语法不同),它返回一个新对象(即我通过上述实现建议您执行的操作,将其转换为字典然后再转回来)。事实上,我不会感到惊讶,如果发现NT宏在幕后正是如上所述实现的。 - Tasos Papastylianou
显示剩余7条评论

2
尝试使用NamedTuples包来实现此功能:https://github.com/blackrock/NamedTuples.jl。我们还在努力将其添加到语言中,以便它可以具有更好的语法,并且我们可以确保它在每种情况下都能正常工作。

这已经被添加到即将发布的0.7版本中了! - Simon Byrne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接