コード例 #1
0
        /// <summary>
        /// Returns a data-producer that will ignore the
        /// elements from the start of a sequence while a condition
        /// (involving the elements's index in the sequence)
        /// is satsified; when the condition fails for an element,
        /// that element and all subsequent elements are yielded.
        /// </summary>
        /// <param name="source">The source data-producer</param>
        /// <param name="predicate">The condition to skip elements</param>
        public static IDataProducer <TSource> SkipWhile <TSource>(this IDataProducer <TSource> source, DotNet20.Func <TSource, int, bool> predicate)
        {
            source.ThrowIfNull("source");
            predicate.ThrowIfNull("predicate");

            DataProducer <TSource> ret = new DataProducer <TSource>();
            Action completion          = () => ret.End();

            bool skipping = true;
            int  index    = 0;

            source.DataProduced += value =>
            {
                if (skipping)
                {
                    skipping = predicate(value, index++);
                }
                // Note - not an else clause!
                if (!skipping)
                {
                    ret.Produce(value);
                }
            };
            source.EndOfData += completion;
            return(ret);
        }
コード例 #2
0
        /// <summary>
        /// Returns a data-producer that will yield a specified number of
        /// contiguous elements from the start of a sequence - i.e.
        /// "the first &lt;x&gt; elements".
        /// </summary>
        /// <param name="source">The source data-producer</param>
        /// <param name="count">The maximum number of elements to return</param>
        public static IDataProducer <TSource> Take <TSource>(this IDataProducer <TSource> source, int count)
        {
            source.ThrowIfNull("source");

            DataProducer <TSource> ret = new DataProducer <TSource>();

            Action           completion = () => ret.End();
            Action <TSource> production = null;

            production = value =>
            {
                if (count > 0)
                {
                    ret.Produce(value);
                    count--;
                }
                if (count <= 0)
                {
                    source.EndOfData    -= completion;
                    source.DataProduced -= production;
                    ret.End();
                }
            };

            source.DataProduced += production;
            source.EndOfData    += completion;
            return(ret);
        }
コード例 #3
0
        /// <summary>
        /// Returns a data-producer that will yield
        /// elements a sequence as long as a condition
        /// (involving the element's index in the sequence)
        /// is satsified; when the condition fails for an element,
        /// that element and all subsequent elements are ignored.
        /// </summary>
        /// <param name="source">The source data-producer</param>
        /// <param name="predicate">The condition to yield elements</param>
        public static IDataProducer <TSource> TakeWhile <TSource>(this IDataProducer <TSource> source, DotNet20.Func <TSource, int, bool> predicate)
        {
            source.ThrowIfNull("source");
            predicate.ThrowIfNull("predicate");

            DataProducer <TSource> ret  = new DataProducer <TSource>();
            Action           completion = () => ret.End();
            Action <TSource> production = null;

            int index = 0;

            production = value =>
            {
                if (!predicate(value, index++))
                {
                    ret.End();
                    source.DataProduced -= production;
                    source.EndOfData    -= completion;
                }
                else
                {
                    ret.Produce(value);
                }
            };

            source.DataProduced += production;
            source.EndOfData    += completion;
            return(ret);
        }
コード例 #4
0
        /// <summary>
        /// Returns a future that indicates whether any suitable values are
        /// yielded by the data-producer. The future will return false
        /// for an empty sequence or one with no matching values, or true for a sequence with matching values.
        /// </summary>
        /// <param name="source">The data-producer to be monitored.</param>
        /// <param name="predicate">The condition that must be satisfied.</param>
        public static IFuture <bool> Any <TSource>(this IDataProducer <TSource> source, DotNet20.Func <TSource, bool> predicate)
        {
            source.ThrowIfNull("source");
            predicate.ThrowIfNull("predicate");

            Future <bool> ret = new Future <bool>();

            Action <TSource> production = null;
            Action           completion = () => ret.Value = false;

            production = value =>
            {
                if (predicate(value))
                {
                    ret.Value            = true;
                    source.DataProduced -= production;
                    source.EndOfData    -= completion;
                }
            };

            source.DataProduced += production;
            source.EndOfData    += completion;

            return(ret);
        }
