如何从函数返回Filter迭代器? [英] How do I return a Filter iterator from a function?

查看:134
本文介绍了如何从函数返回Filter迭代器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

该函数的返回类型是什么? (我想返回Iterator)

(我希望这不是太明显,我已经尝试了半个小时,刚刚开始感到沮丧:p)

编辑:



我试着按照< a href =https://stackoverflow.com/questions/27535289/correct-way-to-return-an-iterator> here => 围栏连结



编译器给我以下错误:

 < anon>:5:1:7:2错误:特性`core :: kinds :: Sized`没有针对< r> core :: ops :: Fn(&'r T) - > bool +'a` 
< anon>:5 fn filter_one<'a,T:Int>(输入:&'a Vec< T>) - > Filter& T,Iter<'a,T> ;, Fn(& T) - > bool> {
< anon>:6 input.iter()。filter(|& x | x == Int :: one())
< anon>:7}
< anon>:5:1:7:2注:core :: iter :: Filter所需要的
< anon>:5 fn filter_one<'a,T:Int>(input& amp ;'a Vec< T>) - > Filter& T,Iter<'a,T> ;, Fn(& T) - > bool> {
< anon>:6 input.iter()。filter(|& x | x == Int :: one())
< anon>:7}
< anon>:5:1:7:2错误:对于< r> core :: ops :: Fn(&'r&'a T) - > bool`没有被实现用于''< r> core :: ops :: Fn(&'r T) - > bool +'a`
< anon>:5 fn filter_one<'a,T:Int>(输入:&'a Vec< T>) - > Filter& T,Iter<'a,T> ;, Fn(& T) - > bool> {
< anon>:6 input.iter()。filter(|& x | x == Int :: one())
< anon>:7}
< anon>:5:1:7:2注:core :: iter :: Filter所需要的
< anon>:5 fn filter_one<'a,T:Int>(input& amp ;'a Vec< T>) - > Filter& T,Iter<'a,T> ;, Fn(& T) - > bool> {
< anon>:6 input.iter()。filter(|& x | x == Int :: one())
< anon>:7}
错误:由于之前的两个错误而中止
围栏:应用程序以错误代码101终止

如何判断 rustc Fn(& T) - > bool Sized?

解决方案

更新稳定的Rust 1.1

  fn filter_one< a>(输入:&'a [u8]) - > Box< Iterator< Item =&'a u8> +'a> {
Box :: new(input.iter()。filter(|&& x | x == 1))
}

main(){
let nums = vec![1,2,3,1,2,3];
让其他:Vec< _> = filter_one(& nums).collect();
println!({:?},other);
}

稳定的解决方案需要额外的分配。我们创建一个盒装特质对象。在这里,对象的大小总是已知的(它只是一个或两个指针),但堆中对象的大小不需要知道。



正如 Vladimir Matveev指出的,如果您的谓词逻辑不需要来自环境的任何信息,则可以使用函数关闭:

 使用std :: iter :: Filter; 
使用std :: slice :: Iter;

fn filter_one<'a>(输入:&'a [u8]) - >过滤< Iter< u8>,fn(& u8) - >布尔> {
fn is_one(a:&& u8) - > bool {** a == 1}

input.iter()。filter(is_one)
}

fn main(){
let nums = vec![1,2,3,1,2,3];
让其他:Vec< _> = filter_one(& nums).collect();
println!({:?},other);
}

原始答案

以下是返回Iterator的正确方法如何返回一个通用的Map结构?。我们可以创建一个满足特性 Fn 并且是 Sized 的结构,因此可以作为具体项返回。值得注意的是大小为零,所以它实际上并没有消耗额外的堆栈空间:
$ b

 #![功能(unboxed_closures)] 

使用std :: num :: Int;
使用std :: iter :: Filter;
使用std :: slice :: Iter;

struct X;
impl<'a,'r,T:Int> Fn(&'r&'a T) - > bool for X {
externrust-callfn call(& self,(a,):(&& T,)) - > bool {
** a == Int :: one()
}
}

fn filter_one< T:Int>(input:& [T] ) - >过滤器& T,Iter< T>,X> {
input.iter()。filter(X)
}

fn main(){
let nums = vec![1i,2,3,1 1,2,3];
让其他:Vec< _> = filter_one(nums.as_slice())。collect();
println!({},other);



$ b

这只适用于一个特定的逻辑(一次过滤,这种情况),而不是一个通用的封闭。如果您需要任何闭包,那么您可能会在封闭闭包的地方使用解决方案。

I want something like that:

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

What's the return type of that function? (I want to return the Iterator)

(I hope this isn't too obvious, I've been trying for half an hour now and am just starting to get frustrated :p )

EDIT:

I tried to follow the instructions from here => playpen link

the compiler gives me the following error:

<anon>:5:1: 7:2 error: the trait `core::kinds::Sized` is not implemented for the type `for<'r> core::ops::Fn(&'r T) -> bool + 'a`
<anon>:5 fn filter_one<'a, T: Int>(input: &'a Vec<T>) -> Filter<&T, Iter<'a, T>, Fn(&T) -> bool>{
<anon>:6     input.iter().filter(|&x| x == Int::one())
<anon>:7 }
<anon>:5:1: 7:2 note: required by `core::iter::Filter`
<anon>:5 fn filter_one<'a, T: Int>(input: &'a Vec<T>) -> Filter<&T, Iter<'a, T>, Fn(&T) -> bool>{
<anon>:6     input.iter().filter(|&x| x == Int::one())
<anon>:7 }
<anon>:5:1: 7:2 error: the trait `for<'r> core::ops::Fn(&'r &'a T) -> bool` is not implemented for the type `for<'r> core::ops::Fn(&'r T) -> bool + 'a`
<anon>:5 fn filter_one<'a, T: Int>(input: &'a Vec<T>) -> Filter<&T, Iter<'a, T>, Fn(&T) -> bool>{
<anon>:6     input.iter().filter(|&x| x == Int::one())
<anon>:7 }
<anon>:5:1: 7:2 note: required by `core::iter::Filter`
<anon>:5 fn filter_one<'a, T: Int>(input: &'a Vec<T>) -> Filter<&T, Iter<'a, T>, Fn(&T) -> bool>{
<anon>:6     input.iter().filter(|&x| x == Int::one())
<anon>:7 }
error: aborting due to 2 previous errors
playpen: application terminated with error code 101

