2

Is there a way to write a function that will look like this:

fn read_and_iter_u32_line<'a>(mut buf: String) -> Iterator<Item=u32> {
    buf.truncate(0);
    io::stdin().read_line(&mut buf).unwrap();
    buf.split_whitespace()
        .map(|s| s.parse::<u32>().unwrap())
}

2 Answers 2

5

Iterators are lazy. This means the data they are operating on needs to exist as long as the iterator itself, but buf ceases to exist when the function returns. If we keep buf around for longer it can work though.

Writing functions that return complex iterators is tricky at the moment, but it's possible:

use std::io;
use std::iter::{Iterator, Map};
use std::str::SplitWhitespace;

fn read_and_iter_u32_line(buf: &mut String) -> Map<SplitWhitespace, fn(&str) -> u32> {
    buf.truncate(0);
    io::stdin().read_line(buf).unwrap();
    buf.split_whitespace().map(parse)
}

fn parse(s: &str) -> u32 {
    s.parse::<u32>().unwrap()
}
Sign up to request clarification or add additional context in comments.

Comments

3

Iterators are lazy, therefore they must borrow their input:

  • this requires that their input lives longer than they do
  • this requires, for safety reason, that the borrowing relationship be exposed at function boundaries

The former point requires that the buf be passed as a reference and not a value.

The latter point prevents you from returning a generic Iterator<Item=u32> (even boxed) because it hides the borrowing relationship between the returned iterator and the passed in buffer. So instead you must be explicit:

use std::io;

fn read_and_iter_u32_line<'a>(buf: &'a mut String)
    -> std::iter::Map<std::str::SplitWhitespace<'a>, fn(&'a str) -> u32>
{
    fn convert(s: &str) -> u32 { s.parse().unwrap() }

    buf.truncate(0);
    io::stdin().read_line(buf).unwrap();

    buf.split_whitespace().map(convert)
}

fn main() {
    let mut buf = "".to_string();
    for i in read_and_iter_u32_line(&mut buf) {
        println!("{}", i);
    }
}

Note: actually, the lifetime annotation can be elided, but I have exposed it here to highlight why the generic iterator is not possible.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.