Last active
August 29, 2015 14:25
-
-
Save b0urb4k1/c03fc7c2e9b690ee3d94 to your computer and use it in GitHub Desktop.
This file contains hidden or 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.Reactive.Subjects; | |
using System.Reactive.Linq; | |
using System; | |
using LanguageExt; | |
using static LanguageExt.Prelude; | |
using static Shock.Strategies; | |
using System.Collections.Generic; | |
using static Shock.BusinessLogic; | |
using System.Linq; | |
namespace Shock | |
{ | |
#region Variable | |
public sealed class Variable<T> : ISubject<T>, IDisposable | |
{ | |
private BehaviorSubject<T> _subject; | |
private Action _onDispose; | |
private Variable() {} | |
public static Variable<T> make(BehaviorSubject<T> subject) => new Variable<T>() {_subject = subject }; | |
public IDisposable Subscribe(IObserver<T> observer) => _subject.Subscribe(observer); | |
public void OnCompleted() => _subject.OnCompleted(); | |
public void OnError(Exception error) => _subject.OnError(error); | |
public void OnNext(T value) => _subject.OnNext(value); | |
public static Variable<T> make(Action onDispose) => | |
new Variable<T>() | |
{ _subject = new BehaviorSubject<T>(default(T)) | |
, _onDispose = onDispose | |
}; | |
public static Variable<T> make(T value, Action onDispose) => | |
new Variable<T>() | |
{ _subject = new BehaviorSubject<T>(value) | |
, _onDispose = onDispose | |
}; | |
public void Dispose() | |
{ | |
if (_onDispose != null) | |
_onDispose(); | |
_subject.Dispose(); | |
} | |
public T Value { get { return _subject.Value; } set { _subject.OnNext(value); } } | |
} | |
#endregion | |
#region Combinder | |
public static class Combiner | |
{ | |
public static IObservable<Tuple<T1, T2>> and<T1, T2, T3> | |
( this IObservable<T1> o1 | |
, Tuple<Func<IObservable<T1>, IObservable<T2>, IObservable<Tuple<T1, T2>>>, Func<IObservable<Tuple<T1, T2>>, IObservable<T3>, IObservable<Tuple<T1, T2, T3>>>> fun | |
, IObservable<T2> o2 | |
) => fun.Item1(o1, o2); | |
public static IObservable<Tuple<T1, T2, T3>> and<T1, T2, T3> | |
(this IObservable<Tuple<T1, T2>> o1 | |
, Tuple<Func<IObservable<T1>, IObservable<T2>, IObservable<Tuple<T1, T2>>>, Func<IObservable<Tuple<T1, T2>>, IObservable<T3>, IObservable<Tuple<T1, T2, T3>>>> fun | |
, IObservable<T3> o2 | |
) => fun.Item2(o1, o2); | |
public static IObservable<T3> then<T1, T2, T3>(this IObservable<Tuple<T1, T2>> o, Func<Tuple<T1, T2>, T3> fun) => | |
o.Select(v => { return fun(v); }); | |
public static IObservable<T4> then<T1, T2, T3, T4>(this IObservable<Tuple<T1, T2, T3>> o, Func<Tuple<T1, T2, T3>, T4> fun) => | |
o.Select(v => { return fun(v); }); | |
public static IObservable<T3> then<T1, T2, T3>(this IObservable<Tuple<T1, T2>> o, Func<T1, T2, T3> fun) => | |
o.then(tuplize(fun)); | |
public static IObservable<T4> then<T1, T2, T3, T4>(this IObservable<Tuple<T1, T2, T3>> o, Func<T1, T2, T3, T4> fun) => | |
o.then(tuplize(fun)); | |
public static IDisposable assign<T>(this IObservable<T> o, ISubject<T> b) => o.Subscribe(b.OnNext); | |
public static Func<Tuple<T1, T2>, T3> tuplize<T1, T2, T3>(Func<T1, T2, T3> fun) => | |
t => fun(t.Item1, t.Item2); | |
public static Func<Tuple<T1, T2, T3>, T4> tuplize<T1, T2, T3, T4>(Func<T1, T2, T3, T4> fun) => | |
t => fun(t.Item1, t.Item2, t.Item3); | |
public static IDisposable then<T>(this Variable<T> v, Action<T> a) => v.Skip(1).Subscribe(a); | |
} | |
#endregion | |
#region NoBuffer | |
class NoBuffer<T1, T2> : IObservable<Tuple<T1, T2>>, IDisposable | |
{ | |
readonly IObservable<T1> _observer1; | |
readonly IObservable<T2> _observer2; | |
Option<T1> _optional1; | |
Option<T2> _optional2; | |
readonly IDisposable _subscription1; | |
readonly IDisposable _subscription2; | |
readonly Subject<Tuple<T1, T2>> _subject = new Subject<Tuple<T1, T2>>(); | |
void OnT1(T1 value) => | |
match | |
( _optional2 | |
, Some: v => | |
{ | |
_optional2 = Option<T2>.None; | |
_subject.OnNext(tuple(value, v)); | |
} | |
, None: () => _optional1 = value | |
); | |
void OnT2(T2 value) => | |
match | |
( _optional1 | |
, Some: v => | |
{ | |
_optional1 = Option<T1>.None; | |
_subject.OnNext(tuple(v, value)); | |
} | |
, None: () => _optional2 = value | |
); | |
void OnCompleted() => _subject.OnCompleted(); | |
void OnError(Exception error) => _subject.OnError(error); | |
public IDisposable Subscribe(IObserver<Tuple<T1, T2>> observer) => _subject.Subscribe(observer); | |
public NoBuffer(IObservable<T1> o1, IObservable<T2> o2) | |
{ | |
_observer1 = o1; | |
_observer2 = o2; | |
_subscription1 = _observer1.Subscribe(OnT1, OnError, OnCompleted); | |
_subscription2 = _observer2.Subscribe(OnT2, OnError, OnCompleted); | |
} | |
public void Dispose() | |
{ | |
_subscription1.Dispose(); | |
_subscription2.Dispose(); | |
_subject.Dispose(); | |
} | |
} | |
#endregion | |
#region Strategies | |
public static class Strategies | |
{ | |
public static Tuple<Func<IObservable<T1>, IObservable<T2>, IObservable<Tuple<T1, T2>>>, Func<IObservable<Tuple<T1, T2>>, IObservable<T3>, IObservable<Tuple<T1, T2, T3>>>> _buffer<T1, T2, T3>() => | |
Tuple.Create<Func<IObservable<T1>, IObservable<T2>, IObservable<Tuple<T1, T2>>>, Func<IObservable<Tuple<T1, T2>>, IObservable<T3>, IObservable<Tuple<T1, T2, T3>>>> | |
( (o1, o2) => o1.CombineLatest(o2, (v1, v2) => tuple(v1, v2)) | |
, (o1, o2) => o1.CombineLatest(o2, (t, v) => tuple(t.Item1, t.Item2, v)) | |
); | |
public static Tuple<Func<IObservable<T1>, IObservable<T2>, IObservable<Tuple<T1, T2>>>, Func<IObservable<Tuple<T1, T2>>, IObservable<T3>, IObservable<Tuple<T1, T2, T3>>>> _consume<T1, T2, T3>() => | |
Tuple.Create<Func<IObservable<T1>, IObservable<T2>, IObservable<Tuple<T1, T2>>>, Func<IObservable<Tuple<T1, T2>>, IObservable<T3>, IObservable<Tuple<T1, T2, T3>>>> | |
( (o1, o2) => new NoBuffer<T1, T2>(o1, o2) | |
, (o1, o2) => { throw new NotImplementedException(); } | |
); | |
} | |
#endregion | |
#region Environment | |
public class Environment<T> : IDisposable | |
{ | |
private readonly Dictionary<string, Variable<T>> _dictionaryVariables = new Dictionary<string, Variable<T>>(); | |
private readonly Dictionary<string, T> _dictionary = new Dictionary<string, T>(); | |
public Environment(Dictionary<string, T> dictionary) | |
{ | |
_dictionary = dictionary; | |
} | |
public Variable<T> GetOrCreate(string key) => getOrCreate(key, default(T)); | |
public Variable<T> getOrCreate(string key, T value) | |
{ | |
if (_dictionaryVariables.ContainsKey(key) == false) | |
{ | |
_dictionaryVariables[key] = Variable<T>.make | |
( () => | |
{ if (_dictionary.ContainsKey(key)) | |
_dictionary.Remove(key) | |
; if (_dictionaryVariables.ContainsKey(key)) | |
_dictionaryVariables.Remove(key); | |
}); | |
_dictionaryVariables[key].Subscribe(v => _dictionary[key] = v); | |
} | |
return _dictionaryVariables[key]; | |
} | |
#endregion | |
public void Dispose() | |
{ | |
var list = new List<Variable<T>>(); | |
foreach (var k in _dictionaryVariables) | |
list.Add(k.Value); | |
list.ForEach(v => v.Dispose()); | |
} | |
public T this[string key] => _dictionary[key]; | |
} | |
#region BusinessLogic | |
public static class BusinessLogic | |
{ | |
public static int Multiply(int x, int y) => x * y; | |
public static int Add3(int x, int y, int z) => x + y + z; | |
} | |
#endregion | |
class Program | |
{ | |
public static void Main(string[] args) | |
{ | |
#region data | |
var dictionary = new Dictionary<string, int>(); | |
dictionary.Add("x", 0); | |
dictionary.Add("y", 0); | |
dictionary.Add("z", 0); | |
dictionary.Add("v", 0); | |
dictionary.Add("sum", 0); | |
dictionary.Add("endValue", 0); | |
#endregion | |
using (var env = new Environment<int>(dictionary)) | |
{ | |
#region variables | |
var x = env.GetOrCreate("x"); | |
var y = env.GetOrCreate("y"); | |
var z = env.GetOrCreate("z"); | |
var v = env.GetOrCreate("v"); | |
var sum = env.GetOrCreate("sum"); | |
var endValue = env.GetOrCreate("endValue"); ; | |
#endregion | |
#region strategies | |
var consume = _consume<int, int, int>(); | |
var buffer = _buffer<int, int, int>(); | |
#endregion | |
using (x.and(buffer, y).and(buffer, z).then(Add3).assign(sum)) | |
using (sum.and(buffer, v).then(Multiply).assign(endValue)) | |
using (endValue.then(Console.WriteLine)) | |
{ | |
x.Value = 1; | |
y.Value = 2; | |
z.Value = 3; | |
v.Value = 4; | |
//z.Value = 5; | |
//v.Value = 6; | |
} | |
Console.WriteLine(env["sum"]); | |
Console.WriteLine(env["endValue"]); | |
} | |
System.Console.ReadKey(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment