/// ///Unwrap a behavior inside another behavior to give a time-varying behavior implementation. /// public static Behavior <TA> SwitchB <TA>(Behavior <Behavior <TA> > bba) { Func <TA> za = () => bba.SampleNoTrans().SampleNoTrans(); var @out = new EventSink <TA>(); var h = new TransactionHandler <Behavior <TA> >(); h.Run = (trans2, ba) => { // Note: If any switch takes place during a transaction, then the // value().listen will always cause a sample to be fetched from the // one we just switched to. The caller will be fetching our output // using value().listen, and value() throws away all firings except // for the last one. Therefore, anything from the old input behaviour // that might have happened during this transaction will be suppressed. if (h.CurrentListener != null) { h.CurrentListener.Unlisten(); } h.CurrentListener = ba.Value(trans2).Listen( @out.Node, trans2, new TransactionHandler <TA> { Run = (trans3, a) => @out.Send(trans3, a) }, false); }; Listener l1 = bba.Value().Listen_(@out.Node, h); return(@out.AddCleanup(l1).HoldLazy(za)); }
/// <summary> /// Unwrap a behavior inside another behavior to give a time-varying behavior implementation. /// </summary> /// <typeparam name="T">The type of the behavior.</typeparam> /// <param name="bba">The behavior containing another behavior.</param> /// <returns>The unwrapped behavior.</returns> public static Behavior <T> SwitchC <T>(this Behavior <Behavior <T> > bba) { return(Transaction.Apply( trans1 => { Lazy <T> za = bba.SampleLazy().Map(ba => ba.Sample()); Stream <T> @out = new Stream <T>(bba.KeepListenersAlive); MutableListener currentListener = new MutableListener(); void H(Transaction trans2, Behavior <T> ba) { currentListener.Unlisten(); currentListener.SetListener(ba.Value(trans2).Listen(@out.Node, trans2, @out.Send, false)); } IListener l1 = bba.Value(trans1).Listen(@out.Node, trans1, H, false); return @out.UnsafeAttachListener(l1).UnsafeAttachListener(currentListener).HoldLazyInternal(trans1, za); }, false)); }
/// <summary> /// A stream that is guaranteed to fire once upon listening, giving the current /// value of a behavior, and thereafter gives the updates/steps for the behavior. /// </summary> /// <typeparam name="T">The type of the values in the behavior.</typeparam> /// <param name="b"></param> /// <returns></returns> /// <remarks> /// This is an OPERATIONAL primitive, which is not part of the main Sodium /// API. It breaks the property of non-detectability of behavior steps/updates. /// The rule with this primitive is that you should only use it in functions /// that do not allow the caller to detect the behavior updates. /// </remarks> public static Stream <T> Value <T>(Behavior <T> b) => Transaction.Apply((trans, _) => b.Value(trans), false);