Add additional `Option` methods
Add Option equivalents of the following System.Linq.Enumerable methods:
-
Intersect: a kind of eager Boolean "and" over 2 options. Returns the second option unless the first is None. -
Union: a kind of eager Boolean "or" over 2 options. Returns the first option unless it is None. -
SelectMany: a chainable version of Select akin toEnumerable.SelectMany. The supplied function returns an option rather than a bare type, and the result type is the function's result type. -
SomeOrDefault: a kind ofEnumerable.Concatover an option and an option-generating thunk. If the option is None, call the thunk to generate a default option.
All names of these new methods are open to revision. These are less common methods and their names vary in other programming languages. Alternatives might be:
-
Option.Intersect-->Option.And -
Option.Union-->Option.Or -
Option.SelectMany-->Option.BindorOption.AndThen -
Option.SomeOrDefault-->Option.ConcatorOption.OrElse
SomeOrDefault is called or_else in Rust and C++23. SelectMany is variously called and_then (Rust, C++23, Elm),
bind (OCaml), or flat_map (Nim, Swift). Intersect is called and in Rust, and Union is called or in Rust.
@rabeckett Feel free to suggest alternative names. One option (ha ha) is to stick very closely to System.Linq.Enumerable.
-
Option.Intersectfor the "and" of two Options. A bit unclear as a name perhaps, since twoOption.Somes with different values don't produceOption.None:Option.Some(3).Intersect(Option.Some(1)) == Option.Some(1). -
Option.Unionfor the "or" of two Options. Again, a similar problem toOption.Intersect, as "union" does not suggest that, when given twoOption.Somes, the result is the first value:Option.Some(3).Union(Option.Some(1)) == Option.Some(3). -
Option.Concatinstead ofOption.SomeOrDefault. Somewhat intuitive since it respects the fact thatEnumerable.Emptyis an identity:Enumerable.Empty<int>().Concat(enumerable) == enumerableandOption.None<int>().Concat(thunk()) == thunk(). On the other hand,SomeOrDefaulttells you more about what it actually does. -
Option.SelectManyfor a flat-map over an Option. "Many" looks a little strange in this context, since we're not projecting multiple enumerables into one, but that's an unfortunate consequence of C#'s choice of names.
Names that might be less aligned with Enumerable but more suggestive of the methods' purposes would be Option.And, Option.Or, Option.SomeOrDefault and Option.AndThen, respectively.
Very nice.
In terms of naming, I find the rust naming convention to be fairly sensible.
Option.Intersect -> Option.And
Option.SelectMany -> Option.AndThen
Option.Union -> Option.Or
Option.SomeOrDefault -> Option.OrElse
A few other useful variants in rust, that are similar to and and and_then:
Option.UnwrapOr
Option.UnwrapOrElse
Very nice.
In terms of naming, I find the rust naming convention to be fairly sensible.
Option.Intersect->Option.AndOption.SelectMany->Option.AndThenOption.Union->Option.OrOption.SomeOrDefault->Option.OrElseA few other useful variants in rust, that are similar to
andandand_then:Option.UnwrapOrOption.UnwrapOrElse
Sounds good, I've updated the naming scheme. Option.UnwrapOr is equivalent to Option.ValueOrDefault as far as I can tell; we could change the name to UnwrapOr if you like. I can add in Option.UnwrapOrElse too.