【问题标题】:Did the Designers of Rust ever publicly say why the syntax of indexing an array is different to indexing a tuple?Rust 的设计者有没有公开说过为什么索引数组的语法与索引元组的语法不同?
【发布时间】:2021-10-07 06:14:41
【问题描述】:

在 Rust 中,可以使用点来索引元组(例如:x.0),而可以使用方括号来索引数组(例如:x[0])。乍一看,这似乎会使重构现有代码变得更加困难,而没有任何实际目的。但是,我可能只是错过了一些东西。 Rust 的创建者有没有对此发表评论并告诉我们他们为什么选择以这种方式构建语言?

【问题讨论】:

  • Rust 是一种强类型语言。索引切片/数组将始终产生相同的类型,因为整个切片中只能有一种类型。 “索引”一个元组实际上意味着“访问一个字段”,这可能会根据您访问的匿名字段产生不同的类型。可能会出现混淆,因为像 Python 这样的语言允许索引甚至迭代元组,这可以很容易地用鸭子类型的语言完成。投票结束,因为我编辑了问题的基于意见的方法,你颠倒了,所以问题仍然要求意见而不是技术原因
  • @AKX 这可能是原因,但在我看来,与数组的相似性更大。这本书甚至将两者并排介绍,请参阅:doc.rust-lang.org/book/…
  • @user2722968 关于索引的要点。关于编辑:您的编辑使其基于意见,而我最初的问题不是。如果你问“为什么……?”那么这是一个关于意见的问题。如果你问“X 有没有说为什么……?”那么这是一个关于事实的问题。至少原则上可以查明 X 是否曾评论过某事。没有意见。如果我错了,这可能已经在 meta 上讨论过了,我会很感激它的链接。

标签: arrays indexing rust tuples language-lawyer


【解决方案1】:

这种元组字段访问语法是在RFC 184 (discussion thread) 中引入的。在此之前,您必须解构所有元组(和元组结构)才能访问它们的值,或者使用标准库中的特殊特征。

RFC 本身并没有详细介绍替代 [index] 语法,但讨论线程会详细说明。我看到了我们最终使用 .index 语法的三个主要原因:

[]std::ops::Index 相关

[index] 语法与 ops::Index 特征密切相关。它允许您为自己的类型重载该运算符。按照 trait 的设计方式,index 方法(在使用 [] 时调用)每次都必须返回相同的类型。所以ops::Index 不能用于异构类型。并且由于[] 与特征非常相关,所以有一些[] 的特殊用法不使用std::ops::Index 可能会很奇怪。

正如在reddit 中所指出的那样,索引本身(即tuple[0]tuple[1] 等)作为替代是没有意义的,因为元组是异构的。 (绝对不能让它们实现 Index* 特征。)

——Comment

索引语法 [is] 实际上非常不合适。值得注意的是,其他地方的索引语法具有一致的类型,但元组是异构的,因此 a[0]a[1] 会有不同的类型。

——Comment

元组/元组结构作为具有匿名字段的结构

Rust 还有其他异构数据类型:structs。您可以使用.field 语法访问他们的字段。并且将元组结构描述为具有未命名字段的结构,并将元组描述为未命名的元组结构,将两者都视为结构是有意义的。然后,.0 感觉就像引用了一个未命名的字段。

我觉得,尤其是在静态类型语言中,a[1], a[2], ..., a[N] 的类型应该是一样的。

是的,这就是为什么没有人提倡向元组添加索引语法的原因。 tuple.1 语法更合适;它基本上是匿名字段访问,而不是索引。

——Comment

元组和元组结构只是具有按其定义排序的匿名字段的结构,因此两者都应支持将字段作为左值直接访问的语法,以使它们的使用更加一致和容易。

——Comment

受 Swift 影响

Swift 已经有了这种语法并且似乎产生了影响:

作为参考,Swift 允许这种元组索引语法,并允许使用它进行赋值。

——Comment

+1 swift 有很多实用的调整,IMO 就是其中之一。

——Comment

感谢 swift,将会有一个熟悉 .0 .1 ... 符号的大型社区

——Comment


顺便说一句:从这个线程可以看出,“Rust 的设计者”在大多数情况下实际上只是社区成员。当然,当时的 RFC 流程存在问题(并且仍然不完美),但您可以在线阅读大部分讨论,社区成员对提议的语法进行评论。

【讨论】:

    【解决方案2】:

    我没有看到任何明确提及该决定背后的原因,但考虑到索引语法的原始含义,这是有道理的。追溯到 C 语言,数组是连续的,这意味着它们存储数据,使得每个数据字节都从前一个字节停止。当您访问数组的第 N 个元素时,您实际上是在访问距离数组开头 N * sizeof(type) 字节开始的数据。

    ---------------------
    | 0 | 1 | 2 | 3 | 4 |
    ---------------------
    

    此方法仅适用于数组中的每个值都属于同一类型并因此使用相同数量的内存时,如 Rust arraysslices 的情况,但 tuple 类型不一定如此.如果设计者允许使用索引访问元组数据,可能会导致学习 Rust 的人对元组的使用做出错误的假设。

    元组通常用于制作简单的“数据类”,它只存储数据,不需要任何关联的方法。因此,您应该将元组视为一个结构,其中所有字段都是公共的并且可以通过数字访问。

    【讨论】:

    • 说实话,我不认为这是一个特别有力的论点。有很多具有异构数组/元组的语言可以通过方括号进行索引。并非所有 Rust 程序员都来自 C。另外,以 JS 为例,[] 可用于访问对象的字段。最后,在 Rust 中有很多 [] 的用法不像 N * sizeof(T) 那样工作——例如HashMap。您甚至可以使用std::ops::Index 自己定义[] 的含义。
    • @LukasKalbertodt 我同意,你的回答肯定比我的更明智。这主要是它对我的意义,尤其是在静态类型语言中。并且尝试帮助 OP 至少接受一段让他们感到困惑的语法。非常感谢您引用的 RFC!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-07
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多