在 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)
的情况下,编译器推断出 T
是 Number
。在 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<_>>();
在 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)
的情况下,编译器推断出 T
是 Number
。在 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<_>>();