为什么要在类型参数之前声明生命周期参数?

Why should lifetime parameters be declared before type parameters?

当我遇到这个编译器错误时,我正在尝试一个简单的函数。这背后的真正原因是什么?在我的例子中(下面的代码),在生命周期参数之前写类型参数没有效果。编译器不应该知道得更多吗?

use std::fmt::Debug;

fn random_func<T : Debug, 'a>(parameter : &'a mut T) {
    println!("{:?}", parameter);
}

fn main(){
    let mut name : String = "random".to_string();
    random_func(&mut name);
    println!("{:?}", "compiled successfully");
}

错误:

life_time_trait.rs:3:27: 3:29 error: lifetime parameters must be declared prior to type parameters
life_time_trait.rs:3 fn random_func<T : Debug, 'a>(parameter : &'a mut T) {

                                           ^~

我不确定这是的原因,但请记住,类型参数可以有生命周期界限,但生命周期参数不能有类型界限。所以把它们放在第一位意味着你不需要处理非前向声明。

就我个人而言,我认为这条规则让事情更容易理解,也更容易实施。双赢!

在设计语言时,或多或少会有很多随意的决定。

例如,当不需要实现相同的功能时,为什么允许在函数参数名称前加上 mut?为什么要求 let 声明一个可以消除歧义的变量?

总的来说,归结为方便:

  • 要么给用户,又名 sugar
  • 或对于实施者

回到我上面的例子:

  • mut 是语法糖,避免了函数内部的 let mut name = name;
  • let 保留语法 LL(1),使开发替代解析器更容易(用于文本编辑器或 IDE 例如)

在这种精确的情况下,我不知道确切的原因,但这不是重点。有无数这样或多或少任意的设计决定(尤其是在语法上),这样的 bike shedding 没有什么价值。

有人可能会争辩说 writer 会稍微容易一些,而另一个人会回答说容纳 reader 更重要,并试图证明当前的形式更具可读性......这种争论通常是无休止的,各方拒绝让步。

我个人欢迎这样的编译器限制(并希望 rustfmt),这将减少对未来琐事的争论。