Skip to content

Commit

Permalink
1.0.1 Option.TryGet, Option.ToString
Browse files Browse the repository at this point in the history
  • Loading branch information
pimbrouwers committed Dec 1, 2024
1 parent 539296f commit a09ddf0
Show file tree
Hide file tree
Showing 15 changed files with 254 additions and 89 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ jobs:
dotnet-version: ${{ matrix.dotnet-version }}

- name: Install dependencies
run: dotnet restore test/Danom.Mvc.Tests
run: dotnet restore

- name: Build Core
run: dotnet build src/Danom -c Release

Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Changelog

All notable changes to this project will be documented in this file.

## [1.0.1] - 2024-12-01

### Added

- `Option<T>.TryGet(out T result)` to safely provide the internal value. A return value indicates whether or not the Option was Some(x) or None.
- `Option<T>.ToString(string defaultValue, string? format = null, IFormatProvider? provider = null)` to minimize code required to execute ToString against the inner value safely (i.e., replaces Map -> ToString -> DefaultValue chain).

## [1.0.0] - 2024-11-29

> Hello world!
64 changes: 64 additions & 0 deletions Danom.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{606C9E49-7696-48B1-A799-B456E680C9F0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Danom", "src\Danom\Danom.csproj", "{2E1327A1-9244-49BA-BC31-9CCE3CE2335C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{624FD20E-2393-4198-8DC9-AB02DCC12338}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Danom.Tests", "test\Danom.Tests\Danom.Tests.csproj", "{C364C599-3120-44EF-9D7C-81EF68072FB7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Danom.Validation", "src\Danom.Validation\Danom.Validation.csproj", "{6D32D457-228C-46BA-B94A-9FB4206BE460}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Danom.Validation.Tests", "test\Danom.Validation.Tests\Danom.Validation.Tests.csproj", "{A30031C7-1B82-4DFF-BEE7-31BE90BAC74A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Danom.Mvc", "src\Danom.Mvc\Danom.Mvc.csproj", "{C34292FD-E8B7-4214-9844-A653746C1AFF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Danom.Mvc.Tests", "test\Danom.Mvc.Tests\Danom.Mvc.Tests.csproj", "{EF188F59-5C11-4BAA-A965-56C08C370C84}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2E1327A1-9244-49BA-BC31-9CCE3CE2335C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2E1327A1-9244-49BA-BC31-9CCE3CE2335C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2E1327A1-9244-49BA-BC31-9CCE3CE2335C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2E1327A1-9244-49BA-BC31-9CCE3CE2335C}.Release|Any CPU.Build.0 = Release|Any CPU
{C364C599-3120-44EF-9D7C-81EF68072FB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C364C599-3120-44EF-9D7C-81EF68072FB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C364C599-3120-44EF-9D7C-81EF68072FB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C364C599-3120-44EF-9D7C-81EF68072FB7}.Release|Any CPU.Build.0 = Release|Any CPU
{6D32D457-228C-46BA-B94A-9FB4206BE460}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6D32D457-228C-46BA-B94A-9FB4206BE460}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6D32D457-228C-46BA-B94A-9FB4206BE460}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6D32D457-228C-46BA-B94A-9FB4206BE460}.Release|Any CPU.Build.0 = Release|Any CPU
{A30031C7-1B82-4DFF-BEE7-31BE90BAC74A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A30031C7-1B82-4DFF-BEE7-31BE90BAC74A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A30031C7-1B82-4DFF-BEE7-31BE90BAC74A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A30031C7-1B82-4DFF-BEE7-31BE90BAC74A}.Release|Any CPU.Build.0 = Release|Any CPU
{C34292FD-E8B7-4214-9844-A653746C1AFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C34292FD-E8B7-4214-9844-A653746C1AFF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C34292FD-E8B7-4214-9844-A653746C1AFF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C34292FD-E8B7-4214-9844-A653746C1AFF}.Release|Any CPU.Build.0 = Release|Any CPU
{EF188F59-5C11-4BAA-A965-56C08C370C84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EF188F59-5C11-4BAA-A965-56C08C370C84}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EF188F59-5C11-4BAA-A965-56C08C370C84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EF188F59-5C11-4BAA-A965-56C08C370C84}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{2E1327A1-9244-49BA-BC31-9CCE3CE2335C} = {606C9E49-7696-48B1-A799-B456E680C9F0}
{C364C599-3120-44EF-9D7C-81EF68072FB7} = {624FD20E-2393-4198-8DC9-AB02DCC12338}
{6D32D457-228C-46BA-B94A-9FB4206BE460} = {606C9E49-7696-48B1-A799-B456E680C9F0}
{A30031C7-1B82-4DFF-BEE7-31BE90BAC74A} = {624FD20E-2393-4198-8DC9-AB02DCC12338}
{C34292FD-E8B7-4214-9844-A653746C1AFF} = {606C9E49-7696-48B1-A799-B456E680C9F0}
{EF188F59-5C11-4BAA-A965-56C08C370C84} = {624FD20E-2393-4198-8DC9-AB02DCC12338}
EndGlobalSection
EndGlobal
2 changes: 1 addition & 1 deletion src/Danom/Danom.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<AssemblyName>Danom</AssemblyName>
<Version>1.0.0</Version>
<Version>1.0.1</Version>

<!-- General info -->
<Description>Monadic structures to simplify functional programming patterns in C#.</Description>
Expand Down
45 changes: 42 additions & 3 deletions src/Danom/Option/Option.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,22 @@ public Option<T> OrElseWith(
Func<Option<T>> ifNoneWith) =>
Match(Option<T>.Some, ifNoneWith);

