Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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;
- using System.Reactive.Disposables;
- using System.Linq.Expressions;
- using System.Collections;
- namespace Shock
- {
- #region Variable
- public sealed class Variable<T> : ISubject<T>, IDisposable
- {
- private Subject<T> _subject;
- private Action _onDispose;
- private Option<T> _optional;
- public Variable(Variable<T> other)
- {
- _subject = other._subject;
- _onDispose = other._onDispose;
- _optional = other._optional;
- }
- private Variable(Subject<T> subject)
- {
- _subject = subject;
- this.Subscribe(v => _optional = v);
- }
- public static Variable<T> make(Subject<T> subject) => new Variable<T>(subject);
- public IDisposable Subscribe(IObserver<T> observer) => _subject.Subscribe(observer);
- public static Variable<T> make(Action onDispose) => make(default(T), onDispose);
- public void OnError(Exception error) => _subject.OnError(error);
- public void OnCompleted() => _subject.OnCompleted();
- public void OnNext(T value) => _subject.OnNext(value);
- public static Variable<T> make(T value, Action onDispose) =>
- new Variable<T>(new Subject<T>())
- {
- _onDispose = onDispose
- };
- private void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (_onDispose != null)
- _onDispose();
- _subject.Dispose();
- }
- }
- public void Dispose()
- {
- Dispose(true);
- }
- public T Value { get { return _optional.IfNone(null); } 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 IDisposable assign<T>(this IObservable<T> o, Environment<T> env, string key) => o.Subscribe(env.GetOrCreate(key));
- 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.Subscribe(a);
- }
- #endregion
- #region Consuming
- public class Consuming<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>>();
- public IObservable<T1> Observer1 => _observer1;
- public IObservable<T2> Observer2 => _observer2;
- 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 Consuming(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();
- }
- }
- public class Consuming<T1, T2, T3> : IObservable<Tuple<T1, T2, T3>>, IDisposable
- {
- readonly IObservable<Tuple<T1, T2>> _observer1;
- readonly IObservable<T3> _observer2;
- readonly CompositeDisposable _subscriptions;
- readonly Subject<Tuple<T1, T2, T3>> _subject = new Subject<Tuple<T1, T2, T3>>();
- Option<Tuple<T1, T2>> _optional1;
- Option<T3> _optional2;
- void OnT1xT2(Tuple<T1, T2> value) =>
- match
- ( _optional2
- , Some: v =>
- {
- _optional2 = Option<T3>.None;
- _subject.OnNext(tuple(value.Item1, value.Item2, v));
- }
- , None: () => _optional1 = value
- );
- void OnT2(T3 value) =>
- match
- ( _optional1
- , Some: v =>
- {
- _optional1 = Option<Tuple<T1, T2>>.None;
- _subject.OnNext(tuple(v.Item1, v.Item2, value));
- }
- , None: () => _optional2 = value
- );
- void OnCompleted() => _subject.OnCompleted();
- void OnError(Exception error) => _subject.OnError(error);
- public IDisposable Subscribe(IObserver<Tuple<T1, T2, T3>> observer) => _subject.Subscribe(observer);
- public Consuming(IObservable<Tuple<T1, T2>> o1, IObservable<T3> o2)
- {
- _observer1 = o1;
- _observer2 = o2;
- _subscriptions = new CompositeDisposable
- ( _observer1.Subscribe(OnT1xT2, OnError, OnCompleted)
- , _observer2.Subscribe(OnT2, OnError, OnCompleted)
- );
- }
- public void Dispose()
- {
- _subscriptions.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 Consuming<T1, T2>(o1, o2)
- , (o1, o2) => new Consuming<T1, T2, T3>(o1, o2)
- );
- }
- #endregion
- #region StandardStrategiess
- public static class StandardStrategies
- {
- public static Tuple<Func<IObservable<int>, IObservable<int>, IObservable<Tuple<int, int>>>, Func<IObservable<Tuple<int, int>>, IObservable<int>, IObservable<Tuple<int, int, int>>>> ConsumeInt => _consume<int, int, int>();
- public static Tuple<Func<IObservable<float>, IObservable<float>, IObservable<Tuple<float, float>>>, Func<IObservable<Tuple<float, float>>, IObservable<float>, IObservable<Tuple<float, float, float>>>> ConsumeFloat => _consume<float, float, float>();
- public static Tuple<Func<IObservable<int>, IObservable<int>, IObservable<Tuple<int, int>>>, Func<IObservable<Tuple<int, int>>, IObservable<int>, IObservable<Tuple<int, int, int>>>> BufferInt => _buffer<int, int, int>();
- public static Tuple<Func<IObservable<float>, IObservable<float>, IObservable<Tuple<float, float>>>, Func<IObservable<Tuple<float, float>>, IObservable<float>, IObservable<Tuple<float, float, float>>>> BufferFloat => _buffer<float, float, float>();
- }
- #endregion
- #region FunctionOf
- public static class Function
- {
- public static IObservable<T3> Of<T1, T2, T3, T4>
- ( Expression<Func<T1, T2, T3>> expr
- , IDictionary<string, Variable<T1>> env1
- , IDictionary<string, Variable<T2>> env2
- , Tuple
- < Func<IObservable<T1>, IObservable<T2>, IObservable<Tuple<T1, T2>>>
- , Func<IObservable<Tuple<T1, T2>>, IObservable<T4>, IObservable<Tuple<T1, T2, T4>>>
- > fun
- )
- {
- var parameterNames = expr.Parameters.Select(p => p.Name).ToArray();
- var consume = _consume<T1, T2, T3>();
- if (expr.Body is MethodCallExpression)
- {
- var function = (MethodCallExpression)expr.Body;
- var method = function.Method;
- var arguments = function.Arguments.Cast<ParameterExpression>().Select(p => p.Name).ToArray();
- var x = env1[arguments[0]];
- var y = env2[arguments[1]];
- return x.and(fun, y).then(t => (T3)method.Invoke(null, new[] { (object)t.Item1, t.Item2 }));
- }
- throw new Exception("unsuported expression.");
- }
- public static IObservable<T4> Of<T1, T2, T3, T4>
- ( Expression<Func<T1, T2, T3, T4>> expr
- , IDictionary<string, Variable<T1>> env1
- , IDictionary<string, Variable<T2>> env2
- , IDictionary<string, Variable<T3>> env3
- , Tuple
- < Func<IObservable<T1>, IObservable<T2>, IObservable<Tuple<T1, T2>>>
- , Func<IObservable<Tuple<T1, T2>>, IObservable<T3>, IObservable<Tuple<T1, T2, T3>>>
- > fun
- )
- {
- var parameterNames = expr.Parameters.Select(p => p.Name).ToArray();
- var consume = _consume<T1, T2, T3>();
- var body = expr.Body;
- if (expr.Body is MethodCallExpression)
- {
- var function = (expr.Body as MethodCallExpression);
- var method = (expr.Body as MethodCallExpression).Method;
- var arguments = function.Arguments.Cast<ParameterExpression>().Select(p => p.Name).ToArray();
- var x = env1[arguments[0]];
- var y = env2[arguments[1]];
- var z = env3[arguments[2]];
- return x.and(fun, y).and(fun, z).then(t => (T4)method.Invoke(null, new[] { (object)t.Item1, t.Item2, t.Item3 }));
- }
- //TODO conversions
- //else if (expr.Body is UnaryExpression && (expr.Body as UnaryExpression).NodeType == ExpressionType.Convert)
- //{
- // var function = (expr.Body as UnaryExpression);
- // var operand = (MethodCallExpression)function.Operand;
- // return FunctionOf(expr.Body, env1, env2, retVariable, fun);
- // var method = (expr.Body as MethodCallExpression).Method;
- // return null;
- //}
- throw new Exception("unsuported expression.");
- }
- }
- #endregion
- #region Environment
- public class Environment<T> : IDisposable, IDictionary<string, Variable<T>>
- {
- private readonly Dictionary<string, Variable<T>> _dictionaryVariables = new Dictionary<string, Variable<T>>();
- private readonly Dictionary<string, T> _dictionary = new Dictionary<string, T>();
- public ICollection<string> Keys => _dictionaryVariables.Keys;
- public ICollection<Variable<T>> Values => _dictionaryVariables.Values;
- public int Count => _dictionaryVariables.Count;
- public bool IsReadOnly => true;
- Variable<T> IDictionary<string, Variable<T>>.this[string key]
- {
- get { return GetOrCreate(key); }
- set { throw new Exception(); }
- }
- public Variable<T> this[string key] => GetOrCreate(key);
- 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
- ( value
- , () =>
- {
- if (_dictionary.ContainsKey(key))
- _dictionary.Remove(key);
- if (_dictionaryVariables.ContainsKey(key))
- _dictionaryVariables.Remove(key);
- }
- );
- _dictionaryVariables[key].Subscribe(v => _dictionary[key] = v);
- }
- var result = _dictionaryVariables[key];
- return result;
- }
- private void Dispose(bool disposing)
- {
- if (disposing)
- {
- var list = new List<Variable<T>>();
- foreach (var k in _dictionaryVariables)
- list.Add(k.Value);
- list.ForEach(v => v.Dispose());
- }
- }
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- public bool ContainsKey(string key)
- {
- throw new NotImplementedException();
- }
- public void Add(string key, Variable<T> value)
- {
- throw new NotImplementedException();
- }
- public bool Remove(string key)
- {
- throw new NotImplementedException();
- }
- public bool TryGetValue(string key, out Variable<T> value)
- {
- throw new NotImplementedException();
- }
- public void Add(KeyValuePair<string, Variable<T>> item)
- {
- throw new NotImplementedException();
- }
- public void Clear()
- {
- throw new NotImplementedException();
- }
- public bool Contains(KeyValuePair<string, Variable<T>> item)
- {
- throw new NotImplementedException();
- }
- public void CopyTo(KeyValuePair<string, Variable<T>>[] array, int arrayIndex)
- {
- throw new NotImplementedException();
- }
- public bool Remove(KeyValuePair<string, Variable<T>> item)
- {
- throw new NotImplementedException();
- }
- public IEnumerator<KeyValuePair<string, Variable<T>>> GetEnumerator()
- {
- throw new NotImplementedException();
- }
- IEnumerator IEnumerable.GetEnumerator()
- {
- throw new NotImplementedException();
- }
- }
- #endregion
- #region BusinessLogic
- public static class BusinessLogic
- {
- public static float Multiply(float x, float y) => x * y;
- public static float Add3(int x, int y, int z) => x + y + z;
- }
- #endregion
- class Program
- {
- [STAThread]
- public static void Main(string[] args)
- {
- #region databases
- var database1 = new Dictionary<string, int>();
- database1.Add("x", 0);
- database1.Add("y", 0);
- database1.Add("z", 0);
- var database2 = new Dictionary<string, float>();
- database2.Add("v", 0);
- database2.Add("sum", 0);
- database2.Add("endValue", 0);
- #endregion
- var strategyFloat = StandardStrategies.BufferFloat;
- var strategyInt = StandardStrategies.BufferInt;
- //var strategyFloat = StandardStrategies.ConsumeFloat;
- //var strategyInt = StandardStrategies.ConsumeInt;
- using (var env1 = new Environment<int>(database1))
- using (var env2 = new Environment<float>(database2))
- using (Function.Of(expr((int x, int y, int z) => Add3(x, y, z)), env1, env1, env1, strategyInt).assign(env2, "sum"))
- using (Function.Of(expr((float sum, float v) => Multiply(sum, v)), env2, env2, strategyFloat).assign(env2, "endValue"))
- {
- #region variables
- var x = env1["x"];
- var y = env1["y"];
- var z = env1["z"];
- var v = env2["v"];
- var endValue = env2["endValue"];
- #endregion
- endValue.then(Console.WriteLine);
- x.Value = 1;
- y.Value = 2;
- z.Value = 3;
- v.Value = 3.14f;
- v.Value = 2.9f;
- //z.Value = 5;
- //v.Value = 6;
- Console.WriteLine("Read from database");
- Console.WriteLine(database2["endValue"]);
- }
- System.Console.ReadKey();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement