主要是要練習如何撰寫及應用 error conversion。
整個程式是要實作一個新的型別 PositiveNonzeroInteger
,意即「正整數」;0 或負整數都不是合法的。這個正整數要從字串 parsing 而來。如果 parsing 時就出問題,要把 parse()
的 error 轉換成 ParsePosNonezeroError::ParseInt()
;而如果 parsing 沒問題,但數值本身是 0 或負整數的話,就要回傳 ParsePosNonezeroError::Creation()
(依據數值是 0 或負整數,會代不同的 error code)。
Conversion 的部份很單純:
impl ParsePosNonzeroError {
fn from_creation(err: CreationError) -> ParsePosNonzeroError {
ParsePosNonzeroError::Creation(err)
}
fn from_parsing(err: ParseIntError) -> ParsePosNonzeroError {
ParsePosNonzeroError::ParseInt(err)
}
}
比較有趣的是應用的部份。
解法一
用 pattern match。無趣了點,但至少很清楚。
fn parse_pos_nonzero(s: &str)
-> Result
{
let x = match s.parse() {
Ok(i) => i,
Err(e) => return Err(ParsePosNonzeroError::from_parsing(e)),
};
// PositiveNonzeroInteger::new() 回傳的 error type 是 CreationError,
// 因此需要用 map_err 轉換成 ParsePosNonezeroError。
PositiveNonzeroInteger::new(x)
.map_err(ParsePosNonzeroError::from_creation)
}
解法二
利用 ?
簡化解法一。重點是要先做完 map_err()
後才加 ?
。
fn parse_pos_nonzero(s: &str)
-> Result
{
let x = s.parse().map_err(ParsePosNonzeroError::from_parsing)?;
PositiveNonzeroInteger::new(x)
.map_err(ParsePosNonzeroError::from_creation)
}
解法三
想要用一個 expression 解決?這不就來了嗎?用 and_then()
來串接。
fn parse_pos_nonzero(s: &str)
-> Result
{
s.parse()
.map_err(ParsePosNonzeroError::from_parsing)
.and_then(|x| {
PositiveNonzeroInteger::new(x)
.map_err(ParsePosNonzeroError::from_creation)
})
}