/// <summary> /// Divide to future values that are integers. Return a double (as we should be!!). /// </summary> /// <param name="numerator"></param> /// <param name="denominator"></param> /// <returns></returns> public static IFutureValue <double> DivideBy(this IFutureValue <int> numerator, IFutureValue <int> denominator) { return(new DoFutureOperator <double>( () => ((double)numerator.Value) / ((double)denominator.Value), () => numerator.HasValue && denominator.HasValue, () => Task.WhenAll(numerator.GetAvailibleTask(), denominator.GetAvailibleTask()))); }
/// <summary> /// When requested, we will extract the value from the source. /// </summary> /// <typeparam name="TSource"></typeparam> /// <typeparam name="TResult"></typeparam> /// <param name="source"></param> /// <param name="extractor"></param> /// <returns></returns> public static IFutureValue <TResult> ExtractValue <TSource, TResult>(this IFutureValue <TSource> source, Func <TSource, TResult> extractor) { return(new DoFutureOperator <TResult>( () => extractor(source.Value), () => source.HasValue, () => source.GetAvailibleTask() )); }
/// <summary> /// Select pattern - so that one can access the monad in situ. /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="M"></typeparam> /// <param name="self"></param> /// <param name="map"></param> /// <returns></returns> public static IFutureValue <T> Select <T, M>(this IFutureValue <M> self, Func <M, T> map) { return(new DoFutureOperator <T>( () => map(self.Value), () => self.HasValue, () => self.GetAvailibleTask() )); }
/// <summary> /// Return a FV that contains the cast held object. /// </summary> /// <typeparam name="TResult">The type for the result of the cast</typeparam> /// <returns>A FV that holds onto the cast version of the original value</returns> public IFutureValue <TResult> To <TResult>() where TResult : class { return(new DoFutureOperator <TResult>( () => _value.Value as TResult, () => _value.HasValue, () => _value.GetAvailibleTask() )); }
/// <summary> /// Returns a future value that uses two different future values to calculate a third. A Func does the /// actual manipulation. /// </summary> /// <typeparam name="TSource1"></typeparam> /// <typeparam name="TSource2"></typeparam> /// <typeparam name="TResult"></typeparam> /// <param name="source1"></param> /// <param name="source2"></param> /// <param name="extractor"></param> /// <returns></returns> public static IFutureValue <TResult> ExtractValue <TSource1, TSource2, TResult>(this IFutureValue <TSource1> source1, IFutureValue <TSource2> source2, Func <TSource1, TSource2, TResult> extractor) { return(new DoFutureOperator <TResult>( () => extractor(source1.Value, source2.Value), () => source2.HasValue && source1.HasValue, () => Task.WhenAll(source1.GetAvailibleTask(), source2.GetAvailibleTask()) )); }
/// <summary> /// Implement the select many pattern to allow monadic calculations /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="U"></typeparam> /// <typeparam name="V"></typeparam> /// <param name="self"></param> /// <param name="select"></param> /// <param name="project"></param> /// <returns>A future value that applies the projection operator</returns> /// <remarks> /// The projection is straight forward SelectMany (not that it is straight forward in any way). /// Doing the HasValue guy, however, is not, as we want to be a little careful not to call Value /// on anything that doesn't have a value yet. So we are relying on the fact that self.Value won't /// get calculated until after the self.HasValue has been "ok"d. /// </remarks> public static IFutureValue <V> SelectMany <T, U, V>( this IFutureValue <T> self, Func <T, IFutureValue <U> > select, Func <T, U, V> project) { var fvcache = new FutureValueCache <T>(self); return(new DoFutureOperator <V>( () => { var resT = fvcache.GetValue(); var resUOpt = select(resT); var resU = resUOpt.Value; var resV = project(resT, resU); return resV; }, () => self.HasValue && select(fvcache.GetValue()).HasValue, () => Task.WhenAll(self.GetAvailibleTask(), select(fvcache.GetValue()).GetAvailibleTask()) )); }
public void OnCompleted(Action continuation) { _ifv.GetAvailibleTask().ContinueWith(t => continuation()); }