Rust newbie here (longtime programmer though). This is more a question about what is a canonical way to do "this sort of thing" "in Rust" rather than directly a howto question.
As a learning exercise, I'm translating some code found in an old CS whitepaper from standard ML into Rust. The original functional code used tuples,
(a_value, rest_of_tokens)
as a return type from parsing functions. I found it aided my comprehension to create a helper type for this:
struct ParseResult<'a, T> {
value : T,
rest : &'a [Token],
}
(Side note: rest here might need to become &'a [Token<'a>] where 'a is the lifetime of the str being parsed, and then I'm not sure if that can be 'a twice or if I need two lifetimes, 'a and 'b. But I don't want that to sidetrack my topic question.)
Now the thing is if I want/need parsing to handle failure I might also use Result<T,E>, but as a function return type that becomes partly redundant in both naming and purpose:
Result<ParseResult, Error>
Hmmm, another side note; as I write this I'm wondering if it should rather be:
ParseResult<Result<T,Error>>
This second construction has the benefit of a failed parse being able to still return rest of tokens, however in practice the parse function handles an unsuccessful parse by trying the next choice on fn parse's original input tokens slice; it does not do it by chaining off the result of the previous failed parse choice.
There would, however, be no ambiguity and no naming redundancy if my ParseResult type could also be a Result<T,E>. Either by ParseResult implementing some trait, and/or turning ParseResult into an enum. Is it possible, technically, to integrate this with Rust's built-ins around Result<T,E>? Is it a good idea to implement this this way?
Or, should I just remove the word "result" from the name of type "ParseResult"?
While
Result<Parse, Error>
is in itself clear and succinct, I'm not sure I like "struct Parse" as a name/type standing on its own, and I don't like that the same name, "parse/Parse" is both the name of a function and a type. (Maybe that's fine and I should update my opinion.)
I could use:
Result<Parsing, Error>
which is at least as, if not more, clear about what the result is from. This:
struct Parsing
is a bit weird to have a type ending in "ing", but maybe it's just weird enough that the reader goes, "Hmmm what's going on here? Ah I see: it doesn't stand by itself; it's used in Result<Parsing, Error>."
(This is low-stakes in toy/learning exercise code, but I'm trying to calibrate my sensibilities.)