derive_more
derive_more copied to clipboard
Add `#[try_from(type[, err, err-constructor])]`
It is briefly described in the docs and tests so I spare the duplicate information open the discussion by means of an example.
I felt this is needed when working on an NLP library.
Assume a language has 2 set of characters like below:
enum SetA {
A,
B,
C,
}
impl TryFrom<char> for SetA {
fn try_from(v) -> Result {
Ok(match v.to_lowercase() {
'a' => A,
...
_ => return Err(()),
})
}
}
enum SetE {
E,
F,
G,
}
impl TryFrom<char> for SetE {
fn try_from(v) -> Result {
Ok(match v.to_lowercase() {
'e' => E,
...
_ => return Err(()),
})
}
}
The developer, for whatever reason, decides to also make a union set (not to be confused with the unsafe union type) as written:
enum SetOfSets {
A(SetA),
E(SetE),
}
// #[derive(TryFrom)
// #[try_from(char)]
impl TryFrom<char> for SetOfSets {
fn try_from(v) -> Result {
if let Ok(b1) = SetA::try_from(v) {
return Ok(SetOfSets::A(b1));
}
if let Ok(b1) = SetE::try_from(v) {
return Ok(SetOfSets::E(b1));
}
Err(())
}
}
This macro makes the latter implementation exactly as described.
The first field returning a valid answer to the try_from will be
set and used.
This is rather situational but I thought it's a good idea to share it here even though this is my first contribution and I'm not really good with the custom utilities and standards of this library and only read the parts of code concerned with my own use case... so yeah, have it at that.
Regarding the previous behavior, only a slight compile_fail situation (tests/compile_fail/try_from/invalid_repr.stderr) is changed and the
rest is intact.
I'll be glad to have any suggestions and change requests...
- Sincerely,...
P.S: If not reviewed rapidly, I'll do my best to clean up the code more and update the docs (as I suspect some comments may be old or misleading as this was my after-work little patch and I apologize for whatever shortcomings it has).
First of all, I'm a bit confused. Your PR description seems to be about a completely different feature than the actual feature that's implemented in the code.
Secondly regarding this code snippet:
enum SetOfSets { A(SetA), E(SetE), } // #[derive(TryFrom) // #[try_from(char)] impl TryFrom<char> for SetOfSets { fn try_from(v) -> Result { if let Ok(b1) = SetA::try_from(v) { return Ok(SetOfSets::A(b1)); } if let Ok(b1) = SetE::try_from(v) { return Ok(SetOfSets::E(b1)); } Err(()) } }
I think an inherent problem, or at least surprising behaviour, of this code is what happens when SetA and SetE overlap in the characters that they can be derived from. With this code, it will always cast to A in that case. Is that really desirable?
@JelteF Yes, you are correct. In the case of overlap, by definition, the priority is with the variant which is first defined! This is not desirable and I think an additional attribute is needed to let the user decide which to select in case of such an overlap.
However, I did not implement the priority feature, and probably won't (at least until talk and review a little more). In other words, you are right this is somewhat unfinished and clearly the code shows that the code is not ready to merge. Moreover, it's already enough for my basic local use-cases so I put the development of this branch a tad bit.
I made the PR regardless; To use the expertise of reviews like you before I dedicate more time to it. Since the time I opened this and used the feature for a while, I'm not even sure if this is a good idea to begin with to be honest. Therefore, I decided to sit back, study and observe it a little more while waiting for some activity.
Regarding the comment on the documentation, I am also a bit confused now that you mention it (:D)! Can you please elaborate on the part which is out-of-sync with the description? Excuse my inexperience.
Thanks for the effort you put in seeing this PR
I close this since it's a dormant and niche PR and changes introduced to the crate are a lot since then.
@tyranron Although this is closed, I'm available to help in any way possible (if not a burden, of course)... Thanks for assigning me on this. Let me know if you have any hints on what to do and if you have any ideas about the issues raised before with this half baked idea...