public MainWindow() { this.InitializeComponent(); this.Loaded += (sender, args) => { Animate animate = new Animate((sys, extents) => { Cell<double> time = sys.Time; double t0 = time.Sample(); double ballRadius = 15; double leftWall = -extents.X + ballRadius; double rightWall = extents.X - ballRadius; double floor = -extents.Y + ballRadius; double roof = extents.Y - ballRadius; Signal gravity = new Signal(t0, 0, 0, -1200); StreamLoop<Signal> sBounceX = new StreamLoop<Signal>(); StreamLoop<Signal> sBounceY = new StreamLoop<Signal>(); Cell<Signal> velx = sBounceX.Hold(new Signal(t0, 0, 0, 350)); Cell<Signal> vely = sBounceY.Hold(gravity.Integrate(0)); Cell<Signal> posx = Signal.Integrate(velx, leftWall); Cell<Signal> posy = Signal.Integrate(vely, roof); sBounceX.Loop(BounceAt(sys, velx, posx, leftWall).OrElse(BounceAt(sys, velx, posx, rightWall))); sBounceY.Loop(BounceAt(sys, vely, posy, floor)); return Shapes.Translate(Shapes.Scale(Shapes.Circle(Colors.Red), Cell.Constant(ballRadius)), time.Lift(posx, posy, (t, x, y) => new Point(x.ValueAt(t), y.ValueAt(t)))); }, this.Placeholder.RenderSize); this.Placeholder.Children.Add(animate); animate.Start(); }; }
public MainWindow() { this.InitializeComponent(); this.Loaded += (sender, args) => { Animate animate = new Animate((sys, extents) => { Behavior <double> time = sys.Time; double t0 = time.Sample(); double ballRadius = 15; double leftWall = -extents.X + ballRadius; double rightWall = extents.X - ballRadius; double floor = -extents.Y + ballRadius; double roof = extents.Y - ballRadius; Signal gravity = new Signal(t0, 0, 0, -1200); StreamLoop <Signal> sBounceX = new StreamLoop <Signal>(); StreamLoop <Signal> sBounceY = new StreamLoop <Signal>(); Cell <Signal> velx = sBounceX.Hold(new Signal(t0, 0, 0, 350)); Cell <Signal> vely = sBounceY.Hold(gravity.Integrate(0)); Cell <Signal> posx = Signal.Integrate(velx, leftWall); Cell <Signal> posy = Signal.Integrate(vely, roof); sBounceX.Loop(BounceAt(sys, velx, posx, leftWall).OrElse(BounceAt(sys, velx, posx, rightWall))); sBounceY.Loop(BounceAt(sys, vely, posy, floor)); return(Shapes.Translate(Shapes.Scale(Shapes.Circle(Colors.Red), Behavior.Constant(ballRadius)), time.Lift(posx.AsBehavior(), posy.AsBehavior(), (t, x, y) => new Point(x.ValueAt(t), y.ValueAt(t))))); }, this.Placeholder.RenderSize); this.Placeholder.Children.Add(animate); animate.Start(); }; }
public Sspinner(int initVal) { Transaction.RunVoid(() => { StreamLoop <int> sSetValue = new StreamLoop <int>(); STextBox textBox = new STextBox( sSetValue.Map(v => v.ToString()), initVal.ToString(), Cell.Constant(true)); this.Value = textBox.CText.Map(txt => int.TryParse(txt, out int val) ? val : 0); //initializeComponent InitializeComponent(); textBox.HorizontalContentAlignment = HorizontalAlignment.Center; textBox.VerticalAlignment = VerticalAlignment.Center; this.valueTextBoxPlaceHolder.Children.Add(textBox); Stream <int> sPlusDelta = this.plusButton.SClicked.Map(u => 1); Stream <int> sMinusDelta = this.minusButton.SClicked.Map(u => - 1); Stream <int> sDelta = sPlusDelta.OrElse(sMinusDelta); sSetValue.Loop( sDelta.Snapshot( this.Value, (delta, value) => delta + value)); }); }
public Outputs Create(Inputs inputs) { StreamLoop <Fuel> sStart = new StreamLoop <Fuel>(); Fill fi = new Fill(inputs.SClearSale, inputs.SFuelPulses, inputs.Calibration, inputs.Price1, inputs.Price2, inputs.Price3, sStart); NotifyPointOfSale np = new NotifyPointOfSale( new LifeCycle(inputs.SNozzle1, inputs.SNozzle2, inputs.SNozzle3), inputs.SClearSale, fi); sStart.Loop(np.SStart); CellLoop <bool> keypadActive = new CellLoop <bool>(); Keypad ke = new Keypad(inputs.SKeypad, inputs.SClearSale, keypadActive); Preset pr = new Preset(ke.Value, fi, np.FuelFlowing); keypadActive.Loop(pr.KeypadActive); return(new Outputs() .SetDelivery(pr.Delivery) .SetSaleCostLcd(fi.DollarsDelivered.Map(Formatters.FormatSaleCost)) .SetSaleQuantityLcd(fi.LitersDelivered.Map(Formatters.FormatSaleQuantity)) .SetPriceLcd1(ShowDollarsPump.PriceLcd(np.FillActive, fi.Price, Fuel.One, inputs)) .SetPriceLcd2(ShowDollarsPump.PriceLcd(np.FillActive, fi.Price, Fuel.Two, inputs)) .SetPriceLcd3(ShowDollarsPump.PriceLcd(np.FillActive, fi.Price, Fuel.Three, inputs)) .SetSaleComplete(np.SSaleComplete) .SetPresetLcd(ke.Value.Map(Formatters.FormatPresetAmount)) .SetBeep(np.SBeep.OrElse(ke.SBeep))); }
public Outputs Create(Inputs inputs) { StreamLoop<Fuel> sStart = new StreamLoop<Fuel>(); Fill fi = new Fill( inputs.SClearSale, inputs.SFuelPulses, inputs.Calibration, inputs.Price1, inputs.Price2, inputs.Price3, sStart); NotifyPointOfSale np = new NotifyPointOfSale( new LifeCycle(inputs.SNozzle1, inputs.SNozzle2, inputs.SNozzle3), inputs.SClearSale, fi); sStart.Loop(np.SStart); return new Outputs() .SetDelivery(np.FuelFlowing.Map( m => m.Equals(Maybe.Just(Fuel.One)) ? Delivery.Fast1 : m.Equals(Maybe.Just(Fuel.Two)) ? Delivery.Fast2 : m.Equals(Maybe.Just(Fuel.Three)) ? Delivery.Fast3 : Delivery.Off)) .SetSaleCostLcd(fi.DollarsDelivered.Map(Formatters.FormatSaleCost)) .SetSaleQuantityLcd(fi.LitersDelivered.Map(Formatters.FormatSaleQuantity)) .SetPriceLcd1(ShowDollarsPump.PriceLcd(np.FillActive, fi.Price, Fuel.One, inputs)) .SetPriceLcd2(ShowDollarsPump.PriceLcd(np.FillActive, fi.Price, Fuel.Two, inputs)) .SetPriceLcd3(ShowDollarsPump.PriceLcd(np.FillActive, fi.Price, Fuel.Three, inputs)) .SetBeep(np.SBeep) .SetSaleComplete(np.SSaleComplete); }
public Outputs Create(Inputs inputs) { StreamLoop <Fuel> sStart = new StreamLoop <Fuel>(); Fill fi = new Fill( inputs.SClearSale, inputs.SFuelPulses, inputs.Calibration, inputs.Price1, inputs.Price2, inputs.Price3, sStart); NotifyPointOfSale np = new NotifyPointOfSale( new LifeCycle(inputs.SNozzle1, inputs.SNozzle2, inputs.SNozzle3), inputs.SClearSale, fi); sStart.Loop(np.SStart); return(new Outputs() .SetDelivery(np.FuelFlowing.Map( m => m.Equals(Maybe.Some(Fuel.One)) ? Delivery.Fast1 : m.Equals(Maybe.Some(Fuel.Two)) ? Delivery.Fast2 : m.Equals(Maybe.Some(Fuel.Three)) ? Delivery.Fast3 : Delivery.Off)) .SetSaleCostLcd(fi.DollarsDelivered.Map(Formatters.FormatSaleCost)) .SetSaleQuantityLcd(fi.LitersDelivered.Map(Formatters.FormatSaleQuantity)) .SetPriceLcd1(ShowDollarsPump.PriceLcd(np.FillActive, fi.Price, Fuel.One, inputs)) .SetPriceLcd2(ShowDollarsPump.PriceLcd(np.FillActive, fi.Price, Fuel.Two, inputs)) .SetPriceLcd3(ShowDollarsPump.PriceLcd(np.FillActive, fi.Price, Fuel.Three, inputs)) .SetBeep(np.SBeep) .SetSaleComplete(np.SSaleComplete)); }
public void TestLoopStream() { StreamSink <int> sa = Stream.CreateSink <int>(); (StreamLoop <int> sb, Stream <int> sb2, Stream <int> sc) = Transaction.Run(() => { StreamLoop <int> sbLocal = Stream.CreateLoop <int>(); Stream <int> scLocal = sa.Map(x => x % 10).Merge(sbLocal, (x, y) => x * y); Stream <int> sbOut = sa.Map(x => x / 10).Filter(x => x != 0); sbLocal.Loop(sbOut); return(sbLocal, sbOut, scLocal); }); List <int> @out = new List <int>(); List <int> out2 = new List <int>(); List <int> out3 = new List <int>(); IListener l = sb.Listen(@out.Add); IListener l2 = sb2.Listen(out2.Add); IListener l3 = sc.Listen(out3.Add); sa.Send(2); sa.Send(52); l3.Unlisten(); l2.Unlisten(); l.Unlisten(); CollectionAssert.AreEqual(new[] { 5 }, @out.ToArray()); CollectionAssert.AreEqual(new[] { 5 }, out2.ToArray()); CollectionAssert.AreEqual(new[] { 2, 10 }, out3.ToArray()); }
public Outputs Create(Inputs inputs) { StreamLoop<Fuel> sStart = new StreamLoop<Fuel>(); Fill fi = new Fill(inputs.SClearSale, inputs.SFuelPulses, inputs.Calibration, inputs.Price1, inputs.Price2, inputs.Price3, sStart); NotifyPointOfSale np = new NotifyPointOfSale( new LifeCycle(inputs.SNozzle1, inputs.SNozzle2, inputs.SNozzle3), inputs.SClearSale, fi); sStart.Loop(np.SStart); CellLoop<bool> keypadActive = new CellLoop<bool>(); Keypad ke = new Keypad(inputs.SKeypad, inputs.SClearSale, keypadActive); Preset pr = new Preset(ke.Value, fi, np.FuelFlowing); keypadActive.Loop(pr.KeypadActive); return new Outputs() .SetDelivery(pr.Delivery) .SetSaleCostLcd(fi.DollarsDelivered.Map(Formatters.FormatSaleCost)) .SetSaleQuantityLcd(fi.LitersDelivered.Map(Formatters.FormatSaleQuantity)) .SetPriceLcd1(ShowDollarsPump.PriceLcd(np.FillActive, fi.Price, Fuel.One, inputs)) .SetPriceLcd2(ShowDollarsPump.PriceLcd(np.FillActive, fi.Price, Fuel.Two, inputs)) .SetPriceLcd3(ShowDollarsPump.PriceLcd(np.FillActive, fi.Price, Fuel.Three, inputs)) .SetSaleComplete(np.SSaleComplete) .SetPresetLcd(ke.Value.Map(Formatters.FormatPresetAmount)) .SetBeep(np.SBeep.OrElse(ke.SBeep)); }
public void Issue151_PoolDoubleSubtraction_Fixed() { CellSink <int> threshold = new CellSink <int>(10); StreamSink <int> addPoolSink = new StreamSink <int>(); (Stream <int> input, Cell <int> pool) = Transaction.Run(() => { StreamLoop <int> submitPooledAmount = new StreamLoop <int>(); // Ways that the pool is modified. Stream <Func <int, int> > poolAddByInput = addPoolSink.Map <Func <int, int> >(i => x => x + i); Stream <Func <int, int> > poolRemoveByUsage = Operational.Defer(submitPooledAmount.Map <Func <int, int> >(i => x => x - i)); // The current level of the pool Cell <int> poolLocal = poolAddByInput .Merge(poolRemoveByUsage, (f, g) => x => g(f(x))) .Accum(0, (f, x) => f(x)); // The current input changes combined with the pool as a stream Stream <int> inputByAdded = poolAddByInput .Snapshot( poolLocal, threshold, (f, x, t) => f(x) >= t ? Maybe.Some(f(x)) : Maybe.None) .FilterMaybe(); // Simple rising edge on pool threshold satisfaction. Stream <int> inputBySatisfaction = poolLocal.Updates .Snapshot( poolLocal, threshold, (neu, alt, t) => neu >= t && alt < t ? Maybe.Some(neu) : Maybe.None) .FilterMaybe(); submitPooledAmount.Loop(inputByAdded.Merge(inputBySatisfaction, Math.Max)); return(submitPooledAmount, poolLocal); }); List <int> submissions = new List <int>(); using (input.Listen(submissions.Add)) { // Add amount which can be immediately used based on threshold. // Pool should remain zero after the transaction is complete. addPoolSink.Send(10); } Assert.AreEqual(1, submissions.Count); Assert.AreEqual(10, submissions[0]); Assert.AreEqual(0, pool.Sample()); }
private SSpinner(int initialValue) { StreamLoop <int> sSetValue = new StreamLoop <int>(); STextBox textField = new STextBox(sSetValue.Map(v => v.ToString()), initialValue.ToString()) { VerticalContentAlignment = VerticalAlignment.Center }; this.Value = textField.Text.Map(t => { int result; if (int.TryParse(t, out result)) { return(result); } return(0); }); SButton plus = new SButton { Content = "+", Width = 25 }; SButton minus = new SButton { Content = "-", Width = 25 }; this.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); this.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); this.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); this.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); SetRow(textField, 0); SetColumn(textField, 0); SetRowSpan(textField, 2); this.Children.Add(textField); SetRow(plus, 0); SetColumn(plus, 1); this.Children.Add(plus); SetRow(minus, 1); SetColumn(minus, 1); this.Children.Add(minus); Stream <int> sPlusDelta = plus.SClicked.Map(_ => 1); Stream <int> sMinusDelta = minus.SClicked.Map(_ => - 1); Stream <int> sDelta = sPlusDelta.OrElse(sMinusDelta); sSetValue.Loop(sDelta.Snapshot(this.Value, (d, v) => v + d)); }
public void Issue151_PoolDoubleSubtraction_Broken() { Exception actual = null; try { CellSink <int> threshold = new CellSink <int>(10); StreamSink <int> addPoolSink = new StreamSink <int>(); Transaction.Run(() => { StreamLoop <int> submitPooledAmount = new StreamLoop <int>(); // Ways that the pool is modified. Stream <Func <int, int> > poolAddByInput = addPoolSink.Map <Func <int, int> >(i => x => x + i); Stream <Func <int, int> > poolRemoveByUsage = submitPooledAmount.Map <Func <int, int> >(i => x => x - i); // The current level of the pool Cell <int> poolLocal = poolAddByInput .Merge(poolRemoveByUsage, (f, g) => x => g(f(x))) .Accum(0, (f, x) => f(x)); // The current input changes combined with the pool as a stream Stream <int> inputByAdded = poolAddByInput .Snapshot( poolLocal, threshold, (f, x, t) => f(x) >= t ? Maybe.Some(f(x)) : Maybe.None) .FilterMaybe(); // Simple rising edge on pool threshold satisfaction. Stream <int> inputBySatisfaction = poolLocal.Updates .Snapshot( poolLocal, threshold, (neu, alt, t) => neu >= t && alt < t ? Maybe.Some(neu) : Maybe.None) .FilterMaybe(); submitPooledAmount.Loop(inputByAdded.Merge(inputBySatisfaction, Math.Max)); return(submitPooledAmount, poolLocal); }); } catch (Exception e) { actual = e; } Assert.IsNotNull(actual); Assert.AreEqual("A dependency cycle was detected.", actual.Message); }
private FrButton(Cell<string> label, StreamLoop<Unit> sClicked) : base((size, sMouse, sKey, focus, idSupply) => { Stream<Unit> sPressed = sMouse.Snapshot(size, (e, mSize) => mSize.Match( s => { MouseButtonEventArgs b = e.Args as MouseButtonEventArgs; Point p = e.GetPosition(); return b != null && b.ChangedButton == MouseButton.Left && b.ButtonState == MouseButtonState.Pressed && p.X >= 2 && p.X < s.Width - 2 && p.Y >= 2 && p.Y < s.Height - 2 ? Maybe.Just(Unit.Value) : Maybe.Nothing<Unit>(); }, Maybe.Nothing<Unit>)).FilterMaybe(); Stream<Unit> sReleased = sMouse.Snapshot(size, (e, mSize) => mSize.Match( s => { MouseButtonEventArgs b = e.Args as MouseButtonEventArgs; return b != null && b.ChangedButton == MouseButton.Left && b.ButtonState == MouseButtonState.Released ? Maybe.Just(Unit.Value) : Maybe.Nothing<Unit>(); }, Maybe.Nothing<Unit>)).FilterMaybe(); Cell<bool> pressed = sPressed.Map(_ => true).OrElse(sReleased.Map(_ => false)).Hold(false); sClicked.Loop(sReleased.Gate(pressed)); Typeface typeface = new Typeface(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal); Cell<Size> desiredSize = label.Map(l => { Size labelSize = FontUtilities.MeasureString(l, typeface, 13); return new Size(labelSize.Width + 14, labelSize.Height + 10); }); return new Output( label.Lift( size, pressed, (l, mSize, p) => new DrawableDelegate(d => { mSize.Match(sz => { d.DrawRectangle(p ? Brushes.DarkGray : Brushes.LightGray, new Pen(Brushes.Black, 1), new Rect(new Point(2, 2), new Size(sz.Width - 5, sz.Height - 5))); FormattedText t = FontUtilities.GetStandardFormattedText(l, typeface, 13, Brushes.Black); d.DrawText(t, new Point((sz.Width - t.Width) / 2, (sz.Height - t.Height) / 2)); }, () => { }); })), desiredSize, Stream.Never<long>()); }) { this.SClicked = sClicked; }
private FrButton(Cell <string> label, StreamLoop <Unit> sClicked) : base((size, sMouse, sKey, focus, idSupply) => { Stream <Unit> sPressed = sMouse.Snapshot(size, (e, mSize) => mSize.Match( s => { MouseButtonEventArgs b = e.Args as MouseButtonEventArgs; Point p = e.GetPosition(); return(b != null && b.ChangedButton == MouseButton.Left && b.ButtonState == MouseButtonState.Pressed && p.X >= 2 && p.X < s.Width - 2 && p.Y >= 2 && p.Y < s.Height - 2 ? Maybe.Just(Unit.Value) : Maybe.Nothing <Unit>()); }, Maybe.Nothing <Unit>)).FilterMaybe(); Stream <Unit> sReleased = sMouse.Snapshot(size, (e, mSize) => mSize.Match( s => { MouseButtonEventArgs b = e.Args as MouseButtonEventArgs; return(b != null && b.ChangedButton == MouseButton.Left && b.ButtonState == MouseButtonState.Released ? Maybe.Just(Unit.Value) : Maybe.Nothing <Unit>()); }, Maybe.Nothing <Unit>)).FilterMaybe(); Cell <bool> pressed = sPressed.Map(_ => true).OrElse(sReleased.Map(_ => false)).Hold(false); sClicked.Loop(sReleased.Gate(pressed)); Typeface typeface = new Typeface(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal); Cell <Size> desiredSize = label.Map(l => { Size labelSize = FontUtilities.MeasureString(l, typeface, 13); return(new Size(labelSize.Width + 14, labelSize.Height + 10)); }); return(new Output( label.Lift( size, pressed, (l, mSize, p) => new DrawableDelegate(d => { mSize.Match(sz => { d.DrawRectangle(p ? Brushes.DarkGray : Brushes.LightGray, new Pen(Brushes.Black, 1), new Rect(new Point(2, 2), new Size(sz.Width - 5, sz.Height - 5))); FormattedText t = FontUtilities.GetStandardFormattedText(l, typeface, 13, Brushes.Black); d.DrawText(t, new Point((sz.Width - t.Width) / 2, (sz.Height - t.Height) / 2)); }, () => { }); })), desiredSize, Stream.Never <long>())); }) { this.SClicked = sClicked; }
public void TestMerge() { StreamSink <Unit> s = Stream.CreateSink <Unit>(); var obj = Transaction.Run(() => { StreamLoop <bool> loop = Stream.CreateLoop <bool>(); DiscreteCellStreamSink <int> s1 = new DiscreteCellStreamSink <int>(); DiscreteCellStreamSink <int> s2 = new DiscreteCellStreamSink <int>(); TestObject[] l = Enumerable.Range(0, 5000).Select(_ => new TestObject(loop, s1, s2)).ToArray(); loop.Loop(s.Snapshot(l.Select(o => o.Cell).Lift().Cell).Map(o => o.All(v => v == 0))); return(l); }); int[] values = obj.Select(v => v.CurrentValue).ToArray(); }
public void ImperativeStreamLoopFailsWhenLoopedTwice() { InvalidOperationException actual = null; try { StreamSink <int> s = Stream.CreateSink <int>(); Transaction.RunVoid( () => { StreamLoop <int> l = new StreamLoop <int>(); Stream <int> resultLocal = s.Snapshot(l.Hold(0), (n, o) => n + o); l.Loop(resultLocal); l.Loop(resultLocal); }); } catch (InvalidOperationException e) { actual = e; } Assert.IsNotNull(actual); Assert.AreEqual("Loop was looped more than once.", actual.Message); }
public void TestStreamLoopDefer() { StreamSink <int> streamSink = Stream.CreateSink <int>(); Stream <int> stream = Transaction.Run(() => { StreamLoop <int> streamLoop = new StreamLoop <int>(); Stream <int> streamLocal = Operational.Defer(streamSink.OrElse(streamLoop).Filter(v => v < 5).Map(v => v + 1)); streamLoop.Loop(streamLocal); return(streamLocal); }); List <int> @out = new List <int>(); IListener l = stream.Listen(@out.Add); streamSink.Send(2); l.Unlisten(); CollectionAssert.AreEqual(new[] { 3, 4, 5 }, @out); }
public void TestLoopStream() { StreamSink <int> sa = new StreamSink <int>(); Stream <int> sc = Transaction.Run(() => { StreamLoop <int> sb = new StreamLoop <int>(); Stream <int> scLocal = sa.Map(x => x % 10).Merge(sb, (x, y) => x * y); Stream <int> sbOut = sa.Map(x => x / 10).Filter(x => x != 0); sb.Loop(sbOut); return(scLocal); }); List <int> @out = new List <int>(); using (sc.Listen(@out.Add)) { sa.Send(2); sa.Send(52); } CollectionAssert.AreEqual(new[] { 2, 10 }, @out.ToArray()); }
private SSpinner(int initialValue) { StreamLoop<int> sSetValue = new StreamLoop<int>(); STextBox textField = new STextBox(sSetValue.Map(v => v.ToString()), initialValue.ToString()) { VerticalContentAlignment = VerticalAlignment.Center }; this.Value = textField.Text.Map(t => { int result; if (int.TryParse(t, out result)) { return result; } return 0; }); SButton plus = new SButton { Content = "+", Width = 25 }; SButton minus = new SButton { Content = "-", Width = 25 }; this.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); this.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); this.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); this.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); SetRow(textField, 0); SetColumn(textField, 0); SetRowSpan(textField, 2); this.Children.Add(textField); SetRow(plus, 0); SetColumn(plus, 1); this.Children.Add(plus); SetRow(minus, 1); SetColumn(minus, 1); this.Children.Add(minus); Stream<int> sPlusDelta = plus.SClicked.Map(_ => 1); Stream<int> sMinusDelta = minus.SClicked.Map(_ => -1); Stream<int> sDelta = sPlusDelta.OrElse(sMinusDelta); sSetValue.Loop(sDelta.Snapshot(this.Value, (d, v) => v + d)); }
public void TestStreamLoop() { StreamSink <int> streamSink = Stream.CreateSink <int>(); Stream <int> s = Transaction.Run(() => { StreamLoop <int> sl = new StreamLoop <int>(); Cell <int> c = sl.Map(v => v + 2).Hold(0); Stream <int> s2 = streamSink.Snapshot(c, (x, y) => x + y); sl.Loop(s2); return(s2); }); List <int> @out = new List <int>(); IListener l = s.Listen(@out.Add); streamSink.Send(3); streamSink.Send(4); streamSink.Send(7); streamSink.Send(8); l.Unlisten(); CollectionAssert.AreEqual(new[] { 3, 9, 18, 28 }, @out); }
public void ImperativeStreamLoop() { StreamSink <int> s = Stream.CreateSink <int>(); Stream <int> result = Transaction.Run( () => { StreamLoop <int> l = new StreamLoop <int>(); Stream <int> resultLocal = s.Snapshot(l.Hold(0), (n, o) => n + o); l.Loop(resultLocal); return(resultLocal); }); List <int> @out = new List <int>(); using (result.Listen(@out.Add)) { s.Send(1); s.Send(2); s.Send(3); } CollectionAssert.AreEqual(new[] { 1, 3, 6 }, @out); }
public void TestLoopStream() { StreamSink<int> sa = new StreamSink<int>(); Stream<int> sc = Transaction.Run(() => { StreamLoop<int> sb = new StreamLoop<int>(); Stream<int> scLocal = sa.Map(x => x % 10).Merge(sb, (x, y) => x * y); Stream<int> sbOut = sa.Map(x => x / 10).Filter(x => x != 0); sb.Loop(sbOut); return scLocal; }); List<int> @out = new List<int>(); using (sc.Listen(@out.Add)) { sa.Send(2); sa.Send(52); } CollectionAssert.AreEqual(new[] { 2, 10 }, @out.ToArray()); }