Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add additional Option methods #98

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

alberdingk-thijm
Copy link
Contributor

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 to Enumerable.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 of Enumerable.Concat over 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.Bind or Option.AndThen
  • Option.SomeOrDefault --> Option.Concat or Option.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.

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 to `Enumerable.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 of `Enumerable.Concat` over 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.Bind or Option.AndThen
* Option.SomeOrDefault --> Option.Concat or Option.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).
@alberdingk-thijm
Copy link
Contributor Author

@rabeckett Feel free to suggest alternative names. One option (ha ha) is to stick very closely to System.Linq.Enumerable.

  • Option.Intersect for the "and" of two Options. A bit unclear as a name perhaps, since two Option.Somes with different values don't produce Option.None: Option.Some(3).Intersect(Option.Some(1)) == Option.Some(1).
  • Option.Union for the "or" of two Options. Again, a similar problem to Option.Intersect, as "union" does not suggest that, when given two Option.Somes, the result is the first value: Option.Some(3).Union(Option.Some(1)) == Option.Some(3).
  • Option.Concat instead of Option.SomeOrDefault. Somewhat intuitive since it respects the fact that Enumerable.Empty is an identity: Enumerable.Empty<int>().Concat(enumerable) == enumerable and Option.None<int>().Concat(thunk()) == thunk(). On the other hand, SomeOrDefault tells you more about what it actually does.
  • Option.SelectMany for 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.

@rabeckett
Copy link
Member

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

Names of new Option methods now match those used by Rust,
i.e. Option.Or, Option.OrElse, Option.And, Option.AndThen.
@alberdingk-thijm
Copy link
Contributor Author

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

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants