Conflicting lifetime requirement for iterator returned from function

点点圈 提交于 2019-12-24 16:48:04

问题


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:


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


来源:https://stackoverflow.com/questions/28774496/conflicting-lifetime-requirement-for-iterator-returned-from-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!