Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
411 views
in Technique[技术] by (71.8m points)

rust - Return Iterator of an array wrapped in an Option

I'm trying to return an array iterator of an array in an Option from the closure passed to a filter_map so I can flatten it afterwards. Unfortunately, rustc produces the following error:

cannot return value referencing local variable `res`

returns a value referencing data owned by the current function
main.rs(3, 5): returns a value referencing data owned by the current function
main.rs(3, 10): `res` is borrowed here

for the minimal example:

fn demo<'a>() -> Option<impl Iterator + 'a> {
    let res = [1,2];
    Some(res.into_iter())
}

Though the complete code I'm trying to make work is this:

fn generate_next<'a>(prev: &'a [u32]) -> impl Iterator + 'a {

    let mut counter = 1_u32;

    prev.windows(2).filter_map(move |window| {
        
        if window[0] == window[1] {
            counter+=1;
            None
        } else {
            let res = [counter, window[0]];
            counter=1;
            Some(res.into_iter())
        }
    }).flatten()
}

Both produce the same error for the Some(...) part.

If I understand correctly, the code should work, because the into_iter() method consumes the array and produces an iterator from it. Some should then take ownership of the iterator via a move. Why does rustc think that I'm borrowing res here?

I'm also open to other ways to implement the generate_next function.

question from:https://stackoverflow.com/questions/66049801/return-iterator-of-an-array-wrapped-in-an-option

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Calling into_iter() on an array produces the same result as calling iter(), i.e. an iterator over references. This is an unfortunate gotcha within the Rust standard library.

You can accomplish what you want by using std::iter::once to create iterators of counter and window[0] and then chain them together:

fn generate_next<'a>(prev: &'a [u32]) -> impl Iterator + 'a {
    let mut counter = 1_u32;

    prev.windows(2)
        .filter_map(move |window| {
            if window[0] == window[1] {
                counter += 1;
                None
            } else {
                let counter_iter = std::iter::once(counter);
                let window_iter = std::iter::once(window[0]);
                counter = 1;
                Some(counter_iter.chain(window_iter))
            }
        })
        .flatten()
}

playground


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...