我有使用嵌套的代码,Result如下所示:
fn ip4(s: &str) -> Result<(u8, u8, u8, u8), num::ParseIntError> {
let t: Vec<_> = s.split('.').collect();
match t[0].parse::<u8>() {
Ok(a1) => {
match t[1].parse::<u8>() {
Ok(a2) => {
match t[2].parse::<u8>() {
Ok(a3) => {
match t[3].parse::<u8>() {
Ok(a4) => {
Ok((a1, a2, a3, a4))
}
Err(er) => Err(er)
}
},
Err(er) => Err(er)
}
}
Err(er) => Err(er)
}
}
Err(er) => Err(er),
}
}
Run Code Online (Sandbox Code Playgroud)
是否有任何功能或组成方式来减少这种情况?像Haskell或Scala程序员那样:
fn ip4(s: &str) -> Result<(u8, u8, u8, u8), num::ParseIntError> {
let t: Vec<_> = s.split('.').collect();
Result
.lift((,,,))
.ap(() -> t[0].parse::<u8>())
.ap(() -> t[1].parse::<u8>())
.ap(() -> t[2].parse::<u8>())
.ap(() -> t[3].parse::<u8>()) // maybe more concise in Haskell or Scala but I think it's enough :)
}
Run Code Online (Sandbox Code Playgroud)
log*_*yth 11
您的直接问题的答案是questionmark运算符,它允许您替换整个match块
Ok((
t[0].parse::<u8>()?,
t[1].parse::<u8>()?,
t[2].parse::<u8>()?,
t[3].parse::<u8>()?,
))
Run Code Online (Sandbox Code Playgroud)
?如果遇到错误,将立即返回错误.
也就是说,Rust已经提供了用于解析IP地址的API.即使你想保持你的元组方法(虽然你为什么会这样),你可以实现你的功能
fn ip4(s: &str) -> Result<(u8, u8, u8, u8), net::AddrParseError> {
let addr: net::Ipv4Addr = s.parse()?;
let octets = addr.octets();
Ok((octets[0], octets[1], octets[2], octets[3]))
}
Run Code Online (Sandbox Code Playgroud)
或者直接传递Ipv4Addr值.