Beginners query on borrowing and and_then using read_to_string() as an example

so, I wanted to read the contents of a file. i wanted use the result and not just panic if something went wrong, ie not expect. this was my first attempt:

    let r = File::open("a.txt").and_then(|f| {
    let mut s = String::new();
    f.read_to_string(&mut s).and_then(|_| Ok(s))
});

this told me I couldn't borrow f as mutable. aha! I next tried:
let r = File::open("a.txt").as_mut().and_then(|f| {
let mut s = String::new();
f.read_to_string(&mut s).as_mut().and_then(|_| Ok(s))
});

I now get borrowed value does not live long enough. At this point I believe I'm stuck, or is this even possible?

thanks,

|mut f| the error in first code should be containing this.

1 Like

It wants

let mut /*edit*/f = File...

The .as_mut() isn't enough, because it's called on a value that hasn't been assigned to a variable, so it lives only temporarily for the expression (one line)

I recommend using the ? operator. It'll save you writing so many and_then().

To avoid panicking, put file reading code in a function, and then match that_function() to handle the error nicely.

1 Like
    let r = File::open("a.txt").and_then(|mut f| {
    let mut s = String::new();
    f.read_to_string(&mut s).and_then(|_| Ok(s))
});

worked a treat!
I didn't have so much success with let mut r = File...

Using the ? operator worked nicely, in a do notation style, but the special sauce was it needs to be in a function that returns Result. This gave me:

fn read_text() -> std::io::Result<String> {
let mut f = File::open("a.txt")?;
let mut s = String::new();
f.read_to_string(&mut s)?;
Ok(s)

}

thanks all :slight_smile:

Yup, that's it!

std::io::Result can be shortened to just Result (the compiler prints the full name, but the Result is available globally).

std::result::Result is, not the io one :slight_smile:

1 Like

Oh, right. I misread.

1 Like

many thanks. it's starting to come together now

See also:

thanks. that looks handy