【问题标题】:Why does Rust put a :: before the parameters in generics sometimes?为什么 Rust 有时会在泛型中的参数前放 :: ?
【发布时间】:2015-03-10 03:15:17
【问题描述】:

在 Rust 中声明向量类型的变量或哈希映射时,我们会这样做:

let v: Vec<int>
let m: HashMap<int, int>

要实例化,我们需要调用new()。但是,我们这样做:

Vec::<int>::new()
   ^^
HashMap::<int, int>::new()
       ^^

注意:: 的突然出现。来自 C++,这些很奇怪。为什么会出现这些?具有领先的:: 是否使IDENTIFIER :: &lt; IDENTFIER …IDENTIFIER &lt; IDENTIFIER 更容易解析,这可能被解释为小于运算? (因此,这只是为了让语言更容易解析?但如果是这样,为什么不在类型规范中也这样做,以使两者相互镜像?)

(正如 Shepmaster 所说,Vec::new() 通常就足够了;通常可以推断出类型。)

【问题讨论】:

  • 它们在 Rust 中不被称为 模板;我认为你的 C++ 正在展示。 :-) 有趣的是,我从未见过指定类型参数的特殊用法。使用类型推断,你可以说Vec::new()。我唯一一次看到指定这样的类型是针对返回特征的函数,您必须选择具体类型,例如 parsecollect
  • @Shepmaster:Ack,它们是泛型的,不是吗?是的,一定数量的类型推断可以避免您需要指定实际类型;我想我偶然发现了这一点,主要是作为 Rust 的新手,还没有意识到类型推断可以做到这一点,并且仍然想知道为什么。
  • 我认为这是个好问题;我什至没有意识到您可以在该位置指定类型参数!我期待一个答案,但我的猜测是,正如您所建议的那样,这将归结为解析的简单性。我只是想发表评论以表明您的示例代码并不常见,希望对阅读此问题的其他新手有所帮助。干杯!
  • 在大多数情况下,类型推断确实可以解决问题,但有些函数的类型参数既不出现在参数中,也不出现在返回值中,在这种情况下,您必须使用该语法。这种函数的一个例子是std::mem::size_of()

标签: rust grammar language-design


【解决方案1】:

在解析表达式时,&lt; 是类型参数列表的开头还是小于运算符的开头是不明确的。 Rust 总是假设后者并且需要::&lt; 用于类型参数列表。

当解析一个类型时,它总是明确的类型参数列表,所以::&lt; 是不必要的。

在 C++ 中,这种歧义保留在解析器中,这使得解析 C++ 比解析 Rust 困难得多。请参阅 here 了解为什么这很重要。

无论如何,大多数在 Rust 中,类型可以被推断出来,你可以写 Vec::new()。由于::&lt; 通常不需要并且相当丑陋,因此在类型中只保留&lt; 是有意义的,而不是使两种语法匹配。

【讨论】:

  • 你知道是否有任何理由不在变量声明期间复制语法,例如let v: Vec::&lt;int&gt;
  • 我在最后做了一个编辑来解决这个问题。我认为,基本上,::&lt; 很丑陋,我们希望尽可能避免它。在类型中使用 &lt; 并进行类型推断可以让我们大部分时间免于使用它。
  • 这是否被解析为单个符号::&lt;
  • 不,如果你愿意,你可以写:: &lt;
  • 我感叹,如果只有 rust 跟随 scala 并为泛型保留 [ ] 而不是将它们浪费在数组索引上,这与 apply 运算符的 ( )s 一样好用.
【解决方案2】:

这两种不同的语法甚至不一定指定相同的类型参数。

在这个例子中:

let mut map: HashMap<K, V>;

KV 填充struct HashMap 声明的类型参数,即类型本身。

在这个表达式中:

HashMap::<K, V>::new()

KV 填充 impl 块的类型参数,其中定义了方法 new! impl 块不需要与类型本身具有相同、尽可能多或相同的默认类型参数。

在这种特殊情况下,结构具有参数HashMap&lt;K, V, S = RandomState&gt;(3 个参数,1 个默认值)。并且包含::new()的impl块有参数impl&lt;K, V&gt;(2个参数,不针对任意状态实现)。

【讨论】:

    猜你喜欢
    • 2017-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-21
    相关资源
    最近更新 更多