有没有技术上的原因,为什么实施不仅仅是推动Foo <t>?

时间:2017-11-18 01:56:50

标签: generics syntax rust

我刚刚了解到使用泛型的结构体被声明为struct Foo<T>,并且实现被声明为impl<T> Foo<T>book以下列方式解释了差异:

  

请注意,我们必须在T之后声明impl才能在T类型中使用Point<T>。在T之后将impl声明为泛型类型是Rust知道Point中尖括号中的类型是泛型类型而不是具体类型。

同样,我是一个新手,但是因为必须宣布struct<T> Foo<T>(甚至可能是fn<T> foo<T>(bar: T))而无法做出相同的论证?

2 个答案:

答案 0 :(得分:7)

impl Foo<T> { ... }

T是类型参数,还是名为T的实际类型?如果您回答了第二个问题,那么您已经完全抛弃了泛型:不可能为一组通用类型实现功能。如果你回答了第一个,那么你如何建议用户这样做:

impl Foo<T> { /* generic stuff */ }
impl Foo<i32> { /* i32-specific stuff */ }
impl Foo<u32> { /* u32-specific stuff */ }

这只是三个impl块,其类型参数分别为Ti32u32

你可能会说“好吧,只是从上下文决定”。现在,为了弄清楚发生了什么,用户不仅要检查模块的其余部分,还要检查所有导入的符号标准库的前奏中的任何内容,以便确定类型是否为参数与否。鲁斯特厌恶这种模糊性。

编译器和读者只需具体了解什么是参数而不是参数,这是远远不够的

您不必对struct执行此操作,因为括号中的内容不可能是其他而不是类型参数声明。

答案 1 :(得分:1)

除了@dk的答案之外,我想比较一下Rust如何做到Haskell的做法。

在Haskell中,所有特定类型都必须开始大写。因此,写下来是违法的:

data mytype Var = Constructor {
    myVar :: Var,
    myInt :: Foo
}

相反,Haskell保留的类型以类型变量的小写字母开头:

data MyType var = Constructor {
     myVar :: var
     myInt :: Int
}

instance MyClass (MyType var) where
     ...

此处,var是一个类型变量,MyType是具体的,Int是具体的。

在我看来 - 你可能不会分享,Rust犯了错误,允许使用非大写的类型标识符。因此,该语言别无选择,只是要求您明确说明哪些类型标识符是变量,哪些是特定的。可以认为Rust的显性提高了可读性。相反也可以争论。

Rust当然可以添加一个假设的功能,您可以说:

 impl Foo<#T, T, u32> { .. }

此处,前缀#表示“这是一个类型变量”,因此#T是一个类型变量,T是特定的,u32是具体。没有歧义,只需要本地推理。

有了这个功能,你可能会得到一点点冗长,但我坚信这艘船已经航行了 - 现在添加这个功能只会增加另一种方式来做同样的事情而获得的收益很少。但是,该功能会增加使用语言用户必须学习的其他功能的成本。

相关问题