How do I return a Filter iterator from a function?

后端 未结 2 1742
别跟我提以往
别跟我提以往 2020-11-28 09:36

I want something like that:

fn filter_one<\'a, T: Int>(input: &\'a Vec) -> ??? {
    input.iter().filter(|&x| x == Int::one())
}
         


        
2条回答
  •  醉话见心
    2020-11-28 10:40

    Unfortunately, it is impossible to return iterators which depend on closures (specifically closures, functions will work fine; see below), like the ones returned by filter() or map() adapters. Here's why.

    This is the signature of filter() iterator extension method:

    fn filter

    (self, predicate: P) -> Filter where P: FnMut(&A) -> bool

    Note that the closure argument accepts any type which implements FnMut trait. That's right, most if not all of the standard libraries have recently been switched to use unboxed closures instead of old boxed ones.

    This signature means, however, that if you specify a closure as an argument to filter(), just like you do in filter_one():

    input.iter().filter(|&x| x == Int::one())
    

    then after monomorphization of this particular call P will become some anonymous unnamed type generated by the compiler. Because it is unnamed, naturally, you can't specify it in type signatures, consequently, you also cannot specify a type of an iterator which depends on unboxed closure - you just wouldn't know what to write as the third argument to Filter.

    You can work around this by using a function instead of a closure, which should be sufficient for your use case:

    use std::slice::Items;
    use std::iter::Filter;
    use std::num::Int;
    
    fn filter_one(input: &[T]) -> Filter<&T, Items, fn(&&T) -> bool> {
        fn equal_to_one(&&x: &&U) -> bool { x == Int::one() }
        input.iter().filter(equal_to_one::)
    }
    
    fn main() {
        let v = [1i, 2, 3];
        let r: Vec = filter_one(v.as_slice()).map(|x| *x).collect();
        println!("{}", r);
    }
    

    Note that I also have changed &Vec to &[T] - you should never use &Vec because it needlessly limits flexibility of your code.

    For more general case of closures, however, it is impossible to do this without abstract return types. There is a proposal to add them, but it was postponed until after 1.0.

提交回复
热议问题