Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning a simpler Iterator interface instead of a Map in Rust

Tags:

rust

I'd like to write this:

fn fibs() -> std::iter::Iterator<int> {
    return std::iter::iterate((1i, 1i), |(a, b)| { (b, a + b) }).map(|(a, _)| a)
}

But if I do, I get this error:

error: explicit lifetime bound required
fn fibs() -> std::iter::Iterator<int> {
             ^^^^^^^^^^^^^^^^^^^^^^^^

If, instead I write out the full interface, it compiles:

fn fibs() -> std::iter::Map<'static, (int, int), int, std::iter::Iterate<'static, (int, int)>> {
    return std::iter::iterate((1i, 1i), |(a, b)| { (b, a + b) }).map(|(a, _)| a)
}

Is there a way to return the simpler interface?

like image 601
Jamie McCrindle Avatar asked Oct 12 '14 19:10

Jamie McCrindle


2 Answers

There is not at present any way to return an abstract type such as Iterator<T>, just as you can’t assign that as the type of a variable (let x: Iterator<uint>; won’t compile for the same reasons).

This has been discussed and is certainly desired; when it is done it will probably be in the form fn fibs() -> impl Iterator<uint>, but you can’t do that yet.

like image 62
Chris Morgan Avatar answered Nov 15 '22 07:11

Chris Morgan


as @ChrisMorgan said, for now you can't return an abstract type. If you are creating a public API and want to avoid depending too much on the specific implementation of iterate and map, you can encapsulate the return type into your own struct (which is more or less what the collections in the std library themselves do).

Something like:

// updated to rustc 0.13.0-nightly (2015-01-02) 
use std::iter::{Map, iterate, Unfold};

type Fibs = Map<(int, int), int, Unfold<(int, int), 
    (fn((int, int)) -> (int, int), Option<(int, int)>, bool), 
    fn(&mut (fn((int, int)) -> (int, int), Option<(int, int)>, bool)) -> 
        Option<(int, int)>>, fn((int, int)) -> int>;

struct Fibs2 {
    iter: Fibs,
}

impl Fibs2 {
    fn iter() -> Fibs2 {
        fn inner((a, b): (int, int)) -> (int, int) { (b, a + b) }
        let in_fn = inner as fn((int, int)) -> (int, int);

        fn first((a, _): (int, int)) -> int { a }
        let p_first = first as fn((int, int)) -> int;

        Fibs2{ iter: iterate((1i, 1i), in_fn).map(p_first) }
    }
}

impl Iterator<int> for Fibs2 {
    fn next(&mut self) -> Option<int> {
        self.iter.next()
    }
}

fn main() {
    for fib_n in Fibs2::iter().take(10) {
        println!("{}", fib_n);
    } 
}
like image 32
Paolo Falabella Avatar answered Nov 15 '22 08:11

Paolo Falabella