Skip to content

Commit 0cd5f0b

Browse files
authored
Support for void-returning Match (#6)
* Support for void-returning Match * Fixing unit test
1 parent aae7887 commit 0cd5f0b

File tree

7 files changed

+68
-5
lines changed

7 files changed

+68
-5
lines changed

src/RustyOptions.Tests/OptionTests.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,19 @@ public void CanMatch()
8383
Assert.Equal("empty", noneResult);
8484
}
8585

86+
[Fact]
87+
public void CanMatchWithSideEffects()
88+
{
89+
var someInt = Some(42);
90+
var noneInt = None<int>();
91+
92+
int output = 0;
93+
someInt.Match(x => { output += x; }, () => { output -= 1; });
94+
Assert.Equal(42, output);
95+
noneInt.Match(x => { output += x; }, () => { output -= 1; });
96+
Assert.Equal(41, output);
97+
}
98+
8699
[Fact]
87100
public void CanGetSpan()
88101
{

src/RustyOptions.Tests/ResultTests.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,19 @@ public void CanMatch()
9191
Assert.Equal(-1, errResult);
9292
}
9393

94+
[Fact]
95+
public void CanMatchWithSideEffects()
96+
{
97+
var ok = Ok(42);
98+
var err = Err<int>("oops");
99+
100+
int output = 0;
101+
ok.Match(x => output += x, e => { if (e == "oops") { output -= 1; } });
102+
Assert.Equal(42, output);
103+
err.Match(x => output += x, e => { if (e == "oops") { output -= 1; } });
104+
Assert.Equal(41, output);
105+
}
106+
94107
[Fact]
95108
public void CanUnwrap()
96109
{

src/RustyOptions.Tests/RustyOptions.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<LangVersion>11</LangVersion>
99
<IsPackable>false</IsPackable>
1010
<AssemblyName>RustyOptions.Tests</AssemblyName>
11+
<ReleaseVersion>0.2</ReleaseVersion>
1112
</PropertyGroup>
1213

1314
<ItemGroup>

src/RustyOptions.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@ Global
3434
EndGlobalSection
3535
GlobalSection(MonoDevelopProperties) = preSolution
3636
description = Option and Result types for C#, inspired by Rust
37+
version = 0.2
3738
EndGlobalSection
3839
EndGlobal

src/RustyOptions/Option.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
namespace RustyOptions;
77

8-
// TODO: Match that returns void?
98
// TODO: OptionNumber that implements INumber?
109
// TODO: Async?
1110

@@ -66,8 +65,8 @@ public bool IsSome([MaybeNullWhen(false)] out T value)
6665
/// of the <see cref="Option{T}"/>.
6766
/// </summary>
6867
/// <typeparam name="T2">The return type of the given functions.</typeparam>
69-
/// <param name="onSome">The function to pass the value to, if the result is <c>Ok</c>.</param>
70-
/// <param name="onNone">The function to pass the error value to, if the result is <c>Err</c>.</param>
68+
/// <param name="onSome">The function to pass the value to, if the option is <c>Some</c>.</param>
69+
/// <param name="onNone">The function to call if the option is <c>None</c>.</param>
7170
/// <returns>The value returned by the called function.</returns>
7271
/// <exception cref="System.ArgumentNullException">Thrown if either <paramref name="onSome"/> or <paramref name="onNone"/> is null.</exception>
7372
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -78,6 +77,24 @@ public T2 Match<T2>(Func<T, T2> onSome, Func<T2> onNone)
7877
return _isSome ? onSome(_value) : onNone();
7978
}
8079

80+
/// <summary>
81+
/// If the option is <c>Some</c>, passes the contained value to the <paramref name="onSome"/> function.
82+
/// Otherwise calls the <paramref name="onNone"/> function.
83+
/// </summary>
84+
/// <param name="onSome">The function to call with the contained <c>Some</c> value, if any.</param>
85+
/// <param name="onNone">The function to call if the option is <c>None</c>.</param>
86+
/// <exception cref="System.ArgumentNullException">Thrown if either <paramref name="onSome"/> or <paramref name="onNone"/> is null.</exception>
87+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
88+
public void Match(Action<T> onSome, Action onNone)
89+
{
90+
ThrowIfNull(onSome);
91+
ThrowIfNull(onNone);
92+
if (_isSome)
93+
onSome(_value);
94+
else
95+
onNone();
96+
}
97+
8198
/// <summary>
8299
/// Returns the contained <c>Some</c> value, or throws an <see cref="InvalidOperationException"/>
83100
/// if the value is <c>None</c>.

src/RustyOptions/Result.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
namespace RustyOptions;
77

8-
// TODO: Match overload that returns void (for side effects)?
98
// TODO: ResultNumber that implement INumber?
109
// TODO: Async?
1110

@@ -88,6 +87,24 @@ public T2 Match<T2>(Func<T, T2> onOk, Func<TErr, T2> onErr)
8887
ThrowIfNull(onOk);
8988
ThrowIfNull(onErr);
9089
return _isOk ? onOk(_value) : onErr(_err);
90+
}
91+
92+
/// <summary>
93+
/// Calls the <paramref name="onOk"/> with the <c>Ok</c> value, or calls <paramref name="onErr"/>
94+
/// with the <c>Err</c> value, as appropriate.
95+
/// </summary>
96+
/// <param name="onOk">The function to pass the value to, if the result is <c>Ok</c>.</param>
97+
/// <param name="onErr">The function to pass the error value to, if the result is <c>Err</c>.</param>
98+
/// <exception cref="System.ArgumentNullException">Thrown if either <paramref name="onOk"/> or <paramref name="onErr"/> is null.</exception>
99+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
100+
public void Match(Action<T> onOk, Action<TErr> onErr)
101+
{
102+
ThrowIfNull(onOk);
103+
ThrowIfNull(onErr);
104+
if (_isOk)
105+
onOk(_value);
106+
else
107+
onErr(_err);
91108
}
92109

93110
/// <summary>

src/RustyOptions/RustyOptions.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77
<AnalysisMode>Recommended</AnalysisMode>
88
<LangVersion>11</LangVersion>
99
<AssemblyName>RustyOptions</AssemblyName>
10-
<Version>0.1.0</Version>
10+
<Version>0.2.0</Version>
1111
<PackageId>RustyOptions</PackageId>
1212
<Authors>Joel Mueller</Authors>
1313
<Company></Company>
1414
<PackageDescription>Option and Result types for C#, inspired by Rust</PackageDescription>
1515
<RepositoryType>git</RepositoryType>
1616
<RepositoryUrl>https://github.com/jtmueller/RustyOptions</RepositoryUrl>
1717
<PackageLicenseExpression>MIT</PackageLicenseExpression>
18+
<ReleaseVersion>0.2</ReleaseVersion>
1819
</PropertyGroup>
1920

2021
<PropertyGroup Condition=" '$(Configuration)|$(TargetFramework)' == 'Debug|net6.0' ">

0 commit comments

Comments
 (0)