在 rust-lang 中,`static_fly::<Number>(number);` 和 `static_fly(number); 之间有什么区别?

in rust-lang, what's the difference between `static_fly::<Number>(number);` and `static_fly(number);`

在 rust-lang 中,static_fly::<Number>(number);static_fly(number);

有什么区别

这是一个演示:

enum Number {
    Zero,
    One,
    Two,
}

trait Fly {
    fn fly(&self);
}

impl Fly for Number {
    fn fly(&self) {
        println!("flying number: {}", self)
    }
}

// 静态分发
fn static_fly<T: Fly>(f: T){
    print!("静态分发\t");
    f.fly()
}

fn main() {
    let number = Zero;
    // 泛型的分发调用
    static_fly(number);                 // <-- here is the 1st method for calling static_fly
    // static_fly::<Number>(number);    // <-- here is the 2nd method for calling static_fly
}

这两个调用有什么区别

本例中两种调用函数的方法是等价的

给定足够的信息,Rust 可以推断泛型类型参数。在 static_fly(number) 的情况下,编译器推断出 TNumber。在 static_fly::<Number>(number) 的情况下,您只是明确地为类型参数 T 提供了类型。

这与编译器执行的其他类型的推理非常相似。例如,这两个语句也是等价的:

let number = Zero;
let number: Number = Zero;

原理是一样的——在一种情况下我们指定类型,在另一种情况下我们让编译器自行判断。

let a = b;相比let a: Type = b;是一回事。它使您可以选择明确说明操作中使用的类型。通常 Rust 可以推断出你想做什么,但是如果有任何歧义,编译器会要求你明确指定一个类型。

例如,我 运行 最常见的实例是在迭代器上调用 .collect() 时。


fn foo(vals: &[u32]) -> Vec<u32> {
    // In this case there is no ambiguity since the result of collect must
    // be a `Vec<u32>`. Since the compiler can infer the type, we don't need
    // to state what type collect uses.
    vals.iter()
        .map(|x| x * 2)
        .collect()
}

fn bar(vals: &[u32]) -> u32 {
    // In this case the compiler is unable to infer a type as collect can
    // create any type that can be initialized with an iterator.
    let mut a = vals.iter()
        .map(|x| x * 2)
        .collect();

    a.sort();
    a[0]
}

对于此示例,您可以通过多种方式修复 bar

// State the type of a so the compiler can infer collect's types
let mut a: Vec<u32> = vals.iter()
    .map(|x| x * 2)
    .collect();

// State the types used by the function in question but let the compiler infer a's type
let mut a = vals.iter()
    .map(|x| x * 2)
    .collect::<Vec<u32>>();

另一种选择是仅部分说明相关类型。类型名称可以用下划线替换,以告诉编译器推断类型的那部分。这通常是我处理这种特定情况的首选方式。

// Tell the compiler we will collect items to a Vec, but let it infer the content type
let mut a = vals.iter()
    .map(|x| x * 2)
    .collect::<Vec<_>>();