实施 TryFrom/TryInto 特征(而不是 From/Into)
Implementing TryFrom/TryInto trait (instead of From/Into)
我尝试使用 From
特征“重载”一个函数(以便它可以接受一个结构和一个字符串):
pub struct Measurement {
pub value: i16,
pub unit: char,
}
impl From<&str> for Measurement {
fn from(s: &str) -> Measurement {
let value = s[0..s.len() - 1].parse::<i16>().unwrap();
let unit = s.chars().last().unwrap();
return Measurement { value, unit };
}
}
pub fn print_measurement<T: Into<Measurement>>(value: T) {
let m = value.into();
println!("Measurement is {}{}", m.value, m.unit);
}
fn main() {
print_measurement("40m");
print_measurement(Measurement{value: 23, unit: 'g'});
}
根据 Playground,这按预期工作。但是,由于字符串的解析可能会失败,所以我想使用 try_into()
,而不是 into()
。所以:
use std::convert::TryFrom;
#[derive(Debug)]
pub struct Measurement {
pub value: i16,
pub unit: char,
}
impl TryFrom<&str> for Measurement {
type Error = String;
fn try_from(s: &str) -> Result<Measurement, String> {
let value = s[0..s.len() - 1].parse::<i16>();
let unit = s.chars().last();
match (value, unit) {
(Ok(v), Some(u)) => Ok(Measurement { value: v, unit: u }),
_ => Err("Invalid value or unit".to_string()),
}
}
}
pub fn try_print_measurement<T: TryInto<Measurement>>(value: T) {
let m = value.try_into();
match m {
Ok(m) => println!("Measurement is {}{}", m.value, m.unit),
Err(e) => println!("Error when parsing: {:?}", e),
}
}
fn main() {
try_print_measurement("4_0m"); // <-- this line should fail to parse
try_print_measurement(Measurement{value: 23, unit: 'g'});
}
问题:
- 不幸的是,上面的
error[E0277]: '<T as TryInto<Measurement>>::Error' doesn't implement 'Debug'
失败了。为什么错误类型不等于指定的 String
,而是 <T as TryInto<Measurement>>::Error
?这个错误类型是什么意思?
- 我尝试
let m = Measurement::try_from(value)
而不是 let m = value.try_into()
。但是 error[E0277]: the trait bound 'Measurement: From<T>' is not satisfied
失败了,这看起来很奇怪,因为我称之为 try_from
(而不是 from
)。这是为什么?
- 如何正确实现
TryFrom
特性,以便可以按概述处理解析错误?
- 为什么我们需要通过
use std::convert::TryFrom
将 TryFrom
引入作用域,而 From
特征不需要这个?
- 关联类型仍然是泛型,为什么
TryInto<Measurement>
的每个实现都将 String
用于 TryFrom::Error
?按照编译器提示。您可以为 impl TryFrom<i32> for Measurement
或任何使用不同关联类型的实现。
pub fn try_print_measurement<T>(value: T)
where
T: TryInto<Measurement>,
<T as TryInto<Measurement>>::Error: std::fmt::Debug,
{
let m = value.try_into();
match m {
Ok(m) => println!("Measurement is {}{}", m.value, m.unit),
Err(e) => println!("Error when parsing: {:?}", e),
}
}
- 因为您的绑定是
TryInto<Measurement>
而不是 TryFrom<&str>
。 TryInto
在 T
实施 TryFrom
时有空白实施,而不是相反。
- 你做到了
- 因为 Rust 2018 没有将它包含在前奏中,Rust 2021 does
我尝试使用 From
特征“重载”一个函数(以便它可以接受一个结构和一个字符串):
pub struct Measurement {
pub value: i16,
pub unit: char,
}
impl From<&str> for Measurement {
fn from(s: &str) -> Measurement {
let value = s[0..s.len() - 1].parse::<i16>().unwrap();
let unit = s.chars().last().unwrap();
return Measurement { value, unit };
}
}
pub fn print_measurement<T: Into<Measurement>>(value: T) {
let m = value.into();
println!("Measurement is {}{}", m.value, m.unit);
}
fn main() {
print_measurement("40m");
print_measurement(Measurement{value: 23, unit: 'g'});
}
根据 Playground,这按预期工作。但是,由于字符串的解析可能会失败,所以我想使用 try_into()
,而不是 into()
。所以:
use std::convert::TryFrom;
#[derive(Debug)]
pub struct Measurement {
pub value: i16,
pub unit: char,
}
impl TryFrom<&str> for Measurement {
type Error = String;
fn try_from(s: &str) -> Result<Measurement, String> {
let value = s[0..s.len() - 1].parse::<i16>();
let unit = s.chars().last();
match (value, unit) {
(Ok(v), Some(u)) => Ok(Measurement { value: v, unit: u }),
_ => Err("Invalid value or unit".to_string()),
}
}
}
pub fn try_print_measurement<T: TryInto<Measurement>>(value: T) {
let m = value.try_into();
match m {
Ok(m) => println!("Measurement is {}{}", m.value, m.unit),
Err(e) => println!("Error when parsing: {:?}", e),
}
}
fn main() {
try_print_measurement("4_0m"); // <-- this line should fail to parse
try_print_measurement(Measurement{value: 23, unit: 'g'});
}
问题:
- 不幸的是,上面的
error[E0277]: '<T as TryInto<Measurement>>::Error' doesn't implement 'Debug'
失败了。为什么错误类型不等于指定的String
,而是<T as TryInto<Measurement>>::Error
?这个错误类型是什么意思? - 我尝试
let m = Measurement::try_from(value)
而不是let m = value.try_into()
。但是error[E0277]: the trait bound 'Measurement: From<T>' is not satisfied
失败了,这看起来很奇怪,因为我称之为try_from
(而不是from
)。这是为什么? - 如何正确实现
TryFrom
特性,以便可以按概述处理解析错误? - 为什么我们需要通过
use std::convert::TryFrom
将TryFrom
引入作用域,而From
特征不需要这个?
- 关联类型仍然是泛型,为什么
TryInto<Measurement>
的每个实现都将String
用于TryFrom::Error
?按照编译器提示。您可以为impl TryFrom<i32> for Measurement
或任何使用不同关联类型的实现。pub fn try_print_measurement<T>(value: T) where T: TryInto<Measurement>, <T as TryInto<Measurement>>::Error: std::fmt::Debug, { let m = value.try_into(); match m { Ok(m) => println!("Measurement is {}{}", m.value, m.unit), Err(e) => println!("Error when parsing: {:?}", e), } }
- 因为您的绑定是
TryInto<Measurement>
而不是TryFrom<&str>
。TryInto
在T
实施TryFrom
时有空白实施,而不是相反。 - 你做到了
- 因为 Rust 2018 没有将它包含在前奏中,Rust 2021 does