Rust的枚举是代数数据类型。据我所知,这似乎包含了struct是什么。struct有什么不同之处,需要保留它?
a64a0gku1#
首先,您是正确的,就其所能表示的内容而言,enum在语义上严格上级struct,因此struct有些多余。然而,还有其他因素在起作用。
enum
struct
在我看来,struct因此是句法上的糖,我通常更喜欢简洁和平均,但是一点糖可以大大增加简洁的表达。
blmhpbnm2#
首先,Rust具有广泛的数据类型:
struct Foo {bar: uint}
struct Foo(pub Bar, Baz)
struct Foo;
None
Some(T)
Some { pub inner :T }
这给了程序员定义数据类型的灵活性。通常,你不需要命名字段,特别是当struct/variant只有一个字段时。在这种情况下,Rust允许你使用tuple struct/tuple variant。如果从Rust中删除了结构体,那么功能上不会有任何损失,带有结构体变体的枚举可以再次使用。但是会有大量的单变体枚举,这将是不必要的,而且使用起来很麻烦。
cpjpxq1n3#
不是100%正确,但另一个很好的方式来考虑它:enum实际上并不上级struct,语法上的糖衣只是让它看起来像是。enum是一个sum类型,意味着它的值是一组其他类型中的一个值。Result<T, E>类型是T或E类型的 * 任一个 。因此,每个enum变量都有一个类型与之关联。其他任何东西(没有类型、元组变量和结构变量) 都可能 * 是语法糖。
Result<T, E>
T
E
enum Animal { // without syntax sugar Cat(i32), // desugars to `Dog(())` (empty tuple/unit) Dog, // desugars to `Horse((i32, bool))` (tuple) Horse(i32, bool), // desugars to `Eagle(GeneratedEagleType)` and a struct definition outside // of this enum `struct GeneratedEagleType { weight: i32, male: bool }` Eagle { weight: i32, male: bool } }
因此,如果每个enum变体只与一个类型相关联就足够了,在这种情况下,enum并不上级struct,因为它不能构造产品类型(如struct)。能够将“类型定义”写在枚举变量定义中只是为了方便。还有:struct也上级“元组结构”和“元组”。如果我们忽略名称,那三样东西是nearly等价的。但是为了方便起见,Rust仍然有这三种不同的类型。请注意,我不知道这些枚举定义是否真的是语法糖,但它们 * 可能 * 是,这可能有助于思考
nsc4cvqm4#
不是要在可能是暂时的实现细节中寻找原因(我不是核心团队的成员,没有洞察力),而是
k10s72fa5#
你是对的,枚举和特征以及它们通过结构体的继承都实现了代数数据类型。然而traits是一个可扩展的类型集合,任何结构都可以被赋予来自任何代码的trait。使用内省,可以期望一个具有给定trait的值,并动态地挖掘出一个结构的实际类型。但是该类型是不可预测的类型集合之一,因为任何结构都可以从任何地方被赋予所述trait。然而,枚举定义了一个有限的类型层次结构,使得匹配子类型就像它们是简单的值一样是可预测的和直接的。因此,围绕枚举的语言特性可以被优化,以便类型检查静态地发生,提供更好的性能,并在语言中提供一些糖。而且层次结构描述包含在枚举定义中。并且不影响特征类型系统。TL;DR:enum以一种包含的方式缩小了类型的层次结构,而不是依赖于可由任何代码段扩展并影响一切的特性。
vs3odd8k6#
除了上述答案之外,另一个重要的区别是枚举在某个点上只能是所声明的值之一,而结构表示该示例的所有参数的值。
enum Things{ Box, Page(i32), } struct Things{ box: Option<String>, page: i32, }
在上面的例子中,单个枚举可以是Box或Page,而struct的单个示例将表示Box和Page。
6条答案
按热度按时间a64a0gku1#
首先,您是正确的,就其所能表示的内容而言,
enum
在语义上严格上级struct
,因此struct
有些多余。然而,还有其他因素在起作用。
enum
内的值只能通过匹配(直接)访问;与访问struct
字段的易用性相比,您可以为每个字段编写访问器,但这确实很麻烦。enum
是标记并集,struct
具有固定布局;我们(程序员)通常喜欢给事物加上标签,因此可以理解为不同的功能赋予不同的名称。在我看来,
struct
因此是句法上的糖,我通常更喜欢简洁和平均,但是一点糖可以大大增加简洁的表达。blmhpbnm2#
首先,Rust具有广泛的数据类型:
struct Foo {bar: uint}
)struct Foo(pub Bar, Baz)
)struct Foo;
)None
)Some(T)
)Some { pub inner :T }
)这给了程序员定义数据类型的灵活性。通常,你不需要命名字段,特别是当struct/variant只有一个字段时。在这种情况下,Rust允许你使用tuple struct/tuple variant。
如果从Rust中删除了结构体,那么功能上不会有任何损失,带有结构体变体的枚举可以再次使用。但是会有大量的单变体枚举,这将是不必要的,而且使用起来很麻烦。
cpjpxq1n3#
不是100%正确,但另一个很好的方式来考虑它:
enum
实际上并不上级struct
,语法上的糖衣只是让它看起来像是。enum
是一个sum类型,意味着它的值是一组其他类型中的一个值。Result<T, E>
类型是T
或E
类型的 * 任一个 。因此,每个enum
变量都有一个类型与之关联。其他任何东西(没有类型、元组变量和结构变量) 都可能 * 是语法糖。因此,如果每个
enum
变体只与一个类型相关联就足够了,在这种情况下,enum
并不上级struct
,因为它不能构造产品类型(如struct
)。能够将“类型定义”写在枚举变量定义中只是为了方便。
还有:
struct
也上级“元组结构”和“元组”。如果我们忽略名称,那三样东西是nearly等价的。但是为了方便起见,Rust仍然有这三种不同的类型。请注意,我不知道这些枚举定义是否真的是语法糖,但它们 * 可能 * 是,这可能有助于思考
nsc4cvqm4#
可见性
不是要在可能是暂时的实现细节中寻找原因(我不是核心团队的成员,没有洞察力),而是
另见
k10s72fa5#
你是对的,枚举和特征以及它们通过结构体的继承都实现了代数数据类型。
然而traits是一个可扩展的类型集合,任何结构都可以被赋予来自任何代码的trait。使用内省,可以期望一个具有给定trait的值,并动态地挖掘出一个结构的实际类型。但是该类型是不可预测的类型集合之一,因为任何结构都可以从任何地方被赋予所述trait。
然而,枚举定义了一个有限的类型层次结构,使得匹配子类型就像它们是简单的值一样是可预测的和直接的。因此,围绕枚举的语言特性可以被优化,以便类型检查静态地发生,提供更好的性能,并在语言中提供一些糖。而且层次结构描述包含在枚举定义中。并且不影响特征类型系统。
TL;DR:enum以一种包含的方式缩小了类型的层次结构,而不是依赖于可由任何代码段扩展并影响一切的特性。
vs3odd8k6#
除了上述答案之外,另一个重要的区别是枚举在某个点上只能是所声明的值之一,而结构表示该示例的所有参数的值。
在上面的例子中,单个枚举可以是Box或Page,而struct的单个示例将表示Box和Page。