Skip to content

Commit

Permalink
#36 - Started adding cons pattern matching.
Browse files Browse the repository at this point in the history
This is taking a TDD approach, so code is currently written to make the tests pass and needs refactoring.
  • Loading branch information
DavidArno committed May 30, 2017
1 parent ac60a5d commit 03fa602
Show file tree
Hide file tree
Showing 9 changed files with 180 additions and 2 deletions.
13 changes: 13 additions & 0 deletions src/SuccincT/PatternMatchers/ConsActionMatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Collections.Generic;

namespace SuccincT.PatternMatchers
{
internal class ConsActionMatcher<T> : IConsActionMatcher<T>
{
private readonly IEnumerable<T> _collection;

public ConsActionMatcher(IEnumerable<T> collection) => _collection = collection;

public IConsFuncMatcher<T, TResult> To<TResult>() => new ConsFuncMatcher<T, TResult>(_collection);
}
}
63 changes: 63 additions & 0 deletions src/SuccincT/PatternMatchers/ConsFuncMatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace SuccincT.PatternMatchers
{
internal class ConsFuncMatcher<T, TResult> : IConsFuncMatcher<T, TResult>,
IConsFuncNoneHandler<T, TResult>,
IConsFuncSingleHandler<T, TResult>,
IConsFuncSingleWhereHandler<T, TResult>
{
private readonly IEnumerable<T> _collection;
private TResult _emptyValue;
private Func<T, bool> _whereFunc;
private List<(Func<T, bool> testFunc, TResult value)> _singleTests;

internal ConsFuncMatcher(IEnumerable<T> collection)
{
_collection = collection;
_singleTests = new List<(Func<T, bool> testFunc, TResult value)>();
}

IConsFuncNoneHandler<T, TResult> IConsFuncMatcher<T, TResult>.Empty() => this;
IConsFuncSingleHandler<T, TResult> IConsFuncMatcher<T, TResult>.Single() => this;

TResult IConsFuncMatcher<T, TResult>.Result() => _collection.Count() == 0 ? _emptyValue : SingleMatch();

IConsFuncMatcher<T, TResult> IConsFuncNoneHandler<T, TResult>.Do(TResult value)
{
_emptyValue = value;
return this;
}

IConsFuncMatcher<T, TResult> IConsFuncSingleHandler<T, TResult>.Do(TResult value)
{
_singleTests.Add((x => true, value));
return this;
}

IConsFuncSingleWhereHandler<T, TResult> IConsFuncSingleHandler<T, TResult>.Where(Func<T, bool> testFunc)
{
_whereFunc = testFunc;
return this;
}

IConsFuncMatcher<T, TResult> IConsFuncSingleWhereHandler<T, TResult>.Do(TResult value)
{
_singleTests.Add((_whereFunc, value));
return this;
}
private TResult SingleMatch()
{
foreach(var (testFunc, value) in _singleTests)
{
if (testFunc(_collection.First()))
{
return value;
}
}
return default(TResult);
}
}
}
7 changes: 7 additions & 0 deletions src/SuccincT/PatternMatchers/IConsActionMatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace SuccincT.PatternMatchers
{
public interface IConsActionMatcher<T>
{
IConsFuncMatcher<T, TResult> To<TResult>();
}
}
11 changes: 11 additions & 0 deletions src/SuccincT/PatternMatchers/IConsFuncMatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace SuccincT.PatternMatchers
{
public interface IConsFuncMatcher<T, TResult>
{
IConsFuncNoneHandler<T, TResult> Empty();

IConsFuncSingleHandler<T, TResult> Single();

TResult Result();
}
}
7 changes: 7 additions & 0 deletions src/SuccincT/PatternMatchers/IConsFuncNoneHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace SuccincT.PatternMatchers
{
public interface IConsFuncNoneHandler<T, TResult>
{
IConsFuncMatcher<T, TResult> Do(TResult value);
}
}
7 changes: 7 additions & 0 deletions src/SuccincT/PatternMatchers/IConsFuncSingleWhereHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace SuccincT.PatternMatchers
{
public interface IConsFuncSingleWhereHandler<T, TResult>
{
IConsFuncMatcher<T, TResult> Do(TResult value);
}
}
11 changes: 11 additions & 0 deletions src/SuccincT/PatternMatchers/IConsSingleHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;

namespace SuccincT.PatternMatchers
{
public interface IConsFuncSingleHandler<T, TResult>
{
IConsFuncMatcher<T, TResult> Do(TResult value);

IConsFuncSingleWhereHandler<T, TResult> Where(Func<T, bool> testFunc);
}
}
8 changes: 6 additions & 2 deletions src/SuccincT/PatternMatchers/SpecificTypeMatcherExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using System;
using System.Collections.Generic;
using SuccincT.Functional;
using SuccincT.Tuples;

namespace SuccincT.PatternMatchers
{
/// <summary>
/// Defines extension methods for supplying Match() to specific types. Due to the way extension methods are resolved
/// by the compiler, these are placed "closer" to the calling code (ie with a shorter namespace) than the general
/// by the compiler, these are placed "closer" to the calling code (ie with a shorter namespace) than the general
/// type extension method to ensure these are chosen in preference to the general one.
/// </summary>
public static class SpecificTypeMatcherExtensions
Expand Down Expand Up @@ -49,9 +50,12 @@ public static IMatcher<T1, T2, T3, T4> Match<T1, T2, T3, T4>(this ITupleMatchabl
return new Matcher<T1, T2, T3, T4, Unit>(tuple);
}

public static IConsActionMatcher<T> Match<T>(this IEnumerable<T> collection) => new ConsActionMatcher<T>(collection);


private static (T1, T2) AsTuple<T1, T2>(this Tuple<T1, T2> value) => (value.Item1, value.Item2);

private static (T1, T2, T3) AsTuple<T1, T2, T3>(this Tuple<T1, T2, T3> value) =>
private static (T1, T2, T3) AsTuple<T1, T2, T3>(this Tuple<T1, T2, T3> value) =>
(value.Item1, value.Item2, value.Item3);

private static (T1, T2, T3, T4) AsTuple<T1, T2, T3, T4>(this Tuple<T1, T2, T3, T4> value) =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System.Collections.Generic;
using NUnit.Framework;
using SuccincT.PatternMatchers;
using static NUnit.Framework.Assert;

namespace SuccincTTests.SuccincT.PatternMatchers
{
[TestFixture]
public class ConsFuncMatcherTests
{
[Test]
public void EmptyList_CanBeMatchedWithEmpty()
{
var list = new List<int>();
var result = list.Match().To<int>()
.Empty().Do(0)
.Single().Do(1)
.Result();
AreEqual(0, result);
}

[Test]
public void SingleItemList_CanBeMatchedWithSingle()
{
var list = new List<int> { 1 };
var result = list.Match().To<bool>()
.Empty().Do(false)
.Single().Do(true)
.Result();
IsTrue(result);
}

[Test]
public void SingleItemList_CanBeMatchedWithWhere()
{
var list = new List<int> { 1 };
var result = list.Match().To<bool>()
.Single().Where(x => x == 1).Do(true)
.Single().Do(false)
.Result();
IsTrue(result);
}

[Test]
public void SingleItemList_CanBeMatchedWhenWhereDoesntMatch()
{
var list = new List<int> { 0 };
var result = list.Match().To<bool>()
.Single().Where(x => x == 1).Do(true)
.Single().Do(false)
.Result();
IsFalse(result);
}
}
}

0 comments on commit 03fa602

Please sign in to comment.