1
votes

This may be a duplicate. I don't know. I couldn't understand the other answers well enough to know that. :)

Rust version: rustc 1.0.0-nightly (b47aebe3f 2015-02-26) (built 2015-02-27)

Basically, I'm passing a bool to this function that's supposed to build an iterator that filters one way for true and another way for false. Then it kind of craps itself because it doesn't know how to keep that boolean value handy, I guess. I don't know. There are actually multiple lifetime problems here, which is discouraging because this is a really common pattern for me, since I come from a .NET background.

fn main() {
    for n in values(true) {
        println!("{}", n);
    }
}

fn values(even: bool) -> Box<Iterator<Item=usize>> {
    Box::new([3usize, 4, 2, 1].iter()
        .map(|n| n * 2)
        .filter(|n| if even {
            n % 2 == 0
        } else {
            true
        }))
}

Is there a way to make this work?

1
This question was cross-posted to the Rust Reddit.Shepmaster
As a side note, using platform-dependent integers like usize when not needed is discouraged, use i32 or u32 instead.heinrich5991

1 Answers

2
votes

You have two conflicting issues, so let break down a few representative pieces:

[3usize, 4, 2, 1].iter()
    .map(|n| n * 2)
    .filter(|n| n % 2 == 0))

Here, we create an array in the stack frame of the method, then get an iterator to it. Since we aren't allowed to consume the array, the iterator item is &usize. We then map from the &usize to a usize. Then we filter against a &usize - we aren't allowed to consume the filtered item, otherwise the iterator wouldn't have it to return!

The problem here is that we are ultimately rooted to the stack frame of the function. We can't return this iterator, because the array won't exist after the call returns!

To work around this for now, let's just make it static. Now we can focus on the issue with even.

filter takes a closure. Closures capture any variable used that isn't provided as an argument to the closure. By default, these variables are captured by reference. However, even is again a variable located on the stack frame. This time however, we can give it to the closure by using the move keyword. Here's everything put together:

fn main() {
    for n in values(true) {
        println!("{}", n);
    }
}

static ITEMS: [usize; 4] = [3, 4, 2, 1];

fn values(even: bool) -> Box<Iterator<Item=usize>> {
    Box::new(ITEMS.iter()
        .map(|n| n * 2)
        .filter(move |n| if even {
            n % 2 == 0
        } else {
            true
        }))
}