无法弄清楚返回Iter的这个Rust函数的返回类型?

时间:2016-01-14 08:31:16

标签: rust

我有这个小的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>,但似乎所有这些都是错误的。我的函数的返回类型应该是什么?

2 个答案:

答案 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。特质的实现是微不足道的,但我必须拼出来。
  • 我不得不用函数替换闭包。这是因为这里Rust没有执行任何分配,所以它需要知道FactorResult<T>的大小,但是闭包的类型是匿名的,所以没有办法引用它。人们可以使用封闭,但在这种情况下,整个事情都必须装箱。