16.4 Multiple error types

이전 예제는 항상 매우 편리했다; Result는 다른 Result와 그리고 Option은 다른 Option들과 상호작용 했다.

어떨 때는 OptionResult와 상호작용 할 필요가 있거나, Result<T, Error1>Result<T, Error2>와 상호작용 할 필요가 있다. 이런 경우 때문에 우리의 다양한 에러 타입들을 관리하여 이들을 쉽게 상호작용 할 수 있도록 만들고자 하는 것이다.

다음의 코드에서, 두 인스턴스가 unwrap되어 다른 에러 타입을 만든다. Vec::firstOption을 반환하고 parse::<i32>Result<i32, ParseIntError>를 반환한다:

fn double_first(vec: Vec<&str>) -> i32 {
    let first = vec.first().unwrap(); // Generate error 1
    2 * first.parse::<i32>().unwrap() // Generate error 2
}

fn main() {
    let empty = vec![];
    let strings = vec!["tofu", "93", "18"];

    println!("The first doubled is {}", double_first(empty));
    // Error 1: the input vector is empty

    println!("The first doubled is {}", double_first(strings));
    // Error 2: the element doesn't parse to a number
}

연결자에 대한 우리의 지식을 활용하여, 우리는 상기 예제를 명시적으로 에러 처리를 하게끔 재작성할 수 있다. 두 다른 타입의 에러가 일어난 후에, 우리는 이들을 String고 같은 범용 타입으로 변경해야 한다.

이를 위해, 우리는 OptionResultResult들로 변형하고, 그들의 에러들을 동일 타입으로 map한다:

// 에러 타입으로 `String` 사용
type Result<T> = std::result::Result<T, String>;

fn double_first(vec: Vec<&str>) -> Result<i32> {
    vec.first()
       // 값이 있을 시 `Option`을 `Result`로 변환.
       // 그렇지 않으면, 이 `String`을 포함하는 `Err`를 제공.
       .ok_or("Please use a vector with at least one element.".to_owned())
       .and_then(|s| s.parse::<i32>()
                      // `parse`가 얻는 에러를 `String`에 맵핑한다.
                      .map_err(|e| e.to_string())
                      // `Result`은 새로운 리턴 타입이고,
                      // 이제 내부 숫자를 두 배로 늘릴 수 있다.
                      .map(|i| 2 * i))
}

fn print(result: Result<i32>) {
    match result {
        Ok(n)  => println!("The first doubled is {}", n),
        Err(e) => println!("Error: {}", e),
    }
}

fn main() {
    let empty = vec![];
    let strings = vec!["tofu", "93", "18"];

    print(double_first(empty));
    print(double_first(strings));
}

다음 섹션에서, 명시적으로 에러를 처리하는 다른 방법을 살펴본다.

See Also:

Option::ok_or, Result::map_err

results matching ""

    No results matching ""