On a scale between "trivial types" and "very complex data sets", where does
Whenever I see uses of
TryFrom it's to report that an destination integer type can not hold a source integer value and such "trivial" cases.
But let's say you have a file format represented by a type, and this file format can be converted to another format. Would it be considered controversial to implement/express this conversion using
TryFrom<FileFormatV1> for FileFormatV2?
I realize it technically can be used for as complex conversions as one wants, but I'm asking from the perspective of Principle of Least Astonishment.
I started making a pretty complicated
TryFrom implementation and I realized I was POLA:ing myself, but I'm not sure if complex
TryFrom implementations really should be stigmatized or not.
I'd guess it's a matter of taste. But then again, since you can actually return detailed error types using
TryFrom, it is a reasonable thing to implement.
Into-style conversions are not expected to be trivial by means of the idiomatic naming convention. I'm not sure what exactly you mean by converting between file formats, though – to me, that would imply creating a new file from an original. I don't see how that could be done through
My own take: it's Ok to have arbitrarily complex
TryFrom as long as it's easy to explain why it may succeed or fail.
For example one can imagine
TryFrom which creates representation of DAG from arbitrary graph.
It would, probably, be complex but if it only fails when graph is not DAG then it's easy to understand what happens on the conceptual level.
Now, imagine very simple
TryFrom which converts
Graph if reference count shows that you are the only owner.
Technically it's valid
TryFrom but I wouldn't implement it as
TryFrom because it's failure or success is not, really, related to properties of
Graph but to the ownership situation around that
Graph in a given moment.
That's kinda bizzare and not obvious because it's not obvious what should happen if reference_count is 2. Would it fail? Would it succeed (via
clone)? What about weak references? Do they affect the outcome or not?
You need to read the documentation and at this point it stops being useful to use familiar trait name.
My heuristic: Only have
impl From<A> for B if it's reasonable to have an
impl TryFrom<B> for A that can recover the original.
That vaguely implies a bunch of things, like successful conversion shouldn't be lossy, it should be the only reasonable way to do a conversion, etc.
std doesn't always respect this. I'd have rathered that
impl From<Vec<T>> for BinaryHeap<T> would have been
BinaryHeap::heapify or something, since the original
Vec cannot be recovered, even fallibly, since the original order is lost. (And it needing a comment on the impl is good evidence that its behaviour is not necessarily "obvious" enough to be a good
So if you're starting to think it's "pretty complicated", I do think that's a good opportunity to see whether you can rearrange things somehow.
What's complicated about it? Could some of that complexity be handled by an infallible
impl From<FileFormatV1> for SupersetFileFormat, maybe, in such a way that
impl TryFrom<SuperSetFileFormat> for FileFormatV2 would be straight-forward enough to be unsurprising? (Just spitballing, since I have no idea about the details.)
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.