/// <summary>
/// Safely retrieve the value using procedural code.
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
public bool TryGet(out T result)
{
var success = true;
result = DefaultWith(() =>
{
success = false;
// we return this only to satisfy the compiler
return default!;
});
return success;
}

/// <summary>
/// Creates a new <see cref="Option{T}"/> with the specified value.
Expand Down Expand Up @@ -214,6 +230,28 @@ public override string ToString() =>
Match(
some: x => $"Some({x})",
none: () => "None");

/// <summary>
/// Returns the string representation of the <see cref="Option{T}"/> or the
/// provided default value.
///
/// If format string and/or provider are provided, they are passed into
/// the objects `ToString` method.
/// </summary>
/// <param name="defaultValue"></param>
/// <param name="format"></param>
/// <param name="provider"></param>
/// <returns></returns>
public string ToString(
string defaultValue,
string? format = null,
IFormatProvider? provider = null) =>
Match(
some: x =>
x is IFormattable f ?
f!.ToString(format, provider) :
x!.ToString(),
none: () => defaultValue) ?? string.Empty;
}

/// <summary>
Expand All @@ -222,7 +260,8 @@ public override string ToString() =>
public static class Option
{
/// <summary>
/// Creates a new <see cref="Option{T}"/> with the specified value.
/// Creates a new <see cref="Option{T}"/> with the specified value, with its
/// type provided via method invocation. Enables `Option.Some(1)` syntax.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
Expand All @@ -235,13 +274,13 @@ public static Option<T> Some<T>(T value) =>
/// <param name="value"></param>
/// <returns></returns>
public static Task<Option<T>> SomeAsync<T>(T value) =>
Task.FromResult(Some(value));
Task.FromResult(Option<T>.Some(value));

/// <summary>
/// Creates a new <see cref="Option{T}"/> with the value of the awaited Task.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static async Task<Option<T>> SomeAsync<T>(Task<T> value) =>
Some(await value);
Option<T>.Some(await value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ internal static void AddResultErrors(
public sealed class ModelStateDictionaryExtensionsTests
{
[Fact]
public void AddResultErrorsShouldWork()
public void AddResultErrors()
{
var modelState = new ModelStateDictionary();
var errors = new ResultErrors("Key1", "Error1");
Expand Down
2 changes: 1 addition & 1 deletion test/Danom.Tests/Option/OptionNullableTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Danom.Tests;
public sealed class OptionNullableExtensionsTests
{
[Fact]
public void ConversionsShouldWork()
public void Conversions()
{
char? nullableChar = null;
bool? nullableBool = null;
Expand Down
14 changes: 7 additions & 7 deletions test/Danom.Tests/Option/OptionTaskTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Danom.Tests;
public sealed class OptionAsyncTests
{
[Fact]
public async Task MatchShouldWork()
public async Task Match()
{
var optionSome = await Option<int>.SomeAsync(1).MatchAsync(x => x, () => -1);
Assert.Equal(1, optionSome);
Expand All @@ -16,7 +16,7 @@ public async Task MatchShouldWork()
}

[Fact]
public async Task BindShouldWork()
public async Task Bind()
{
AssertOption.IsSome(2, await Option<int>.SomeAsync(1).BindAsync(x => Option<int>.Some(x + 1)));
AssertOption.IsSome(2, await Option<int>.SomeAsync(1).BindAsync(x => Option<int>.SomeAsync(x + 1)));
Expand All @@ -25,7 +25,7 @@ public async Task BindShouldWork()
}

[Fact]
public async Task MapShouldWork()
public async Task Map()
{
AssertOption.IsSome(2, await Option<int>.SomeAsync(1).MapAsync(x => x + 1));
AssertOption.IsSome(2, await Option<int>.SomeAsync(1).MapAsync(x => Task.FromResult(x + 1)));
Expand All @@ -34,7 +34,7 @@ public async Task MapShouldWork()
}

[Fact]
public async Task DefaultValueShouldWork()
public async Task DefaultValue()
{
Assert.Equal(1, await Option<int>.NoneAsync().DefaultValueAsync(1));
Assert.Equal(1, await Option<int>.NoneAsync().DefaultValueAsync(Task.FromResult(1)));
Expand All @@ -43,7 +43,7 @@ public async Task DefaultValueShouldWork()
}

[Fact]
public async Task DefaultWithShouldWork()
public async Task DefaultWith()
{
Assert.Equal(1, await Option<int>.NoneAsync().DefaultWithAsync(() => 1));
Assert.Equal(1, await Option<int>.NoneAsync().DefaultWithAsync(() => Task.FromResult(1)));
Expand All @@ -52,7 +52,7 @@ public async Task DefaultWithShouldWork()
}

[Fact]
public async Task OrElseShouldWork()
public async Task OrElse()
{
AssertOption.IsSome(1, await Option<int>.NoneAsync().OrElseAsync(Option<int>.Some(1)));
AssertOption.IsSome(1, await Option<int>.NoneAsync().OrElseAsync(Option<int>.SomeAsync(1)));
Expand All @@ -61,7 +61,7 @@ public async Task OrElseShouldWork()
}

[Fact]
public async Task OrElseWithShouldWork()
public async Task OrElseWith()
{
AssertOption.IsSome(1, await Option<int>.NoneAsync().OrElseWithAsync(() => Option<int>.Some(1)));
AssertOption.IsSome(1, await Option<int>.NoneAsync().OrElseWithAsync(() => Option<int>.SomeAsync(1)));
Expand Down
Loading

0 comments on commit a09ddf0

Please sign in to comment.