How do I tell rustc that Fn(&T) -> bool is Sized??

解决方案

Update for stable Rust 1.1

fn filter_one<'a>(input: &'a [u8]) -> Box<Iterator<Item=&'a u8> + 'a> {
    Box::new(input.iter().filter(|&&x| x == 1))
}

fn main() {
    let nums = vec![1,2,3,1,2,3];
    let other: Vec<_> = filter_one(&nums).collect();
    println!("{:?}", other);
}

The stable solution requires additional allocation. We create a boxed trait object. Here, the size of the object is always known (it's just a pointer or two), but the size of the object in the heap does not need to be known.

As Vladimir Matveev points out, if your predicate logic doesn't need any information from the environment, you can use a function instead of a closure:

use std::iter::Filter;
use std::slice::Iter;

fn filter_one<'a>(input: &'a [u8]) -> Filter<Iter<u8>, fn(&&u8) -> bool> {
    fn is_one(a: &&u8) -> bool { **a == 1 }

    input.iter().filter(is_one)
}

fn main() {
    let nums = vec![1,2,3,1,2,3];
    let other: Vec<_> = filter_one(&nums).collect();
    println!("{:?}", other);
}

Original answer

Here's a combination of the concepts of Correct way to return an Iterator? and How to return a generic Map struct?. We can create a struct that meets the trait Fn and is Sized and thus can be returned as a concrete item. Of note is that the size is zero, so it doesn't actually consume additional stack space:

#![feature(unboxed_closures)]

use std::num::Int;
use std::iter::Filter;
use std::slice::Iter;

struct X;
impl<'a, 'r, T: Int> Fn(&'r &'a T) -> bool for X {
    extern "rust-call" fn call(&self, (a,): (&&T,)) -> bool {
        **a == Int::one()
    }
}

fn filter_one<T: Int>(input: &[T]) -> Filter<&T, Iter<T>, X> {
    input.iter().filter(X)
}

fn main() {
    let nums = vec![1i,2,3,1,2,3];
    let other: Vec<_> = filter_one(nums.as_slice()).collect();
    println!("{}", other);
}

This only works for one specific logic at a time (filter by one, in this case), and not a generic closure. If you needed any closure, then perhaps a solution where you box the closure may be useful.

这篇关于如何从函数返回Filter迭代器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