Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I return a Filter iterator from a function?

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??

like image 409
le_me Avatar asked Dec 25 '14 11:12

le_me


1 Answers

Rust 1.26

fn filter_one(input: &[u8]) -> impl Iterator<Item = &u8> {     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); } 

Rust 1.0

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); } 

This 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, 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); } 

See also:

  • What is the correct way to return an Iterator (or any other trait)?
like image 163
Shepmaster Avatar answered Sep 18 '22 22:09

Shepmaster