Last active
August 29, 2015 14:03
-
-
Save Novakov/4dbbe4a6d97a4499ea62 to your computer and use it in GitHub Desktop.
Having fun with collection initializer in C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace PatternMatch | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var matcher = new Pattern<string, string> | |
{ | |
{ | |
s => s.StartsWith("S"), s => "String starts with S" | |
}, | |
{ | |
s => s.StartsWith("E"), s => "String starts with E" | |
}, | |
s => "Another string" | |
}; | |
Console.WriteLine(matcher.Match("Start")); | |
Console.WriteLine(matcher.Match("Ending")); | |
Console.WriteLine(matcher.Match("Other")); | |
Console.WriteLine(); | |
Console.WriteLine("Space" | matcher); | |
Console.WriteLine(); | |
var range = new FuncPredicate<int>(i => 6 <= i && i <= 8); | |
for (int input = 0; input <= 10; input++) | |
{ | |
Console.WriteLine(input | new Pattern<int, string> | |
{ | |
{range, "In range <6,8>"}, | |
{5, "Five"}, | |
{10, i => "Got value of ten! Proof:" + 10}, | |
{i => i%2 == 0, "Odd"}, | |
{i => i%2 == 1, "Even"}, | |
}); | |
} | |
} | |
} | |
public class Pattern<TInput, TOutput> : IEnumerable | |
{ | |
private readonly List<Tuple<Predicate<TInput>, Func<TInput, TOutput>>> clauses; | |
public Pattern() | |
{ | |
this.clauses = new List<Tuple<Predicate<TInput>, Func<TInput, TOutput>>>(); | |
} | |
public void Add(Predicate<TInput> predicate, Func<TInput, TOutput> action) | |
{ | |
this.clauses.Add(Tuple.Create(predicate, action)); | |
} | |
public void Add(Func<TInput, bool> predicate, Func<TInput, TOutput> action) | |
{ | |
this.Add((Predicate<TInput>)predicate, action); | |
} | |
public void Add(Func<TInput, TOutput> defaultAction) | |
{ | |
this.Add(_ => true, defaultAction); | |
} | |
public void Add(Func<TInput, bool> predicate, TOutput value) | |
{ | |
this.Add(predicate, _ => value); | |
} | |
public void Add(Predicate<TInput> predicate, TOutput value) | |
{ | |
this.Add(predicate, _ => value); | |
} | |
public void Add(TOutput value) | |
{ | |
this.Add(_ => value); | |
} | |
public void Add(IEquatable<TInput> sample, Func<TInput, TOutput> value) | |
{ | |
this.Add(new SamplePredicate<TInput>(sample), value); | |
} | |
public void Add(IEquatable<TInput> sample, TOutput value) | |
{ | |
this.Add(sample, _ => value); | |
} | |
IEnumerator IEnumerable.GetEnumerator() | |
{ | |
throw new NotImplementedException(); | |
} | |
public TOutput Match(TInput input) | |
{ | |
var clause = this.clauses.FirstOrDefault(x => x.Item1.Matches(input)); | |
if (clause != null) | |
{ | |
return clause.Item2(input); | |
} | |
throw new InvalidOperationException("No clause matches"); | |
} | |
public static TOutput operator |(TInput input, Pattern<TInput, TOutput> pattern) | |
{ | |
return pattern.Match(input); | |
} | |
} | |
public abstract class Predicate<T> | |
{ | |
public abstract bool Matches(T value); | |
public static implicit operator Predicate<T>(Func<T, bool> func) | |
{ | |
return new FuncPredicate<T>(func); | |
} | |
} | |
public class FuncPredicate<T> : Predicate<T> | |
{ | |
private readonly Func<T, bool> predicate; | |
public FuncPredicate(Func<T, bool> predicate) | |
{ | |
this.predicate = predicate; | |
} | |
public override bool Matches(T value) | |
{ | |
return this.predicate(value); | |
} | |
} | |
public class SamplePredicate<T> : Predicate<T> | |
{ | |
private readonly IEquatable<T> sample; | |
public SamplePredicate(IEquatable<T> sample) | |
{ | |
this.sample = sample; | |
} | |
public override bool Matches(T value) | |
{ | |
return this.sample.Equals(value); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment