Either a b === a || b
Where `===` means equivalent to. This means that a value of the type can hold either the `a` or the `b`. In order to construct a value of this type you used the `Left` function to construct a value contain the value on the left side of the operator and Right for the other side.They have no "semantics" otherwise. You could call them "Jib" and "Jab," and it'd amount to the same thing. Simply because you ascribe a particular meaning doesn't change their nature. Hence why Left and Right.
Now I do recommend, for readability's sake, ascribing an alias to this type if it aids your understanding of the code when you use it in a particular way that gives your code a certain meaning!
They might convey the exact meaning well, but they (and I) would prefer a type with slightly different semantics that better remind us what each side actually represents.
const ChargeSuccess = Left
const ChargeDeclined = Right
And then use that language in your code. Those words tell you something about the semantics of the code being wrapped. “Normal” and “Error” don’t actually mean much.Also, you might want to someday write:
const NormalDelivery = Left
const FastTrack = Right
And that wouldn’t make much sense if fast track is a so-called error condition.Having a type that is right biased doesn't mean it can't also implement the more generic interface. If your needs change you can always go back to using the less opinionated version with little breakage.
Rust's is notable in that they have both Either and Result. I think there's value in that, even if it is mainly for ergonomics and communication.
Also, aliases are fine, I could just see them being duplicated a lot. Probably not my first choice.
either isn't in std though, it's a third party crate. Personally, I think the core data structure should be as generic as possible. The reality is that if the Result type was named appropriately, the Either crate would be redundant.
What enum? We're talking about a specific data type, it doesn't make any sense to say 'an enum' is the generic version of Result.
I understand why they chose Result instead of Either. I just disagree with it; what you end up with is 2 data structures with the exact same structure and implementations but that represent different things. If you have Either in std, then Result is redundant, but not the other way around.
More fundamentally I disagree that Either makes Result redundant. Result has semantic meaning that's lost with Either.
No, it's not 'a generic', but it has generic type parameters. An enum can be any number of variants with any number of type parameters.
A result is: data Result a b = Err a | Ok b (or in Rust) enum Result<T, E> { Err(E), Ok(T) }
> It's essentially a shorthand instead of manually writing out the enum yourself.
I'm not sure which enum you're referring to. You do realise an enum can have any number of variants, not just 2? I could define a sum type with 16 variants. 'enum' is just Rusts keyword for defining sum types.
> Result has semantic meaning that's lost with Either.
Which is what?
Yes, that's what makes it more generic than Result. Indeed that's the only practical difference except for a few helper functions and a #[must_use] (which only makes sense for Result, not for a more general Either type).
>> Result has semantic meaning that's lost with Either.
>Which is what?
Seriously? Error checking! That's the whole point of it. One side has meaning over the other; it has weight. The "left" is the result you want. The "right" is when something gone wrong.
I think you have some fundamental misconceptions about sum types. Note that enums also don't even need to have any variants.
enum Never {}
Either way, this discussion is no longer fruitful. I encourage you to read about sum & product types.
But, since there's no abstraction that assumes that such a structure of sum-types is shaped like a proper list, there's nothing stopping you from building any arbitrary binary tree of types using Either. And so, like any other binary tree, the two branches get called Left and Right.
As this association was extended to left-handed people, its use nominally perpetuates an ancient slur, but I think we can put that aside.
[1] https://english.stackexchange.com/questions/39092/how-did-si...
An interesting place this is preserved is in heraldry[0], and I've also heard it used in cards (a King, in red, facing the dexter).
"Right" also has the meaning of "upright" (as in right angle) or, archaically, as "straight", and the normal processing path might be regarded as the straight one in the railway metaphor.
[1] https://www.reddit.com/r/etymology/comments/2cdshk/etymology...
Right is actually a synonym for Ok.. besides, Either is useful for _much_ more than error handling. That is exactly why I dislike Error for the left side; often it's just not an error.
If all went well, the result is Right.
If something went awry, you can still examine what's Left.
A good way to remember which variant represents success in the case you're talking about an error is that Right is the "right" variant, Left is the "wrong" one.
At least there's a pun (right vs. left, right vs. wrong), which is probably why the pattern stuck, but I don't think that's actually sufficient justification.
On the other hand, it may be easier to forget the error state if it were the second argument. As is often the case with Promises and JS developers.
A better naming for 99% of cases is (like found in Elm)
type Result error value = Ok value | Err error
I disagree - what if on success it returns a string representing some data, and on failure it returns a string detailing the error? A `string | string` return type is not very useful, while an `Either<string, string>` is IMO.
You could have:
type Result = {type: 'ok', value: string} | {type: 'err', value: string}
It would be bad to name it after error handling, but the entirely meaningless names aren't great either.
The underlying error handling methodology however is awesome and I miss its guarantees and composability in my daily C++ work (yes I know, there's Boost Outcome, but they stripped it of everything useful before including it in boost, as far as I'm concerned).