为了让我的代码更简洁,我尝试通过名称直接将闭包传递map()给&[&str]. map 需要迭代&&str这是可以理解的,但我的闭包只需要&str.
代码示例:
fn capitalize_first(word: &str) -> String {
word.chars().next().unwrap().to_uppercase().to_string()
}
fn main() {
let cap_cap = |word: &&str| -> String {
word.chars().next().unwrap().to_uppercase().to_string()
};
let a = ["we", "are", "testing"];
let b = &a; // this is where this becomes interesting.
b.iter().map(|&x| capitalize_first(x)); // Works
b.iter().map(|x| capitalize_first(x)); // Works
b.iter().map(cap_cap); // That's what the compiler expects.
b.iter().map(capitalize_first); // fails to compile!
}
Run Code Online (Sandbox Code Playgroud)
编译器错误:
error[E0631]: type mismatch in function arguments
--> src/main.rs:17:18
|
1 | fn capitalize_first(word: &str) -> String {
| ----------------------------------------- found signature of `for<'r> fn(&'r str) -> _`
...
16 | b.iter().map(capitalize_first); // fails to compile!
| ^^^^^^^^^^^^^^^^ expected signature of `fn(&&str) -> _`
Run Code Online (Sandbox Code Playgroud)
有几个问题:
map(|x| capitalize_first(x))而map(capitalize_first)无效?第一个案例的幕后发生了什么样的魔法?在我看来,这些应该是相同的。&&str和 之间透明地转换&str?kmd*_*eko 10
是否有原因导致 Rust 无法在
&&str和 之间透明地转换&str?
Rust确实透明地从 转换为&&str,&str您可以在您的工作示例之一中看到它:
b.iter().map(|x| capitalize_first(x))
// ^ x is a &&str here ^ but seems to be a &str here
Run Code Online (Sandbox Code Playgroud)
幕后发生了什么样的魔法[?]
发生的“魔法”是由于类型强制,特别是Deref强制。“类型强制是改变值类型的隐式操作”。
为什么这有效
map(|x| capitalize_first(x))而map(capitalize_first)无效?
您发现,虽然 to 存在强制&&str,但to&str没有强制。可用的强制非常有限。fn(&&str)fn(&str)
最重要的是,只有特定的地方可以发生强制,但第一个案例之所以有效是因为,随着关闭,强制站点就可以在您调用的地方可用capitalize_first:
b.iter().map(|x| capitalize_first(x))
// ^ the compiler injects code here to do the coercion
// as if you had written capitalize_first(*x)
Run Code Online (Sandbox Code Playgroud)
当您直接使用该函数时,不存在可以发生强制转换的站点。