我有这个小的Rust函数:
pub fn factor(input_array: &mut [i32]) {
let x = input_array
.iter()
.filter(|&x| x % 2 == 0);
x
}
当我通过cargo run
运行时,我收到此错误:
Compiling gettingrusty v0.0.1 (file:///home/lowks/src/rust/gettingrusty)
src/functional.rs:22:9: 22:10 error: mismatched types:
expected `()`,
found `core::iter::Filter<core::slice::Iter<'_, i32>, [closure@src/functional.rs:21:21: 21:36]>`
(expected (),
found struct `core::iter::Filter`) [E0308]
src/functional.rs:22 x
^
src/functional.rs:22:9: 22:10 help: run `rustc --explain E0308` to see a detailed explanation
error: aborting due to previous error
Could not compile `gettingrusty`.
我尝试了一些返回类型,例如slice::Iter<i32>
和core::slice::Iter<i32>
,但似乎所有这些都是错误的。我的函数的返回类型应该是什么?
答案 0 :(得分:3)
在正常情况下,您只需复制+粘贴错误消息的found
部分即可。在这种特殊情况下,存在两个问题。
首先,core
无法直接访问。标准库libstd
公开了各种项目,但libcore
实际上是定义。基本上,标准库是您用来访问这些项的公共接口,但是编译器不知道。通常,您只需将core::*
替换为std::*
即可解决此问题。
第二个问题是该类型包含一个闭包,并且不能命名。最简单的解决方案是根本不使用封闭;无论如何,你并没有抓住任何东西。
这样做只是修复编译错误导致:
pub fn factor(input_array: &mut [i32])
-> std::iter::Filter<std::slice::Iter<i32>, fn(&&i32) -> bool> {
fn even(x: &&i32) -> bool { **x % 2 == 0 }
let x = input_array
.iter()
.filter(even as for<'r> fn(&'r &_) -> _);
x
}
答案 1 :(得分:2)
您的函数返回一个Filter
对象,因此对于某些泛型参数,它的实际返回类型为Filter<_, _>
。这很好,但很可能,你会想要隐藏类型签名中的所有实现细节,只是说你的函数返回一些迭代器。不幸的是,没有(截至今天)这么简单的方法。
似乎很常见的模式是使用newtype包装器。这样做的问题是编写包装器比人们预期的要困难一些,例如,一个人将不得不明确地处理生命。
这是一个完整的例子:
use std::iter::Filter;
use std::slice::Iter;
struct FactorResult<'a, T: 'a>(Filter<Iter<'a, T>, fn(&&T) -> bool>);
impl<'a, T> Iterator for FactorResult<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> { self.0.next() }
fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
}
fn factor(input_array: &[i32]) -> FactorResult<i32> {
fn even(x : &&i32) -> bool { **x % 2 == 0 }
FactorResult(input_array.iter().filter(even))
}
fn main () {
for x in factor(&[1,2,3,4]) {
println!("{}", x);
}
}
factor
函数返回FactorResult
,它只是一个隐藏实际基础类型的包装器。FactorResult
唯一了解的是它是Iterator
。特质的实现是微不足道的,但我必须拼出来。FactorResult<T>
的大小,但是闭包的类型是匿名的,所以没有办法引用它。人们可以使用封闭,但在这种情况下,整个事情都必须装箱。