如何简化在函数中多次将错误转换为字符串的过程?

4
有没有简化这段代码的方法?
fn parse(line: &str) -> Result<(usize, f64), String> {
    let mut it = line.split_whitespace();
    let n  = it.next().ok_or("Invalid line")?;
    let n = n.parse::<usize>().map_err(|e| e.to_string())?;
    let f = it.next().ok_or("Invalid line")?;
    let f = f.parse::<f64>().map_err(|e| e.to_string())?;
    Ok((n, f))
}

fn main() {       
    println!("Results: {:?}", parse("5 17.2").unwrap())
}

在实际代码中,我需要在一行中解析4个值,编写.map_err(|e| e.to_string())很无聊。

据我了解,不可能为ParseIntError/ParseFloatError实现std::convert::From转换成String,因为这些类型都没有在我的代码中定义,我是对的吗?

我看到简化这段代码的一种方法:

fn econv<E: ToString>(e: E) -> String {
    e.to_string()
} 

并且使用 .map_err(econv)。还有其他简化代码的选项吗?

2个回答

3

嗯,一个不太糟糕的选项就是创建一个函数来抽象重复的部分:

use std::fmt::Display;
use std::iter::Iterator;
use std::str::FromStr;

fn parse_next<'a, Target, T>(it: &mut T) -> Result<Target, String>
    where
        T: Iterator<Item = &'a str>,
        Target: FromStr,
        <Target as FromStr>::Err: Display
{
    it.next().ok_or("Invalid line")?.parse::<Target>().map_err(|e| e.to_string())
}

fn parse(line: &str) -> Result<(usize, f64), String> {
    let mut it = line.split_whitespace();
    Ok((parse_next(&mut it)?, parse_next(&mut it)?))
}

fn main() {       
    println!("Results: {:?}", parse("5 17.2").unwrap())
}

2
我会引入单独的错误类型。如果需要,之后我会将错误转换为字符串:
#[macro_use]
extern crate quick_error;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        InvalidLine {}
        Int(err: std::num::ParseIntError) {
            from()
        }
        Float(err: std::num::ParseFloatError) {
            from()
        }
    }
}

fn parse_inner(line: &str) -> Result<(usize, f64), Error> {
    let mut it = line.split_whitespace();
    let n = it.next().ok_or(Error::InvalidLine)?;
    let n = n.parse()?;
    let f = it.next().ok_or(Error::InvalidLine)?;
    let f = f.parse()?;
    Ok((n, f))
}

fn parse(line: &str) -> Result<(usize, f64), String> {
    parse_inner(line).map_err(|e| e.to_string())
}

fn main() {
    println!("Results: {:?}", parse("5 17.2").unwrap())
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接