diff --git a/README.md b/README.md index e0942db..923753b 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ An auxiliary namespace is also provided: using Optuple.Linq; // LINQ query syntax support ``` + ### Creating optional values The most basic way to create optional values is to use the static `Option` @@ -165,6 +166,25 @@ var stillSome = some.Filter(x => x == 10); var none = some.Filter(x => x != 10); ``` +### Helpers as global methods + +If you [statically import][static-using] `OptionModule`: + +```c# +using static Optuple.OptionModule; +``` + +it will make the following common methods available for use without type +qualification: + +- `Some` +- `None<>` +- `SomeWhen` +- `NoneWhen` + +This permits you to, for example, simply write `Some(42)` and `None()` +instead of `Option.Some(42)` and `None()`, respectively. + ### Enumerating options [comment]: # (Move somewhere?!) @@ -218,3 +238,4 @@ project [Optional]. Thank you, [Nils Lück][nlkl]! [Optional]: https://www.nuget.org/packages/Optional/ [nlkl]: https://github.com/nlkl +[static-using]: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-static diff --git a/src/Option.cs b/src/Option.cs index a650ea6..0b7167b 100644 --- a/src/Option.cs +++ b/src/Option.cs @@ -19,6 +19,18 @@ namespace Optuple using System; using System.Collections.Generic; + static partial class OptionModule + { + public static (bool HasValue, T Value) Some(T value) => Option.Some(value); + public static (bool HasValue, T Value) None() => Option.None(); + + public static (bool HasValue, T Value) SomeWhen(T value, Func predicate) => + Option.SomeWhen(value, predicate); + + public static (bool HasValue, T Value) NoneWhen(T value, Func predicate) => + Option.NoneWhen(value, predicate); + } + static partial class Option { public static (bool HasValue, T Value) Some(T value) => (true, value); diff --git a/src/Public.cs b/src/Public.cs index 9deb880..ad4027e 100644 --- a/src/Public.cs +++ b/src/Public.cs @@ -1,6 +1,7 @@ namespace Optuple { public partial class Option {} + public partial class OptionModule {} namespace Linq { diff --git a/tests/OptionTests.cs b/tests/OptionTests.cs index f915953..ac2a3a8 100644 --- a/tests/OptionTests.cs +++ b/tests/OptionTests.cs @@ -3,14 +3,15 @@ namespace Optuple.Tests using System; using NUnit.Framework; using _ = System.Object; + using static OptionModule; [TestFixture] public class OptionTests { [Test] - public void Some() + public void SomeValue() { - var (t, x) = Option.Some(42); + var (t, x) = Some(42); Assert.That(t, Is.True); Assert.That(x, Is.EqualTo(42)); } @@ -18,7 +19,7 @@ public void Some() [Test] public void SomeNullReference() { - var (t, x) = Option.Some((object) null); + var (t, x) = Some((object) null); Assert.That(t, Is.True); Assert.That(x, Is.Null); } @@ -26,7 +27,7 @@ public void SomeNullReference() [Test] public void SomeNullValue() { - var (t, x) = Option.Some((int?) null); + var (t, x) = Some((int?) null); Assert.That(t, Is.True); Assert.That(x, Is.Null); } @@ -34,7 +35,7 @@ public void SomeNullValue() [Test] public void None() { - var (t, x) = Option.None(); + var (t, x) = None(); Assert.That(t, Is.False); Assert.That(x, Is.Zero); } @@ -42,28 +43,28 @@ public void None() [Test] public void IsSome() { - var result = Option.Some(42); + var result = Some(42); Assert.That(result.IsSome(), Is.True); } [Test] public void SomeIsNotNone() { - var result = Option.Some(42); + var result = Some(42); Assert.That(result.IsNone(), Is.False); } [Test] public void IsNone() { - var result = Option.None(); + var result = None(); Assert.That(result.IsNone(), Is.True); } [Test] public void NoneIsNotSome() { - var result = Option.None(); + var result = None(); Assert.That(result.IsSome(), Is.False); } @@ -72,7 +73,7 @@ public void ToOptionWithNullableNonNull() { int? i = 42; var result = i.ToOption(); - Assert.That(result, Is.EqualTo(Option.Some(42))); + Assert.That(result, Is.EqualTo(Some(42))); } [Test] @@ -80,65 +81,65 @@ public void ToOptionWithNullableNull() { int? i = null; var result = i.ToOption(); - Assert.That(result, Is.EqualTo(Option.None())); + Assert.That(result, Is.EqualTo(None())); } [Test] public void From() { var result = Option.From(true, 42); - Assert.That(result, Is.EqualTo(Option.Some(42))); + Assert.That(result, Is.EqualTo(Some(42))); } [Test] public void FromNone() { var result = Option.From(false, 42); - Assert.That(result, Is.EqualTo(Option.None())); + Assert.That(result, Is.EqualTo(None())); } [Test] public void SomeWhenWithNullPredicate() { var e = Assert.Throws(() => - Option.SomeWhen(42, null)); + SomeWhen(42, null)); Assert.That(e.ParamName, Is.EqualTo("predicate")); } [Test] public void SomeWhenWithTrueCondition() { - var result = Option.SomeWhen(42, n => n > 0); - Assert.That(result, Is.EqualTo(Option.Some(42))); + var result = SomeWhen(42, n => n > 0); + Assert.That(result, Is.EqualTo(Some(42))); } [Test] public void SomeWhenWithFalseCondition() { - var result = Option.SomeWhen(42, n => n < 0); - Assert.That(result, Is.EqualTo(Option.None())); + var result = SomeWhen(42, n => n < 0); + Assert.That(result, Is.EqualTo(None())); } [Test] public void NoneWhenWithNullPredicate() { var e = Assert.Throws(() => - Option.NoneWhen(42, null)); + NoneWhen(42, null)); Assert.That(e.ParamName, Is.EqualTo("predicate")); } [Test] public void NoneWhenNullableIsNonNull() { - var result = Option.NoneWhen(42, n => n < 0); - Assert.That(result, Is.EqualTo(Option.Some(42))); + var result = NoneWhen(42, n => n < 0); + Assert.That(result, Is.EqualTo(Some(42))); } [Test] public void NoneWhenNullableIsNull() { - var result = Option.NoneWhen(42, n => n > 0); - Assert.That(result, Is.EqualTo(Option.None())); + var result = NoneWhen(42, n => n > 0); + Assert.That(result, Is.EqualTo(None())); } [TestCase(true, 42)] @@ -162,7 +163,7 @@ public void MatchWithNullNoneFunction(bool f, int v) [Test] public void MatchSome() { - var some = Option.Some(3); + var some = Some(3); var result = some.Match(i => "foobar".Substring(i), () => "none"); Assert.That(result, Is.EqualTo("bar")); } @@ -170,7 +171,7 @@ public void MatchSome() [Test] public void MatchNone() { - var none = Option.None(); + var none = None(); var result = none.Match(i => "foobar".Substring(i), () => "foobar"); Assert.That(result, Is.EqualTo("foobar")); } @@ -196,14 +197,14 @@ public void MatchWithNullNoneAction(bool f, int v) [Test] public void MatchSomeWithAction() { - var some = Option.Some(42); + var some = Some(42); some.Match(x => Assert.That(x, Is.EqualTo(42)), Assert.Fail); } [Test] public void MatchNoneWithAction() { - var none = Option.None(); + var none = None(); none.Match(x => Assert.Fail(), Assert.Pass); } @@ -219,7 +220,7 @@ public void DoWithNullAction(bool f, int v) [Test] public void DoSome() { - var some = Option.Some(42); + var some = Some(42); var result = 0; some.Do(x => result = x); Assert.That(result, Is.EqualTo(42)); @@ -228,7 +229,7 @@ public void DoSome() [Test] public void DoNone() { - var none = Option.None(); + var none = None(); none.Do(x => Assert.Fail()); Assert.Pass(); } @@ -245,17 +246,17 @@ public void BindWithNullFunction(bool f, int v) [Test] public void BindSome() { - var some = Option.Some(3); - var result = some.Bind(i => Option.Some("foobar".Substring(i))); - Assert.That(result, Is.EqualTo(Option.Some("bar"))); + var some = Some(3); + var result = some.Bind(i => Some("foobar".Substring(i))); + Assert.That(result, Is.EqualTo(Some("bar"))); } [Test] public void BindNone() { - var none = Option.None(); - var result = none.Bind(i => Option.Some("foobar".Substring(i))); - Assert.That(result, Is.EqualTo(Option.None())); + var none = None(); + var result = none.Bind(i => Some("foobar".Substring(i))); + Assert.That(result, Is.EqualTo(None())); } [TestCase(true, 42)] @@ -270,72 +271,72 @@ public void MapWithNullMapper(bool f, int v) [Test] public void MapSome() { - var some = Option.Some(42); + var some = Some(42); var result = some.Map(n => new string((char) n, n)); var stars = new string('*', 42); - Assert.That(result, Is.EqualTo(Option.Some(stars))); + Assert.That(result, Is.EqualTo(Some(stars))); } [Test] public void MapNone() { - var none = Option.None(); + var none = None(); var result = none.Map(n => new string((char) n, n)); - Assert.That(result, Is.EqualTo(Option.None())); + Assert.That(result, Is.EqualTo(None())); } [Test] public void GetSome() { - var some = Option.Some(42); + var some = Some(42); Assert.That(some.Get(), Is.EqualTo(42)); } [Test] public void GetNone() { - var none = Option.None(); + var none = None(); Assert.Throws(() => none.Get()); } [Test] public void OrDefaultSome() { - var some = Option.Some(42); + var some = Some(42); Assert.That(some.OrDefault(), Is.EqualTo(42)); } [Test] public void OrDefaultNone() { - var none = Option.None(); + var none = None(); Assert.That(none.OrDefault(), Is.Zero); } [Test] public void OrSome() { - var some = Option.Some(42); + var some = Some(42); Assert.That(some.Or(-42), Is.EqualTo(42)); } [Test] public void OrNone() { - var none = Option.None(); + var none = None(); Assert.That(none.Or(42), Is.EqualTo(42)); } [Test] public void CountSome() { - Assert.That(Option.Some(42).Count(), Is.EqualTo(1)); + Assert.That(Some(42).Count(), Is.EqualTo(1)); } [Test] public void CountNone() { - Assert.That(Option.None().Count(), Is.Zero); + Assert.That(None().Count(), Is.Zero); } [TestCase(true, 42)] @@ -350,7 +351,7 @@ public void ExistsWithNullPredicate(bool f, int v) [Test] public void ExistsSome() { - var some = Option.Some(42); + var some = Some(42); Assert.That(some.Exists(x => x > 0), Is.True); Assert.That(some.Exists(x => x < 0), Is.False); } @@ -358,7 +359,7 @@ public void ExistsSome() [Test] public void ExistsNone() { - var some = Option.None(); + var some = None(); Assert.That(some.Exists(x => x < 0), Is.False); Assert.That(some.Exists(x => x > 0), Is.False); } @@ -375,17 +376,17 @@ public void FilterWithNullPredicate(bool f, int v) [Test] public void FilterSome() { - var some = Option.Some(42); + var some = Some(42); var result1 = some.Filter(x => x > 0); var result2 = some.Filter(x => x < 0); Assert.That(result1, Is.EqualTo(some)); - Assert.That(result2, Is.EqualTo(Option.None())); + Assert.That(result2, Is.EqualTo(None())); } [Test] public void FilterNone() { - var none = Option.None(); + var none = None(); var result1 = none.Filter(x => x > 42); var result2 = none.Filter(x => x < 42); Assert.That(result1, Is.EqualTo(none)); @@ -395,7 +396,7 @@ public void FilterNone() [Test] public void ToNullableSome() { - var some = Option.Some(42); + var some = Some(42); var result = some.ToNullable(); Assert.That(result, Is.EqualTo(42)); } @@ -403,7 +404,7 @@ public void ToNullableSome() [Test] public void ToNullableNone() { - var none = Option.None(); + var none = None(); var result = none.ToNullable(); Assert.That(result, Is.Null); } @@ -431,9 +432,9 @@ static void EqualTo((bool, T) left, (bool, T) right) [Test] public void ValueTypes() { - var none = Option.None(); - var some1 = Option.Some(1); - var some2 = Option.Some(2); + var none = None(); + var some1 = Some(1); + var some2 = Some(2); LessThan(none, some1); LessThan(some1, some2); @@ -445,10 +446,10 @@ public void ValueTypes() [Test] public void Comparables() { - var none = Option.None(); - var someNull = Option.Some(null); - var some1 = Option.Some("1"); - var some2 = Option.Some("2"); + var none = None(); + var someNull = Some(null); + var some1 = Some("1"); + var some2 = Some("2"); LessThan(none, some1); LessThan(none, someNull); @@ -463,10 +464,10 @@ public void Comparables() [Test] public void NonComparables() { - var none = Option.None(); - var someNull = Option.Some(null); - var some1 = Option.Some(new object()); - var some2 = Option.Some(new object()); + var none = None(); + var someNull = Some(null); + var some1 = Some(new object()); + var some2 = Some(new object()); Assert.Throws(() => some1.CompareTo(some2)); Assert.Throws(() => some2.CompareTo(some1));