Reputation: 3360
Is there any real difference between FromStr
and TryFrom<&str>
?
From the definitions in the documentation, they look identical once you substitute &str
for T
in TryFrom
:
pub trait FromStr {
type Err;
fn from_str(s: &str) -> Result<Self, Self::Err>;
}
pub trait TryFrom<T> {
type Error;
fn try_from(value: T) -> Result<Self, Self::Error>;
}
Then there is parse:
FromStr’s from_str method is often used implicitly, through str’s parse method.
But if we look at its implementation, we see that it does not do anything beyond providing a slightly shorter way of calling from_str
:
pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
FromStr::from_str(self)
}
If you look at TryFrom's library implementations, then it is almost exclusively composed of numerical conversions, though there is also:
impl<'_, T, const N: usize> TryFrom<&'_ [T]> for [T; N] where
T: Copy,
type Error = TryFromSliceError
which is reminiscent of
impl FromStr for String {
type Err = core::convert::Infallible;
#[inline]
fn from_str(s: &str) -> Result<String, Self::Err> {
Ok(String::from(s))
}
}
Converting the example implementation of FromStr from the docs to TryFrom is trivial.
There was a similar question on Reddit to which the best answer seems to be "just implement both".
Finally there is this similar question though it uses the wrong type and the Serde context is a distraction.
So:
FromStr
and TryFrom<&str>
?Upvotes: 5
Views: 943
Reputation: 70950
FromStr
provides more type information to the compiler, and thus may help inference. It is also more specific, and thus helps the reader. When the intent is to parse the string, I would use FromStr
, because it can be used via the parse()
method. If this is just for conversion, I would implement TryFrom<&str>
.
Also remember that as stated in What is the difference between the FromStr and TryFrom<String> traits?, FromStr
preceeded TryFrom
.
Is there any plan for the future towards improving the situation?
Nothing that I'm aware of.
Upvotes: 2