【发布时间】:2021-08-24 03:24:14
【问题描述】:
在做rustlings standard_library_types/iterators2.rs 时,我开始想知道std::iter::Iterator::map 如何调用它的参数闭包/函数。更具体地说,假设我有一个函数
// "hello" -> "Hello"
pub fn capitalize_first(input: &str) -> String {
let mut c = input.chars();
match c.next() {
None => String::new(),
Some(first) => String::from(first.to_ascii_uppercase()) + c.as_str(),
}
}
现在我想用在
// Apply the `capitalize_first` function to a slice of string slices.
// Return a vector of strings.
// ["hello", "world"] -> ["Hello", "World"]
pub fn capitalize_words_vector(words: &[&str]) -> Vec<String> {
words.into_iter().map(capitalize_first).collect()
}
无法编译
error[E0631]: type mismatch in function arguments
--> exercises/standard_library_types/iterators2.rs:24:27
|
11 | pub fn capitalize_first(input: &str) -> String {
| ---------------------------------------------- found signature of `for<'r> fn(&'r str) -> _`
...
24 | words.into_iter().map(capitalize_first).collect()
| ^^^^^^^^^^^^^^^^ expected signature of `fn(&&str) -> _`
error[E0599]: the method `collect` exists for struct `Map<std::slice::Iter<'_, &str>, for<'r> fn(&'r str) -> String {capitalize_first}>`, but its trait bounds were not satisfied
--> exercises/standard_library_types/iterators2.rs:24:45
|
24 | words.into_iter().map(capitalize_first).collect()
| ^^^^^^^ method cannot be called on `Map<std::slice::Iter<'_, &str>, for<'r> fn(&'r str) -> String {capitalize_first}>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`<for<'r> fn(&'r str) -> String {capitalize_first} as FnOnce<(&&str,)>>::Output = _`
which is required by `Map<std::slice::Iter<'_, &str>, for<'r> fn(&'r str) -> String {capitalize_first}>: Iterator`
`for<'r> fn(&'r str) -> String {capitalize_first}: FnMut<(&&str,)>`
which is required by `Map<std::slice::Iter<'_, &str>, for<'r> fn(&'r str) -> String {capitalize_first}>: Iterator`
`Map<std::slice::Iter<'_, &str>, for<'r> fn(&'r str) -> String {capitalize_first}>: Iterator`
which is required by `&mut Map<std::slice::Iter<'_, &str>, for<'r> fn(&'r str) -> String {capitalize_first}>: Iterator`
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0599, E0631.
For more information about an error, try `rustc --explain E0599`.
但是,在我将.map(capitalize_first) 更改为.map(|x| capitalize_first(x)) 后,它工作正常。显然,Rust 在将每个项目传递给 map 的参数闭包/函数之前借用(不确定是可变还是不可变),这是有道理的,因为我们通常不希望使用被迭代的对象。
我不明白为什么 Rust 不借用 |x| capitalize_first(x) 的参数。我假设闭包|x| capitalize_first(x) 仍然得到&&str,然后auto-dereferencing rules 启动并将其取消引用到&str,但这并不能解释为什么当我使用该函数时它没有启动capitalize_first。 .map(|x| capitalize_first(x)) 和 .map(capitalize_first) 有什么区别?考虑到map 的参数是一个特征对象,这里是否发生了动态调度?
注意:这个问题与Using a function with iter().map() - as a named function vs as a closure 不重复,因为我在问为什么,而另一篇帖子问如何。关于这个问题的公认答案,如果有人能解释为什么我们需要 AsRef 而 Rust 已经有 auto-dereferencing rules,我将不胜感激。
【问题讨论】:
标签: rust functional-programming iterator dereference trait-objects