コード例 #5
0
        /// <summary>
        /// Returns a future to the element at the given position in the sequence,
        /// or the default-value if the specified index is never reached
        /// </summary>
        /// <param name="source">The data-producer</param>
        /// <param name="index">The index of the desired trem in the sequence</param>
        /// <exception cref="ArgumentOutOfRangeException">If the specified index is negative</exception>
        public static IFuture <TSource> ElementAtOrDefault <TSource>(this IDataProducer <TSource> source, int index)
        {
            source.ThrowIfNull("source");
            if (index < 0)
            {
                throw new ArgumentOutOfRangeException("index");
            }

            Future <TSource> ret = new Future <TSource>();

            Action           completion = () => ret.Value = default(TSource);
            Action <TSource> production = null;

            production = value =>
            {
                if (index == 0)
                {
                    ret.Value            = value;
                    source.DataProduced -= production;
                    source.EndOfData    -= completion;
                }
                else
                {
                    index--;
                }
            };

            source.DataProduced += production;
            source.EndOfData    += completion;

            return(ret);
        }
コード例 #6
0
        /// <summary>
        /// Returns a future that indicates whether any values are
        /// yielded by the data-producer. The future will return false
        /// for an empty sequence, or true for a sequence with values.
        /// </summary>
        /// <param name="source">The data-producer to be monitored.</param>
        public static IFuture <bool> Any <TSource>(this IDataProducer <TSource> source)
        {
            source.ThrowIfNull("source");

            Future <bool> ret = new Future <bool>();

            Action <TSource> production = null;
            Action           completion = () => ret.Value = false;

            production = value =>
            {
                ret.Value            = true;
                source.DataProduced -= production;
                source.EndOfData    -= completion;
            };

            source.DataProduced += production;
            source.EndOfData    += completion;

            return(ret);
        }
コード例 #7
0
        /// <summary>
        /// Returns a future to the first value from a sequence that matches the given condition, or the default
        /// for that type if no matching value is produced.
        /// </summary>
        /// <param name="source">The source data-producer.</param>
        /// <param name="predicate">The condition to be satisfied.</param>
        public static IFuture <TSource> FirstOrDefault <TSource>(this IDataProducer <TSource> source, DotNet20.Func <TSource, bool> predicate)
        {
            source.ThrowIfNull("source");
            predicate.ThrowIfNull("predicate");

            Future <TSource> ret = new Future <TSource>();

            Action           completion = () => ret.Value = default(TSource);
            Action <TSource> production = null;

            production = t =>
            {
                if (predicate(t))
                {
                    ret.Value            = t;
                    source.EndOfData    -= completion;
                    source.DataProduced -= production;
                }
            };
            source.DataProduced += production;
            source.EndOfData    += completion;

            return(ret);
        }
コード例 #8
0
        /// <summary>
        /// Returns the first element in a sequence that satisfies a specified condition, as a future value.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements of source.</typeparam>
        /// <param name="source">The sequence to an element from.</param>
        /// <param name="predicate">A function to test each element for a condition.</param>
        /// <returns>The first element in the specified sequence that passes the test in
        /// the specified predicate function, as a future value.
        /// The actual value can only be retrieved after the source has indicated the end
        /// of its data.
        /// </returns>
        public static IFuture <TSource> First <TSource>(this IDataProducer <TSource> source, DotNet20.Func <TSource, bool> predicate)
        {
            source.ThrowIfNull("source");
            predicate.ThrowIfNull("predicate");

            Future <TSource> ret = new Future <TSource>();

            Action           completion = () => { throw new InvalidOperationException("Sequence is empty"); };
            Action <TSource> production = null;

            production = t =>
            {
                if (predicate(t))
                {
                    ret.Value            = t;
                    source.EndOfData    -= completion;
                    source.DataProduced -= production;
                }
            };
            source.DataProduced += production;
            source.EndOfData    += completion;

            return(ret);
        }