diff --git a/src/buildfromsource/FSharp.Core/FSharp.Core.fsproj b/src/buildfromsource/FSharp.Core/FSharp.Core.fsproj index 2e4e9bb148e..20cd0e2f9ca 100644 --- a/src/buildfromsource/FSharp.Core/FSharp.Core.fsproj +++ b/src/buildfromsource/FSharp.Core/FSharp.Core.fsproj @@ -64,12 +64,30 @@ Collections/collections.fs + + Collections/list.fsi + + + Collections/list.fs + + + Collections/array.fsi + + + Collections/array.fs + Collections/seqcore.fsi Collections/seqcore.fs + + Collections/iseq.fsi + + + Collections/iseq.fs + Collections/seq.fsi @@ -95,7 +113,7 @@ Collections/array.fs - Collections/array3.fsi + Collections/array.fsi Collections/array3.fs diff --git a/src/fsharp/FSharp.Core/FSharp.Core.fsproj b/src/fsharp/FSharp.Core/FSharp.Core.fsproj index 1da4c6da6d6..d90a03c34be 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.fsproj +++ b/src/fsharp/FSharp.Core/FSharp.Core.fsproj @@ -92,12 +92,30 @@ Collections/collections.fs + + Collections/list.fsi + + + Collections/list.fs + + + Collections/array.fsi + + + Collections/array.fs + Collections/seqcore.fsi Collections/seqcore.fs + + Collections/iseq.fsi + + + Collections/iseq.fs + Collections/seq.fsi @@ -110,18 +128,6 @@ Collections/string.fs - - Collections/list.fsi - - - Collections/list.fs - - - Collections/array.fsi - - - Collections/array.fs - Collections/array3.fsi diff --git a/src/fsharp/FSharp.Core/array.fs b/src/fsharp/FSharp.Core/array.fs index f9cced85d3b..271d9cf9529 100644 --- a/src/fsharp/FSharp.Core/array.fs +++ b/src/fsharp/FSharp.Core/array.fs @@ -8,7 +8,6 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Core open Microsoft.FSharp.Collections open Microsoft.FSharp.Core.Operators - open Microsoft.FSharp.Core.CompilerServices open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators #if FX_RESHAPED_REFLECTION open System.Reflection @@ -97,12 +96,22 @@ namespace Microsoft.FSharp.Collections j <- j + len res + [] + let toSeq array = + checkNonNull "array" array + Microsoft.FSharp.Primitives.Basics.Array.toSeq array + + [] + let ofSeq source = + checkNonNull "source" source + Microsoft.FSharp.Primitives.Basics.Array.ofSeq source + [] let concat (arrays: seq<'T[]>) = checkNonNull "arrays" arrays match arrays with | :? ('T[][]) as ts -> ts |> concatArrays // avoid a clone, since we only read the array - | _ -> arrays |> Seq.toArray |> concatArrays + | _ -> arrays |> ofSeq |> concatArrays [] let replicate count initial = @@ -182,7 +191,7 @@ namespace Microsoft.FSharp.Collections let countByValueType (projection:'T->'Key) (array:'T[]) = countByImpl HashIdentity.Structural<'Key> projection id array // Wrap a StructBox around all keys in case the key type is itself a type using null as a representation - let countByRefType (projection:'T->'Key) (array:'T[]) = countByImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun t -> RuntimeHelpers.StructBox (projection t)) (fun sb -> sb.Value) array + let countByRefType (projection:'T->'Key) (array:'T[]) = countByImpl StructBox<'Key>.Comparer (fun t -> StructBox (projection t)) (fun sb -> sb.Value) array [] let countBy (projection:'T->'Key) (array:'T[]) = @@ -432,7 +441,7 @@ namespace Microsoft.FSharp.Collections let groupByValueType (keyf:'T->'Key) (array:'T[]) = groupByImpl HashIdentity.Structural<'Key> keyf id array // Wrap a StructBox around all keys in case the key type is itself a type using null as a representation - let groupByRefType (keyf:'T->'Key) (array:'T[]) = groupByImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun t -> RuntimeHelpers.StructBox (keyf t)) (fun sb -> sb.Value) array + let groupByRefType (keyf:'T->'Key) (array:'T[]) = groupByImpl StructBox<'Key>.Comparer (fun t -> StructBox (keyf t)) (fun sb -> sb.Value) array [] let groupBy (projection:'T->'Key) (array:'T[]) = @@ -1051,16 +1060,6 @@ namespace Microsoft.FSharp.Collections let inline compareDescending a b = compare b a sortWith compareDescending array - [] - let toSeq array = - checkNonNull "array" array - Seq.ofArray array - - [] - let ofSeq source = - checkNonNull "source" source - Seq.toArray source - [] let findIndex predicate (array : _[]) = checkNonNull "array" array @@ -1256,7 +1255,7 @@ namespace Microsoft.FSharp.Collections checkNonNull "arrays" arrays match arrays with | :? ('T[][]) as ts -> ts |> transposeArrays // avoid a clone, since we only read the array - | _ -> arrays |> Seq.toArray |> transposeArrays + | _ -> arrays |> Microsoft.FSharp.Primitives.Basics.Array.ofSeq |> transposeArrays [] let truncate count (array:'T[]) = diff --git a/src/fsharp/FSharp.Core/collections.fs b/src/fsharp/FSharp.Core/collections.fs index bd200a7bd75..a04577f4a4a 100644 --- a/src/fsharp/FSharp.Core/collections.fs +++ b/src/fsharp/FSharp.Core/collections.fs @@ -48,3 +48,12 @@ namespace Microsoft.FSharp.Collections { new IComparer<'T> with member __.Compare(x,y) = comparer.Invoke(x,y) } + [] + type internal StructBox<'T when 'T:equality>(value:'T) = + member x.Value = value + static member Comparer = + let gcomparer = HashIdentity.Structural<'T> + { new IEqualityComparer> with + member __.GetHashCode(v) = gcomparer.GetHashCode(v.Value) + member __.Equals(v1,v2) = gcomparer.Equals(v1.Value,v2.Value) } + diff --git a/src/fsharp/FSharp.Core/collections.fsi b/src/fsharp/FSharp.Core/collections.fsi index ad7f4363d1b..a581c80c3fd 100644 --- a/src/fsharp/FSharp.Core/collections.fsi +++ b/src/fsharp/FSharp.Core/collections.fsi @@ -49,4 +49,8 @@ namespace Microsoft.FSharp.Collections // inline justification: allows inlining of hash functions val inline FromFunctions<'T> : hasher:('T -> int) -> equality:('T -> 'T -> bool) -> IEqualityComparer<'T> - + [] + type internal StructBox<'T when 'T : equality> = + new : value:'T -> StructBox<'T> + member Value : 'T + static member Comparer : IEqualityComparer> diff --git a/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs b/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs index 63cb2d80718..28a229e483c 100644 --- a/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs +++ b/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs @@ -134,7 +134,7 @@ module ExtraTopLevelOperators = let dictValueType (l:seq<'Key*'T>) = dictImpl HashIdentity.Structural<'Key> id id l // Wrap a StructBox around all keys in case the key type is itself a type using null as a representation - let dictRefType (l:seq<'Key*'T>) = dictImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun k -> RuntimeHelpers.StructBox k) (fun sb -> sb.Value) l + let dictRefType (l:seq<'Key*'T>) = dictImpl StructBox<'Key>.Comparer (fun k -> StructBox k) (fun sb -> sb.Value) l [] let dict (keyValuePairs:seq<'Key*'T>) : IDictionary<'Key,'T> = diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs new file mode 100644 index 00000000000..290a1038c98 --- /dev/null +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -0,0 +1,1418 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.FSharp.Collections + open System + open System.Diagnostics + open System.Collections + open System.Collections.Generic + open System.Reflection + open Microsoft.FSharp.Core + open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators + open Microsoft.FSharp.Core.Operators + open Microsoft.FSharp.Core.CompilerServices + open Microsoft.FSharp.Control + open Microsoft.FSharp.Collections + open Microsoft.FSharp.Primitives + open Microsoft.FSharp.Primitives.Basics + open Microsoft.FSharp.Collections.SeqComposition + open Microsoft.FSharp.Collections.SeqComposition.Core + + [] + module IConsumableSeq = + open IEnumerator + + /// Base classes and helpers for object expressions that represent the Activitys in + /// the IConsumableSeq chain + module Core = + /// Single value Tuple. + /// Allows null reference type values as key in Dictionary. + [] + type internal Value<'T> = + val mutable _1 : 'T + new (a:'T) = { _1 = a } + + /// 2-Value Tuple. + [] + type Values<'T1,'T2> = + val mutable _1 : 'T1 + val mutable _2 : 'T2 + new (a:'T1, b: 'T2) = { _1 = a; _2 = b } + + /// 3-Value Tuple. + [] + type internal Values<'T1,'T2,'T3> = + val mutable _1 : 'T1 + val mutable _2 : 'T2 + val mutable _3 : 'T3 + new (a:'T1, b:'T2, c:'T3) = { _1 = a; _2 = b; _3 = c } + + /// Base class for chaining mapping or filtering operation within the IConsumableSeq pipeline + [] + type internal SeqTransformActivity<'T,'U,'State> = + inherit SeqConsumerActivity<'T,'U> + + new (next:SeqConsumerActivity, initState:'State) = { + State = initState + Next = next + } + + val mutable State : 'State + val Next : SeqConsumerActivity + + override this.ChainComplete terminatingIdx = + this.Next.ChainComplete terminatingIdx + + override this.ChainDispose () = + this.Next.ChainDispose () + + /// Base class for chaining mapping or filtering operation that require some post processing + /// (i.e. Disposal and/or post conditional checks) within the IConsumableSeq pipeline + [] + type internal SeqTransformActivityWithPostProcessing<'T,'U,'State>(next:SeqConsumerActivity, initState:'State) = + inherit SeqTransformActivity<'T,'U,'State>(next, initState) + + abstract OnComplete : pipeIdx:PipeIdx -> unit + abstract OnDispose : unit -> unit + + override this.ChainComplete terminatingIdx = + this.OnComplete terminatingIdx + this.Next.ChainComplete terminatingIdx + + override this.ChainDispose () = + try this.OnDispose () + finally this.Next.ChainDispose () + + /// Base class for folding operation within the IConsumableSeq pipeline + [] + type SeqConsumerWithState<'T,'Result,'State> = + inherit SeqConsumer<'T,'Result> + + val mutable State : 'State + + new (initalResult,initState) = { + inherit SeqConsumer<'T,'Result>(initalResult) + State = initState + } + + /// Base class for folding operation that require some post processing + /// (i.e. Disposal and/or post conditional checks) within the IConsumableSeq pipeline + [] + type SeqConsumerWithPostProcessing<'T,'Result,'State>(initResult,initState) = + inherit SeqConsumerWithState<'T,'Result,'State>(initResult,initState) + + abstract OnComplete : pipeIdx:PipeIdx -> unit + abstract OnDispose : unit -> unit + + override this.ChainComplete terminatingIdx = + this.OnComplete terminatingIdx + + override this.ChainDispose () = + this.OnDispose () + + open Core + + module internal TailCall = + // used for performance reasons; these are not recursive calls, so should be safe + // ** it should be noted that potential changes to the f# compiler may render this function + // ineffective - i.e. this function shouldn't do anything, it just happens to be complex + // enough to fool the compiler into erasing it's behaviour, but making the calling + // function invalid for tail call optimization (No invesigation beyond observing behaviour) ** + let inline avoid boolean = match boolean with true -> true | false -> false + + let inline internal valueComparer<'T when 'T : equality> () = + let c = HashIdentity.Structural<'T> + { new IEqualityComparer> with + member __.GetHashCode o = c.GetHashCode o._1 + member __.Equals (lhs,rhs) = c.Equals (lhs._1, rhs._1) } + + /// Usually the implementation of GetEnumerator is handled by the IConsumableSeq<'T>.Consume operation, + /// but there can be cases where it is more efficent to provide a specific IEnumerator, and + /// only defer to the IConsumableSeq<'T> interface for its specific operations (this is the case with + /// the scan function) + [] + type internal PreferGetEnumerator<'T>() = + inherit EnumerableBase<'T>() + + abstract GetEnumerator: unit -> IEnumerator<'T> + abstract GetSeq : unit -> IConsumableSeq<'T> + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = this.GetEnumerator () + + interface IConsumableSeq<'T> with + member this.Transform<'U> (next:ISeqTransform<'T,'U>) : IConsumableSeq<'U> = (this.GetSeq()).Transform next + member this.Consume<'Result> (f:PipeIdx->SeqConsumer<'T,'Result>) : 'Result = (this.GetSeq()).Consume f + + [] + let internal empty<'T> = Microsoft.FSharp.Collections.SeqComposition.Core.EmptyEnumerable<'T>.Instance + + [] + let internal singleton<'T> (value:'T) : IConsumableSeq<'T> = new SingletonEnumerable<_>(value) :> _ + + /// wraps a ResizeArray in the IConsumableSeq framework. Care must be taken that the underlying ResizeArray + /// is not modified whilst it can be accessed as the IConsumableSeq, so check on version is performed. + /// i.e. usually iteration on calls the enumerator provied by GetEnumerator ensure that the + /// list hasn't been modified (throwing an exception if it has), but such a check is not + /// performed in this case. If you want this functionality, then use the ofSeq function instead. + [] + let internal ofResizeArrayUnchecked (source:ResizeArray<'T>) : IConsumableSeq<'T> = + ThinResizeArrayEnumerable<'T> source :> _ + + [] + let internal ofArray (source:array<'T>) : IConsumableSeq<'T> = + checkNonNull "source" source + ThinArrayEnumerable<'T> source :> _ + + [] + let internal ofList (source:list<'T>) : IConsumableSeq<'T> = + source :> _ + + [] + let ofSeq (source:seq<'T>) : IConsumableSeq<'T> = + match source with + | :? IConsumableSeq<'T> as seq -> seq + | :? array<'T> as array -> ofArray array + | null -> nullArg "source" + | _ -> ThinEnumerable<'T> source :> _ + + [] + let inline average (source:IConsumableSeq<'T>) = + source.Consume (fun _ -> + { new SeqConsumerWithPostProcessing<'T,'T,int> (LanguagePrimitives.GenericZero, 0) with + override this.ProcessNext value = + this.Result <- Checked.(+) this.Result value + this.State <- this.State + 1 + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = + if this.State = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + this.Result <- LanguagePrimitives.DivideByInt<'T> this.Result this.State + + override this.OnDispose () = () } :> _) + + [] + let inline averageBy (f:'T->'U) (source:IConsumableSeq<'T>) = + source.Consume (fun _ -> + { new SeqConsumerWithPostProcessing<'T,'U,int>(LanguagePrimitives.GenericZero,0) with + override this.ProcessNext value = + this.Result <- Checked.(+) this.Result (f value) + this.State <- this.State + 1 + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = + if this.State = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + this.Result <- LanguagePrimitives.DivideByInt<'U> this.Result this.State + + override this.OnDispose () = () } :> _) + + [] + let internal exactlyOne (source:IConsumableSeq<'T>) : 'T = + source.Consume (fun pipeIdx -> + { new SeqConsumerWithPostProcessing<'T,'T,Values>(Unchecked.defaultof<'T>, Values(true, false)) with + override this.ProcessNext value = + if this.State._1 then + this.State._1 <- false + this.Result <- value + else + this.State._2 <- true + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = + if this.State._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + elif this.State._2 then + invalidArg "source" (SR.GetString SR.inputSequenceTooLong) + + override this.OnDispose () = () } :> _) + + [] + let inline internal fold<'T,'State> (f:'State->'T->'State) (seed:'State) (source:IConsumableSeq<'T>) : 'State = + source.Consume (fun _ -> + { new SeqConsumer<'T,'State>(seed) with + override this.ProcessNext value = + this.Result <- f this.Result value + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline internal fold2<'T1,'T2,'State> (folder:'State->'T1->'T2->'State) (state:'State) (source1:IConsumableSeq<'T1>) (source2: IConsumableSeq<'T2>) = + source1.Consume (fun pipeIdx -> + { new SeqConsumerWithPostProcessing<_,'State,IEnumerator<'T2>>(state,source2.GetEnumerator()) with + override this.ProcessNext value = + if this.State.MoveNext() then + this.Result <- folder this.Result value this.State.Current + else + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = () + + override this.OnDispose () = this.State.Dispose () } :> _) + + [] + let internal unfold (generator:'State->option<'T * 'State>) (state:'State) : IConsumableSeq<'T> = + new UnfoldEnumerable<'T,'T,'State>(generator, state, IdentityTransform.Instance, 1) :> _ + + [] + let internal initInfinite<'T> (f:int->'T) : IConsumableSeq<'T> = + new InitEnumerableDecider<'T>(Nullable (), f, 1) :> _ + + [] + let internal init<'T> (count:int) (f:int->'T) : IConsumableSeq<'T> = + if count < 0 then invalidArgInputMustBeNonNegative "count" count + elif count = 0 then empty else + new InitEnumerableDecider<'T>(Nullable count, f, 1) :> _ + + [] + let inline internal iter action (source:IConsumableSeq<'T>) = + source.Consume (fun _ -> + { new SeqConsumer<'T,unit> (()) with + override this.ProcessNext value = + action value + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline internal iter2 (action:'T->'U->unit) (source1:IConsumableSeq<'T>) (source2:IConsumableSeq<'U>) : unit = + source1.Consume (fun pipeIdx -> + { new SeqConsumerWithPostProcessing<'T,unit,IEnumerator<'U>> ((),source2.GetEnumerator()) with + override this.ProcessNext value = + if this.State.MoveNext() then + action value this.State.Current + else + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = () + + override this.OnDispose () = this.State.Dispose () } :> _) + + [] + let inline internal iteri2 (action:int->'T->'U->unit) (source1:IConsumableSeq<'T>) (source2:IConsumableSeq<'U>) : unit = + source1.Consume (fun pipeIdx -> + { new SeqConsumerWithPostProcessing<'T,unit,Values>>((),Values<_,_>(0,source2.GetEnumerator())) with + override this.ProcessNext value = + if this.State._2.MoveNext() then + action this.State._1 value this.State._2.Current + this.State._1 <- this.State._1 + 1 + Unchecked.defaultof<_> + else + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> + + override this.OnComplete _ = () + + override this.OnDispose () = this.State._2.Dispose () } :> _) + + [] + let internal tryHead (source:IConsumableSeq<'T>) = + source.Consume (fun pipeIdx -> + { new SeqConsumer<'T, Option<'T>> (None) with + override this.ProcessNext value = + this.Result <- Some value + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let internal head (source:IConsumableSeq<_>) = + match tryHead source with + | None -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + | Some x -> x + + [] + let inline internal iteri action (source:IConsumableSeq<'T>) = + source.Consume (fun _ -> + { new SeqConsumerWithState<'T,unit,int> ((),0) with + override this.ProcessNext value = + action this.State value + this.State <- this.State + 1 + Unchecked.defaultof<_> (* return value unused in Fold context *) } :> _) + + [] + let inline internal except (itemsToExclude: seq<'T>) (source:IConsumableSeq<'T>) : IConsumableSeq<'T> when 'T:equality = + checkNonNull "itemsToExclude" itemsToExclude + source.Transform + { new ISeqTransform<'T,'T> with + override __.Compose _ _ next = + { new SeqTransformActivity<'T,'V,Lazy>>(next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with + override this.ProcessNext (input:'T) : bool = + this.State.Value.Add input && TailCall.avoid (next.ProcessNext input) } :> _} + + [] + let inline internal exists predicate (source:IConsumableSeq<'T>) = + source.Consume (fun pipeIdx -> + { new SeqConsumer<'T, bool> (false) with + override this.ProcessNext value = + if predicate value then + this.Result <- true + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline internal exists2 (predicate:'T->'U->bool) (source1:IConsumableSeq<'T>) (source2: IConsumableSeq<'U>) : bool = + source1.Consume (fun pipeIdx -> + { new SeqConsumerWithPostProcessing<'T,bool,IEnumerator<'U>>(false,source2.GetEnumerator()) with + override this.ProcessNext value = + if this.State.MoveNext() then + if predicate value this.State.Current then + this.Result <- true + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + else + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = () + + override this.OnDispose () = this.State.Dispose () } :> _) + + [] + let inline contains element (source:IConsumableSeq<'T>) = + source.Consume (fun pipeIdx -> + { new SeqConsumer<'T, bool> (false) with + override this.ProcessNext value = + if element = value then + this.Result <- true + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline internal forall predicate (source:IConsumableSeq<'T>) = + source.Consume (fun pipeIdx -> + { new SeqConsumer<'T, bool> (true) with + override this.ProcessNext value = + if not (predicate value) then + this.Result <- false + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline internal forall2 predicate (source1:IConsumableSeq<'T>) (source2:IConsumableSeq<'U>) : bool = + source1.Consume (fun pipeIdx -> + { new SeqConsumerWithPostProcessing<'T,bool,IEnumerator<'U>>(true,source2.GetEnumerator()) with + override this.ProcessNext value = + if this.State.MoveNext() then + if not (predicate value this.State.Current) then + this.Result <- false + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + else + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = () + + override this.OnDispose () = this.State.Dispose () } :> _) + + [] + let inline internal filter<'T> (predicate:'T->bool) (source:IConsumableSeq<'T>) : IConsumableSeq<'T> = + source.Transform + { new ISeqTransform<'T,'T> with + override __.Compose _ _ next = + { new SeqTransformActivity<'T,'V,NoValue>(next,Unchecked.defaultof) with + override __.ProcessNext input = + if predicate input then TailCall.avoid (next.ProcessNext input) + else false } :> _} + + [] + let inline internal map<'T,'U> (mapping:'T->'U) (source:IConsumableSeq<'T>) : IConsumableSeq<'U> = + source.Transform + { new ISeqTransform<'T,'U> with + override __.Compose _ _ next = + { new SeqTransformActivity<'T,'V,NoValue>(next,Unchecked.defaultof) with + override __.ProcessNext input = + TailCall.avoid (next.ProcessNext (mapping input)) } :> _ } + + [] + let inline internal mapi mapping (source:IConsumableSeq<_>) = + source.Transform + { new ISeqTransform<'T,'U> with + override __.Compose _ _ next = + { new SeqTransformActivity<'T,'V,int>(next, -1) with + override this.ProcessNext (input:'T) : bool = + this.State <- this.State + 1 + TailCall.avoid (next.ProcessNext (mapping this.State input)) } :> _ } + + [] + let inline internal map2<'T,'U,'V> (mapping:'T->'U->'V) (source1:IConsumableSeq<'T>) (source2:IConsumableSeq<'U>) : IConsumableSeq<'V> = + source1.Transform + { new ISeqTransform<'T,'V> with + override __.Compose outOfBand pipeIdx (next:SeqConsumerActivity<'V,'W>) = + { new SeqTransformActivityWithPostProcessing<'T,'W, IEnumerator<'U>>(next, (source2.GetEnumerator ())) with + override this.ProcessNext input = + if this.State.MoveNext () then + TailCall.avoid (next.ProcessNext (mapping input this.State.Current)) + else + outOfBand.StopFurtherProcessing pipeIdx + false + + override this.OnComplete _ = () + + override this.OnDispose () = this.State.Dispose () } :> _ } + + [] + let inline internal mapi2<'T,'U,'V> (mapping:int->'T->'U->'V) (source1:IConsumableSeq<'T>) (source2:IConsumableSeq<'U>) : IConsumableSeq<'V> = + source1.Transform + { new ISeqTransform<'T,'V> with + override __.Compose<'W> outOfBand pipeIdx next = + { new SeqTransformActivityWithPostProcessing<'T,'W, Values>>(next, Values<_,_>(-1,source2.GetEnumerator ())) with + override this.ProcessNext t = + let idx : byref<_> = &this.State._1 + let u = this.State._2 + if u.MoveNext () then + idx <- idx + 1 + TailCall.avoid (next.ProcessNext (mapping idx t u.Current)) + else + outOfBand.StopFurtherProcessing pipeIdx + false + + override this.OnDispose () = this.State._2.Dispose () + + override this.OnComplete _ = () } :> _ } + + [] + let inline internal map3<'T,'U,'V,'W>(mapping:'T->'U->'V->'W) (source1:IConsumableSeq<'T>) (source2:IConsumableSeq<'U>) (source3:IConsumableSeq<'V>) : IConsumableSeq<'W> = + source1.Transform + { new ISeqTransform<'T,'W> with + override __.Compose<'X> outOfBand pipeIdx next = + { new SeqTransformActivityWithPostProcessing<'T,'X,Values,IEnumerator<'V>>>(next,Values<_,_>(source2.GetEnumerator(),source3.GetEnumerator())) with + override this.ProcessNext t = + let u = this.State._1 + let v = this.State._2 + if u.MoveNext() && v.MoveNext () then + TailCall.avoid (next.ProcessNext (mapping t u.Current v.Current)) + else + outOfBand.StopFurtherProcessing pipeIdx + false + + override this.OnComplete _ = () + + override this.OnDispose () = + this.State._1.Dispose () + this.State._2.Dispose () } :> _ } + + [] + let inline internal compareWith (comparer:'T->'T->int) (source1:IConsumableSeq<'T>) (source2:IConsumableSeq<'T>) : int = + source1.Consume (fun pipeIdx -> + { new SeqConsumerWithPostProcessing<'T,int,IEnumerator<'T>>(0,source2.GetEnumerator()) with + override this.ProcessNext value = + if not (this.State.MoveNext()) then + this.Result <- 1 + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + else + let c = comparer value this.State.Current + if c <> 0 then + this.Result <- c + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = + if this.Result = 0 && this.State.MoveNext() then + this.Result <- -1 + + override this.OnDispose () = this.State.Dispose () } :> _) + + [] + let inline internal choose (f:'T->option<'U>) (source:IConsumableSeq<'T>) : IConsumableSeq<'U> = + source.Transform + { new ISeqTransform<'T,'U> with + override __.Compose _ _ next = + { new SeqTransformActivity<'T,'V,NoValue>(next,Unchecked.defaultof) with + override __.ProcessNext input = + match f input with + | Some value -> TailCall.avoid (next.ProcessNext value) + | None -> false } :> _ } + + [] + let inline internal distinct (source:IConsumableSeq<'T>) : IConsumableSeq<'T> when 'T:equality = + source.Transform + { new ISeqTransform<'T,'T> with + override __.Compose _ _ next = + { new SeqTransformActivity<'T,'V,HashSet<'T>>(next,HashSet HashIdentity.Structural) with + override this.ProcessNext (input:'T) : bool = + this.State.Add input && TailCall.avoid (next.ProcessNext input) } :> _} + + [] + let inline internal distinctBy (keyf:'T->'Key) (source:IConsumableSeq<'T>) :IConsumableSeq<'T> when 'Key:equality = + source.Transform + { new ISeqTransform<'T,'T> with + override __.Compose _ _ next = + { new SeqTransformActivity<'T,'V,HashSet<'Key>> (next,HashSet HashIdentity.Structural) with + override this.ProcessNext (input:'T) : bool = + this.State.Add (keyf input) && TailCall.avoid (next.ProcessNext input) } :> _} + + [] + let inline max (source:IConsumableSeq<'T>) : 'T when 'T:comparison = + source.Consume (fun _ -> + { new SeqConsumerWithPostProcessing<'T,'T,bool>(Unchecked.defaultof<'T>,true) with + override this.ProcessNext value = + if this.State then + this.State <- false + this.Result <- value + elif value > this.Result then + this.Result <- value + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = + if this.State then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + + override this.OnDispose () = () } :> _) + + [] + let inline maxBy (f:'T->'U) (source:IConsumableSeq<'T>) : 'T when 'U:comparison = + source.Consume (fun _ -> + { new SeqConsumerWithPostProcessing<'T,'T,Values>(Unchecked.defaultof<'T>,Values<_,_>(true,Unchecked.defaultof<'U>)) with + override this.ProcessNext value = + match this.State._1, f value with + | true, valueU -> + this.State._1 <- false + this.State._2 <- valueU + this.Result <- value + | false, valueU when valueU > this.State._2 -> + this.State._2 <- valueU + this.Result <- value + | _ -> () + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = + if this.State._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + + override this.OnDispose () = () } :> _) + + [] + let inline min (source:IConsumableSeq<'T>) : 'T when 'T:comparison = + source.Consume (fun _ -> + { new SeqConsumerWithPostProcessing<'T,'T,bool>(Unchecked.defaultof<'T>,true) with + override this.ProcessNext value = + if this.State then + this.State <- false + this.Result <- value + elif value < this.Result then + this.Result <- value + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = + if this.State then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + + override this.OnDispose () = () } :> _) + + [] + let inline minBy (f:'T->'U) (source:IConsumableSeq<'T>) : 'T = + source.Consume (fun _ -> + { new SeqConsumerWithPostProcessing<'T,'T,Values>(Unchecked.defaultof<'T>,Values<_,_>(true,Unchecked.defaultof< 'U>)) with + override this.ProcessNext value = + match this.State._1, f value with + | true, valueU -> + this.State._1 <- false + this.State._2 <- valueU + this.Result <- value + | false, valueU when valueU < this.State._2 -> + this.State._2 <- valueU + this.Result <- value + | _ -> () + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = + if this.State._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + + override this.OnDispose () = () } :> _) + + [] + let internal pairwise (source:IConsumableSeq<'T>) : IConsumableSeq<'T*'T> = + source.Transform + { new ISeqTransform<'T,'T*'T> with + override __.Compose _ _ next = + { new SeqTransformActivity<'T,'U,Values>(next, Values(true, Unchecked.defaultof<'T>)) with + // member this.isFirst = this.State._1 + // member this.lastValue = this.State._2 + override this.ProcessNext (input:'T) : bool = + if this.State._1 then + this.State._2 <- input + this.State._1 <- false + false + else + let currentPair = this.State._2, input + this.State._2 <- input + TailCall.avoid (next.ProcessNext currentPair) } :> _} + + [] + let inline internal reduce (f:'T->'T->'T) (source: IConsumableSeq<'T>) : 'T = + source.Consume (fun _ -> + { new SeqConsumerWithPostProcessing<'T,'T,bool>(Unchecked.defaultof<'T>,true) with + override this.ProcessNext value = + if this.State then + this.State <- false + this.Result <- value + else + this.Result <- f this.Result value + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = + if this.State then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + + override this.OnDispose () = () } :> _) + + [] + let internal concat (sources:IConsumableSeq<#IConsumableSeq<'T>>) : IConsumableSeq<'T> = + ThinConcatEnumerable (sources, id) :> _ + + (* + Represents the following seq comprehension, but they don't work at this level + + seq { + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + let mutable state = initialState + yield state + for item in enumerable do + state <- f.Invoke (state, item) + yield state } + *) + type internal ScanEnumerator<'T,'State>(folder:'State->'T->'State, initialState:'State, enumerable:seq<'T>) = + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let mutable state = 0 (*Pre-start*) + let mutable enumerator = Unchecked.defaultof> + let mutable current = initialState + + interface IEnumerator<'State> with + member this.Current: 'State = + match state with + | 0(*PreStart*) -> notStarted() + | 1(*GetEnumerator*) -> current + | 2(*MoveNext*) -> current + | _(*Finished*) -> alreadyFinished() + + interface IEnumerator with + member this.Current : obj = + box (this:>IEnumerator<'State>).Current + + member this.MoveNext () : bool = + match state with + | 0(*PreStart*) -> + state <- 1(*GetEnumerator*) + true + | 1(*GetEnumerator*) -> + enumerator <- enumerable.GetEnumerator () + state <- 2(*MoveNext*) + (this:>IEnumerator).MoveNext () + | 2(*MoveNext*) -> + if enumerator.MoveNext () then + current <- f.Invoke (current, enumerator.Current) + true + else + current <- Unchecked.defaultof<_> + state <- 3(*Finished*) + false + | _(*Finished*) -> alreadyFinished() + + member this.Reset () : unit = noReset () + + interface IDisposable with + member this.Dispose(): unit = + if isNotNull enumerator then + enumerator.Dispose () + + [] + let internal scan (folder:'State->'T->'State) (initialState:'State) (source:IConsumableSeq<'T>) : IConsumableSeq<'State> = + { new PreferGetEnumerator<'State>() with + member this.GetEnumerator () = + new ScanEnumerator<'T,'State>(folder, initialState, source) :> _ + + member this.GetSeq () = + let head = singleton initialState + let tail = + source.Transform + { new ISeqTransform<'T,'State> with + override __.Compose _ _ next = + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + { new SeqTransformActivity<'T,'V,'State>(next, initialState) with + override this.ProcessNext (input:'T) : bool = + this.State <- f.Invoke (this.State, input) + TailCall.avoid (next.ProcessNext this.State) } :> _ } + concat (ofList [ head ; tail ]) } :> _ + + [] + let internal skip (skipCount:int) (source:IConsumableSeq<'T>) : IConsumableSeq<'T> = + source.Transform + { new ISeqTransform<'T,'T> with + override __.Compose _ _ next = + let mutable this = Unchecked.defaultof> + let skipper = + { new SeqTransformActivityWithPostProcessing<'T,'U,int>(next,(*count*)0) with + // member this.count = this.State + override this.ProcessNext (input:'T) : bool = + if this.State < skipCount then + this.State <- this.State + 1 + false + else + TailCall.avoid (next.ProcessNext input) + + override this.OnComplete _ = + if this.State < skipCount then + let x = skipCount - this.State + invalidOpFmt "{0}\ntried to skip {1} {2} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + + override this.OnDispose () = () + + interface ISkipable with + member __.CanSkip () = + if this.State < skipCount then + this.State <- this.State + 1 + true + else + false } + this <- skipper + this :> _ } + + [] + let inline internal skipWhile (predicate:'T->bool) (source:IConsumableSeq<'T>) : IConsumableSeq<'T> = + source.Transform + { new ISeqTransform<'T,'T> with + override __.Compose _ _ next = + { new SeqTransformActivity<'T,'V,bool>(next,true) with + // member this.skip = this.State + override this.ProcessNext (input:'T) : bool = + if this.State then + this.State <- predicate input + if this.State then + false + else + TailCall.avoid (next.ProcessNext input) + else + TailCall.avoid (next.ProcessNext input) } :> _} + + [] + let inline sum (source:IConsumableSeq<'T>) = + source.Consume (fun _ -> + { new SeqConsumer<'T,'T> (LanguagePrimitives.GenericZero) with + override this.ProcessNext value = + this.Result <- Checked.(+) this.Result value + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline sumBy (f:'T->'U) (source:IConsumableSeq<'T>) = + source.Consume (fun _ -> + { new SeqConsumer<'T,'U> (LanguagePrimitives.GenericZero<'U>) with + override this.ProcessNext value = + this.Result <- Checked.(+) this.Result (f value) + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let internal take (takeCount:int) (source:IConsumableSeq<'T>) : IConsumableSeq<'T> = + if takeCount < 0 then invalidArgInputMustBeNonNegative "count" takeCount + elif takeCount = 0 then empty + else + source.Transform + { new ISeqTransform<'T,'T> with + member __.Compose outOfBand pipelineIdx next = + if takeCount = 0 then + outOfBand.StopFurtherProcessing pipelineIdx + + { new SeqTransformActivityWithPostProcessing<'T,'U,int>(next,(*count*)0) with + // member this.count = this.State + override this.ProcessNext (input:'T) : bool = + if this.State < takeCount then + this.State <- this.State + 1 + if this.State = takeCount then + outOfBand.StopFurtherProcessing pipelineIdx + TailCall.avoid (next.ProcessNext input) + else + outOfBand.StopFurtherProcessing pipelineIdx + false + + override this.OnComplete terminatingIdx = + if terminatingIdx < pipelineIdx && this.State < takeCount then + let x = takeCount - this.State + invalidOpFmt "tried to take {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + + override this.OnDispose () = () } :> _} + + [] + let inline internal takeWhile (predicate:'T->bool) (source:IConsumableSeq<'T>) : IConsumableSeq<'T> = + source.Transform + { new ISeqTransform<'T,'T> with + member __.Compose outOfBand pipeIdx next = + { new SeqTransformActivity<'T,'V,NoValue>(next,Unchecked.defaultof) with + override __.ProcessNext (input:'T) : bool = + if predicate input then + TailCall.avoid (next.ProcessNext input) + else + outOfBand.StopFurtherProcessing pipeIdx + false } :> _ } + + [] + let internal tail (source:IConsumableSeq<'T>) : IConsumableSeq<'T> = + source.Transform + { new ISeqTransform<'T,'T> with + member __.Compose _ _ next = + { new SeqTransformActivityWithPostProcessing<'T,'V,bool>(next,true) with + // member this.isFirst = this.State + override this.ProcessNext (input:'T) : bool = + if this.State then + this.State <- false + false + else + TailCall.avoid (next.ProcessNext input) + + override this.OnComplete _ = + if this.State then + invalidArg "source" (SR.GetString SR.notEnoughElements) + + override this.OnDispose () = () } :> _ } + + [] + let internal truncate (truncateCount:int) (source:IConsumableSeq<'T>) : IConsumableSeq<'T> = + source.Transform + { new ISeqTransform<'T,'T> with + member __.Compose outOfBand pipeIdx next = + { new SeqTransformActivity<'T,'U,int>(next,(*count*)0) with + // member this.count = this.State + override this.ProcessNext (input:'T) : bool = + if this.State < truncateCount then + this.State <- this.State + 1 + if this.State = truncateCount then + outOfBand.StopFurtherProcessing pipeIdx + TailCall.avoid (next.ProcessNext input) + else + outOfBand.StopFurtherProcessing pipeIdx + false } :> _ } + + [] + let internal indexed source = + mapi (fun i x -> i,x) source + + [] + let internal tryItem index (source:IConsumableSeq<'T>) = + if index < 0 then None else + source.Transform + { new ISeqTransform<'T,'T> with + override __.Compose _ _ next = + let mutable this = Unchecked.defaultof> + let skipper = + { new SeqTransformActivity<'T,'U,int>(next,(*count*)0) with + // member this.count = this.State + override this.ProcessNext (input:'T) : bool = + if this.State < index then + this.State <- this.State + 1 + false + else + TailCall.avoid (next.ProcessNext input) + + interface ISkipable with + member __.CanSkip () = + if this.State < index then + this.State <- this.State + 1 + true + else + false } + this <- skipper + this :> _ } + |> tryHead + + [] + let inline internal tryPick f (source:IConsumableSeq<'T>) = + source.Consume (fun pipeIdx -> + { new SeqConsumer<'T, Option<'U>> (None) with + override this.ProcessNext value = + match f value with + | (Some _) as some -> + this.Result <- some + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + | None -> () + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline internal tryFind f (source:IConsumableSeq<'T>) = + source.Consume (fun pipeIdx -> + { new SeqConsumer<'T, Option<'T>> (None) with + override this.ProcessNext value = + if f value then + this.Result <- Some value + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline internal tryFindIndex (predicate:'T->bool) (source:IConsumableSeq<'T>) : int option = + source.Consume (fun pipeIdx -> + { new SeqConsumerWithState<'T, Option, int>(None, 0) with + // member this.index = this.State + override this.ProcessNext value = + if predicate value then + this.Result <- Some this.State + (this :> ISeqConsumer).StopFurtherProcessing pipeIdx + else + this.State <- this.State + 1 + Unchecked.defaultof<_> (* return value unused in Fold context *) } :> _) + + [] + let internal tryLast (source:IConsumableSeq<'T>) : 'T option = + source.Consume (fun _ -> + { new SeqConsumerWithPostProcessing<'T,option<'T>,Values>(None,Values(true, Unchecked.defaultof<'T>)) with + // member this.noItems = this.State._1 + // memebr this.last = this.State._2 + override this.ProcessNext value = + if this.State._1 then + this.State._1 <- false + this.State._2 <- value + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = + if not this.State._1 then + this.Result <- Some this.State._2 + + override this.OnDispose () = () } :> _) + + [] + let internal last (source:IConsumableSeq<_>) = + match tryLast source with + | None -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + | Some x -> x + + [] + let internal windowed (windowSize:int) (source:IConsumableSeq<'T>) : IConsumableSeq<'T[]> = + if windowSize <= 0 then + invalidArgFmt "windowSize" "{0}\nwindowSize = {1}" [|SR.GetString SR.inputMustBePositive; windowSize|] + + source.Transform + { new ISeqTransform<'T,'T[]> with + member __.Compose outOfBand pipeIdx next = + { + new SeqTransformActivity<'T,'U,Values<'T[],int,int>>(next,Values<'T[],int,int>(Array.zeroCreateUnchecked windowSize, 0, windowSize-1)) with + override this.ProcessNext (input:'T) : bool = + let circularBuffer = this.State._1 + let idx : byref<_> = &this.State._2 + let priming : byref<_> = &this.State._3 + + circularBuffer.[idx] <- input + + idx <- idx + 1 + if idx = windowSize then + idx <- 0 + + if priming > 0 then + priming <- priming - 1 + false + elif windowSize < 32 then + let idx = idx + let window :'T [] = Array.init windowSize (fun i -> circularBuffer.[(idx+i) % windowSize]: 'T) + TailCall.avoid (next.ProcessNext window) + else + let window = Array.zeroCreateUnchecked windowSize + Array.Copy (circularBuffer, idx, window, 0, windowSize - idx) + Array.Copy (circularBuffer, 0, window, windowSize - idx, idx) + TailCall.avoid (next.ProcessNext window) } :> _} + + [] + let internal append (source1:IConsumableSeq<'T>) (source2: IConsumableSeq<'T>) : IConsumableSeq<'T> = + match source1 with + | :? EnumerableBase<'T> as s -> s.Append source2 + | _ -> new AppendEnumerable<_>([source2; source1]) :> _ + + [] + let internal delay (delayed:unit->IConsumableSeq<'T>) : IConsumableSeq<'T> = + DelayedEnumerable (delayed, 1) :> _ + + module internal GroupBy = + let inline private impl (comparer:IEqualityComparer<'SafeKey>) (keyf:'T->'SafeKey) (getKey:'SafeKey->'Key) (source:IConsumableSeq<'T>) = + source.Consume (fun _ -> + { new SeqConsumerWithPostProcessing<'T,IConsumableSeq<'Key*IConsumableSeq<'T>>,_>(Unchecked.defaultof<_>,Dictionary comparer) with + override this.ProcessNext v = + let safeKey = keyf v + match this.State.TryGetValue safeKey with + | false, _ -> + let prev = ResizeArray () + this.State.[safeKey] <- prev + prev.Add v + | true, prev -> prev.Add v + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = + let maxWastage = 4 + for value in this.State.Values do + if value.Capacity - value.Count > maxWastage then value.TrimExcess () + + this.Result <- + this.State + |> ofSeq + |> map (fun kv -> getKey kv.Key, ofResizeArrayUnchecked kv.Value) + + override this.OnDispose () = () } :> _ ) + + let inline byVal (projection:'T->'Key) (source:IConsumableSeq<'T>) = + delay (fun () -> impl HashIdentity.Structural<'Key> projection id source) + + let inline byRef (projection:'T->'Key) (source:IConsumableSeq<'T>) = + delay (fun () -> impl (valueComparer<'Key> ()) (projection >> Value) (fun v -> v._1) source) + + [] + let inline internal groupByVal<'T,'Key when 'Key : equality and 'Key : struct> (projection:'T->'Key) (source:IConsumableSeq<'T>) = + GroupBy.byVal projection source + + [] + let inline internal groupByRef<'T,'Key when 'Key : equality and 'Key : not struct> (projection:'T->'Key) (source:IConsumableSeq<'T>) = + GroupBy.byRef projection source + + module CountBy = + let inline private impl (comparer:IEqualityComparer<'SafeKey>) (keyf:'T->'SafeKey) (getKey:'SafeKey->'Key) (source:IConsumableSeq<'T>) = + source.Consume (fun _ -> + { new SeqConsumerWithPostProcessing<'T,IConsumableSeq<'Key*int>,_>(Unchecked.defaultof<_>,Dictionary comparer) with + override this.ProcessNext v = + let safeKey = keyf v + this.State.[safeKey] <- + match this.State.TryGetValue safeKey with + | true, prev -> prev + 1 + | false, _ -> 1 + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = + this.Result <- + this.State + |> ofSeq + |> map (fun group -> getKey group.Key, group.Value) + + override this.OnDispose () = () } :> _ ) + + let inline byVal (projection:'T->'Key) (source:IConsumableSeq<'T>) = + delay (fun () -> impl HashIdentity.Structural<'Key> projection id source) + + let inline byRef (projection:'T->'Key) (source:IConsumableSeq<'T>) = + delay (fun () -> impl (valueComparer<'Key> ()) (projection >> Value) (fun v -> v._1) source) + + [] + let inline internal countByVal<'T,'Key when 'Key : equality and 'Key : struct> (projection:'T -> 'Key) (source:IConsumableSeq<'T>) = + CountBy.byVal projection source + + [] + let inline internal countByRef<'T,'Key when 'Key : equality and 'Key : not struct> (projection:'T -> 'Key) (source:IConsumableSeq<'T>) = + CountBy.byRef projection source + + [] + let internal length (source:IConsumableSeq<'T>) = + match source with + | :? EnumerableBase<'T> as s -> s.Length () + | :? list<'T> as l -> l.Length + | _ -> Basics.IConsumableSeq.length source + + [] + let internal toResizeArray (source:IConsumableSeq<'T>) = + source.Consume (fun _ -> + { new SeqConsumer<'T,ResizeArray<'T>>(ResizeArray ()) with + override this.ProcessNext v = + this.Result.Add v + Unchecked.defaultof<_> (* return value unused in Fold context *) } :> _ ) + + [] + let internal toArray (source:IConsumableSeq<'T>) = + Basics.Array.ofConsumableSeq source + + [] + let internal sortBy projection source = + delay (fun () -> + let array = source |> toArray + Array.stableSortInPlaceBy projection array + ofArray array) + + [] + let internal sort source = + delay (fun () -> + let array = source |> toArray + Array.stableSortInPlace array + ofArray array) + + [] + let sortWith comparer source = + delay (fun () -> + let array = source |> toArray + Array.stableSortInPlaceWith comparer array + ofArray array) + + [] + let internal rev source = + delay (fun () -> + let array = source |> toResizeArray + array.Reverse () + ofResizeArrayUnchecked array) + + [] + let internal permute indexMap (source:IConsumableSeq<_>) = + delay (fun () -> + source + |> toArray + |> Array.permute indexMap + |> ofArray) + + [] + let internal scanBack<'T,'State> folder (source:IConsumableSeq<'T>) (state:'State) : IConsumableSeq<'State> = + delay (fun () -> + let array = source |> toArray + Array.scanSubRight folder array 0 (array.Length - 1) state + |> ofArray) + + let inline internal foldArraySubRight f (arr:ResizeArray<'T>) start fin acc = + let mutable state = acc + for i = fin downto start do + state <- f arr.[i] state + state + + [] + let inline internal foldBack<'T,'State> folder (source: IConsumableSeq<'T>) (state:'State) = + let arr = toResizeArray source + let len = arr.Count + foldArraySubRight folder arr 0 (len - 1) state + + [] + let internal zip source1 source2 = + map2 (fun x y -> x,y) source1 source2 + + [] + let inline internal foldBack2<'T1,'T2,'State> folder (source1:IConsumableSeq<'T1>) (source2:IConsumableSeq<'T2>) (state:'State) = + let zipped = zip source1 source2 + foldBack ((<||) folder) zipped state + + [] + let inline internal reduceBack reduction (source:IConsumableSeq<'T>) = + let arr = toResizeArray source + match arr.Count with + | 0 -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + | len -> foldArraySubRight reduction arr 0 (len - 2) arr.[len - 1] + + [] + type internal CachedSeq<'T>(source:IConsumableSeq<'T>) = + let sync = obj () + + // Wrap a seq to ensure that it is enumerated just once and only as far as is necessary. + // + // This code is required to be thread safe. + // The necessary calls should be called at most once (include .MoveNext() = false). + // The enumerator should be disposed (and dropped) when no longer required. + //------ + // The state is (prefix,enumerator) with invariants: + // * the prefix followed by elts from the enumerator are the initial sequence. + // * the prefix contains only as many elements as the longest enumeration so far. + + let prefix = ResizeArray () + + let mutable started = false + let mutable enumeratorR = None : option> + + // function should only be called from within the lock + let oneStepTo i = + // If possible, step the enumeration to prefix length i (at most one step). + // Be speculative, since this could have already happened via another thread. + if not (i < prefix.Count) then // is a step still required? + // If not yet started, start it (create enumerator). + if not started then + started <- true + enumeratorR <- Some (source.GetEnumerator()) + + match enumeratorR with + | Some enumerator when enumerator.MoveNext() -> + prefix.Add enumerator.Current + | Some enumerator -> + enumerator.Dispose () // Move failed, dispose enumerator, + enumeratorR <- None // drop it and record finished. + | _ -> () + + let unfolding i = + // i being the next position to be returned + // A lock is needed over the reads to prefix.Count since the list may be being resized + // NOTE: we could change to a reader/writer lock here + lock sync (fun () -> + if i < prefix.Count then + Some (prefix.[i], i+1) + else + oneStepTo i + if i < prefix.Count then + Some (prefix.[i], i+1) + else + None) + + let cached : IConsumableSeq<'T> = new UnfoldEnumerable<'T,'T,int>(unfolding, 0, IdentityTransform.Instance, 1) :> _ + + interface System.IDisposable with + member __.Dispose() = + lock sync (fun () -> + prefix.Clear() + + enumeratorR + |> Option.iter IEnumerator.dispose + + started <- false + enumeratorR <- None) + + interface System.Collections.Generic.IEnumerable<'T> with + member __.GetEnumerator() = cached.GetEnumerator() + + interface System.Collections.IEnumerable with + member __.GetEnumerator() = (cached:>IEnumerable).GetEnumerator() + + interface IConsumableSeq<'T> with + member __.Transform next = cached.Transform next + member __.Consume f = cached.Consume f + + member this.Clear() = (this :> IDisposable).Dispose () + + [] + let internal cache (source:IConsumableSeq<'T>) : IConsumableSeq<'T> = + new CachedSeq<_> (source) :> _ + + [] + let internal collect mapping source = map mapping source |> concat + + [] + let internal allPairs (source1:IConsumableSeq<'T1>) (source2:IConsumableSeq<'T2>) : IConsumableSeq<'T1 * 'T2> = + checkNonNull "source1" source1 + checkNonNull "source2" source2 + let cached = cache source2 + source1 |> collect (fun x -> cached |> map (fun y -> x,y)) + + [] + let internal toList (source : IConsumableSeq<'T>) = + match source with + | :? list<'T> as lst -> lst + | _ -> Basics.List.ofConsumableSeq source + + [] + let replicate<'T> count (initial:'T) : IConsumableSeq<'T> = + if count < 0 then raise (ArgumentOutOfRangeException "count") + new InitEnumerable<'T,'T>(Nullable count, (fun _ -> initial), IdentityTransform.Instance, 1) :> _ + + [] + let internal isEmpty (source : IConsumableSeq<'T>) = + match source with + | :? list<'T> as lst -> lst.IsEmpty + | _ -> + use ie = source.GetEnumerator() + not (ie.MoveNext()) + + [] + let internal cast (source: IEnumerable) : IConsumableSeq<'T> = + match source with + | :? IConsumableSeq<'T> as s -> s + | :? IConsumableSeq as s -> s |> map unbox // covariant on ref types + | _ -> + mkSeq (fun () -> IEnumerator.cast (source.GetEnumerator())) |> ofSeq + + [] + let internal chunkBySize chunkSize (source : IConsumableSeq<'T>) : IConsumableSeq<'T[]> = + if chunkSize <= 0 then invalidArgFmt "chunkSize" "{0}\nchunkSize = {1}" + [|SR.GetString SR.inputMustBePositive; chunkSize|] + + source.Transform + { new ISeqTransform<'T,'T[]> with + member __.Compose outOfBand pipeIdx next = + { + new SeqTransformActivityWithPostProcessing<'T,'U,Values<'T[],int>>(next,Values<'T[],int>(Array.zeroCreateUnchecked chunkSize, 0)) with + override this.ProcessNext (input:'T) : bool = + this.State._1.[this.State._2] <- input + this.State._2 <- this.State._2 + 1 + if this.State._2 <> chunkSize then false + else + this.State._2 <- 0 + let tmp = this.State._1 + this.State._1 <- Array.zeroCreateUnchecked chunkSize + TailCall.avoid (next.ProcessNext tmp) + + override this.OnComplete _ = + if this.State._2 > 0 then + System.Array.Resize (&this.State._1, this.State._2) + next.ProcessNext this.State._1 |> ignore + + override this.OnDispose () = () } :> _ } + + let internal mkDelayedSeq (f: unit -> IEnumerable<'T>) = mkSeq (fun () -> f().GetEnumerator()) |> ofSeq + + [] + let internal splitInto count (source:IConsumableSeq<'T>) : IConsumableSeq<'T[]> = + if count <= 0 then invalidArgFmt "count" "{0}\ncount = {1}" + [|SR.GetString SR.inputMustBePositive; count|] + mkDelayedSeq (fun () -> + source |> toArray |> Array.splitInto count :> seq<_>) + + let inline internal indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) + + [] + let internal find predicate source = + match tryFind predicate source with + | None -> indexNotFound() + | Some x -> x + + [] + let internal findIndex predicate (source:IConsumableSeq<_>) = + use ie = source.GetEnumerator() + let rec loop i = + if ie.MoveNext() then + if predicate ie.Current then + i + else loop (i+1) + else + indexNotFound() + loop 0 + + [] + let internal findBack predicate source = + source |> toArray |> Array.findBack predicate + + [] + let internal findIndexBack predicate source = + source |> toArray |> Array.findIndexBack predicate + + [] + let internal pick chooser source = + match tryPick chooser source with + | None -> indexNotFound() + | Some x -> x + + [] + let internal mapFold<'T,'State,'Result> (mapping:'State->'T->'Result*'State) state source = + let arr,state = source |> toArray |> Array.mapFold mapping state + ofArray arr, state + + [] + let internal mapFoldBack<'T,'State,'Result> (mapping:'T->'State->'Result*'State) source state = + let array = source |> toArray + let arr,state = Array.mapFoldBack mapping array state + ofArray arr, state + + let rec internal nth index (e : IEnumerator<'T>) = + if not (e.MoveNext()) then + let shortBy = index + 1 + invalidArgFmt "index" + "{0}\nseq was short by {1} {2}" + [|SR.GetString SR.notEnoughElements; shortBy; (if shortBy = 1 then "element" else "elements")|] + if index = 0 then e.Current + else nth (index-1) e + + [] + let internal item index (source : IConsumableSeq<'T>) = + if index < 0 then invalidArgInputMustBeNonNegative "index" index + use e = source.GetEnumerator() + nth index e + + [] + let inline sortDescending source = + let inline compareDescending a b = compare b a + sortWith compareDescending source + + [] + let inline sortByDescending projection source = + let inline compareDescending a b = compare (projection b) (projection a) + sortWith compareDescending source + + [] + let internal tryFindBack predicate (source : IConsumableSeq<'T>) = + source |> toArray |> Array.tryFindBack predicate + + [] + let internal tryFindIndexBack predicate (source : IConsumableSeq<'T>) = + source |> toArray |> Array.tryFindIndexBack predicate + + [] + let internal zip3 source1 source2 source3 = + map2 (fun x (y,z) -> x,y,z) source1 (zip source2 source3) \ No newline at end of file diff --git a/src/fsharp/FSharp.Core/iseq.fsi b/src/fsharp/FSharp.Core/iseq.fsi new file mode 100644 index 00000000000..774a27b81d7 --- /dev/null +++ b/src/fsharp/FSharp.Core/iseq.fsi @@ -0,0 +1,417 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.FSharp.Collections + + open System + open System.Collections + open System.Collections.Generic + open Microsoft.FSharp.Core + open Microsoft.FSharp.Collections + open Microsoft.FSharp.Collections.SeqComposition + + [] + module IConsumableSeq = + module Core = + /// Values is a mutable struct. It can be embedded within the folder type + /// if two values are required for the calculation. + [] + type internal Value<'a> = + new : a:'a -> Value<'a> + val mutable _1: 'a + + /// Values is a mutable struct. It can be embedded within the folder type + /// if two values are required for the calculation. + [] + type Values<'a,'b> = + new : a:'a * b:'b -> Values<'a,'b> + val mutable _1: 'a + val mutable _2: 'b + + /// Values is a mutable struct. It can be embedded within the folder type + /// if three values are required for the calculation. + [] + type internal Values<'a,'b,'c> = + new : a:'a * b:'b * c:'c -> Values<'a,'b,'c> + val mutable _1: 'a + val mutable _2: 'b + val mutable _3: 'c + + + /// An activity that transforms the input from 'T to 'U, using 'State. It's intended usage + /// is as a base class for an object expression that will be created + /// in the ISeqTransform's Compose function. + [] + type internal SeqTransformActivity<'T,'U,'State> = + inherit SeqConsumerActivity<'T,'U> + new : next:SeqConsumerActivity * 'State -> SeqTransformActivity<'T,'U,'State> + val mutable State : 'State + val private Next : SeqConsumerActivity + + /// An activity that transforms the input from 'T to 'U, using 'State + /// and performs some post processing on the pipeline, either in the case of the stream + /// ending sucessfully or when disposed. It's intended usage + /// is as a base class for an object expression that will be created + /// in the ISeqTransform's Compose function. + [] + type internal SeqTransformActivityWithPostProcessing<'T,'U,'State> = + inherit SeqTransformActivity<'T,'U,'State> + new : next:SeqConsumerActivity * 'State -> SeqTransformActivityWithPostProcessing<'T,'U,'State> + + /// OnComplete is used to determine if the object has been processed correctly, + /// and possibly throw exceptions to denote incorrect application (i.e. such as a Take + /// operation which didn't have a source at least as large as was required). It is + /// not called in the case of an exception being thrown whilst the stream is still + /// being processed. + abstract OnComplete : PipeIdx -> unit + + /// OnDispose is used to cleanup the stream. It is always called at the last operation + /// after the enumeration has completed. + abstract OnDispose : unit -> unit + + /// SeqConsumer is a base class to assist with fold-like operations. It's intended usage + /// is as a base class for an object expression that will be used from within + /// the Fold function. + [] + type SeqConsumerWithState<'T,'Result,'State> = + inherit SeqConsumer<'T,'Result> + new : 'Result*'State -> SeqConsumerWithState<'T,'Result,'State> + val mutable State : 'State + + /// SeqConsumer is a base class to assist with fold-like operations + /// and performs some post processing on the pipeline, either in the case of the stream + /// ending sucessfully or when disposed. It's intended usage + /// is as a base class for an object expression that will be used from within + /// the Fold function. + [] + type SeqConsumerWithPostProcessing<'T,'Result,'State> = + inherit SeqConsumerWithState<'T,'Result,'State> + new : 'Result*'State -> SeqConsumerWithPostProcessing<'T,'Result,'State> + abstract OnDispose : unit -> unit + abstract OnComplete : PipeIdx -> unit + + open Core + + /// ofResizeArrayUnchecked creates an IConsumableSeq over a ResizeArray that accesses the underlying + /// structure via Index rather than via the GetEnumerator function. This provides faster access + /// but doesn't check the version of the underlying object which means care has to be taken + /// to ensure that it is not modified which the result IConsumableSeq exists. + [] + val internal ofResizeArrayUnchecked : ResizeArray<'T> -> IConsumableSeq<'T> + + [] + val internal ofList : list<'T> -> IConsumableSeq<'T> + + [] + val internal ofArray : array<'T> -> IConsumableSeq<'T> + + [] + val ofSeq : seq<'T> -> IConsumableSeq<'T> + + [] + val inline average : source: IConsumableSeq< ^T> -> ^T + when 'T:(static member Zero : ^T) + and 'T:(static member (+) : ^T * ^T -> ^T) + and ^T:(static member DivideByInt : ^T * int -> ^T) + + [] + val inline averageBy : f:('T -> ^U) -> source:IConsumableSeq< 'T > -> ^U + when ^U:(static member Zero : ^U) + and ^U:(static member (+) : ^U * ^U -> ^U) + and ^U:(static member DivideByInt : ^U * int -> ^U) + + [] + val internal empty<'T> : IConsumableSeq<'T> + + [] + val internal exactlyOne : IConsumableSeq<'T> -> 'T + + [] + val inline internal fold<'T,'State> : f:('State->'T->'State) -> seed:'State -> source:IConsumableSeq<'T> -> 'State + + [] + val inline internal fold2<'T1,'T2,'State> : folder:('State->'T1->'T2->'State) -> state:'State -> source1: IConsumableSeq<'T1> -> source2: IConsumableSeq<'T2> -> 'State + + [] + val internal unfold : generator:('State -> option<'T*'State>) -> state:'State -> IConsumableSeq<'T> + + [] + val internal initInfinite : f:(int -> 'T) -> IConsumableSeq<'T> + + [] + val internal init : count:int -> f:(int -> 'T) -> IConsumableSeq<'T> + + [] + val inline internal iter : action:('T -> unit) -> source:IConsumableSeq<'T> -> unit + + [] + val inline internal iter2 : action:('T->'U->unit) -> source1 : IConsumableSeq<'T> -> source2 : IConsumableSeq<'U> -> unit + + [] + val inline internal iteri2 : action:(int->'T->'U->unit) -> source1:IConsumableSeq<'T> -> source2:IConsumableSeq<'U> -> unit + + [] + val internal tryHead : IConsumableSeq<'T> -> option<'T> + + [] + val internal head: source:IConsumableSeq<'T> -> 'T + + [] + val inline internal iteri : action:(int -> 'T -> unit) -> source:IConsumableSeq<'T> -> unit + + [] + val inline internal except : itemsToExclude:seq<'T> -> source:IConsumableSeq<'T> -> IConsumableSeq<'T> when 'T:equality + + [] + val inline internal exists : predicate:('T -> bool) -> source:IConsumableSeq<'T> -> bool + + [] + val inline internal exists2 : predicate:('T->'U->bool) -> source1:IConsumableSeq<'T> -> source2:IConsumableSeq<'U> -> bool + + [] + val inline contains : element:'T -> source:IConsumableSeq<'T> -> bool when 'T : equality + + [] + val inline internal forall : predicate:('T -> bool) -> source:IConsumableSeq<'T> -> bool + + [] + val inline internal forall2 : predicate:('T->'U->bool) -> source1:IConsumableSeq<'T> -> source2:IConsumableSeq<'U> -> bool + + [] + val inline internal filter : predicate:('T -> bool) -> source:IConsumableSeq<'T> -> IConsumableSeq<'T> + + [] + val inline internal map : mapping:('T -> 'U) -> source:IConsumableSeq<'T> -> IConsumableSeq<'U> + + [] + val inline internal mapi : mapping:(int->'a->'b) -> source: IConsumableSeq<'a> -> IConsumableSeq<'b> + + [] + val inline internal map2<'T,'U,'V> : mapping:('T->'U->'V) -> source1:IConsumableSeq<'T> -> source2:IConsumableSeq<'U> -> IConsumableSeq<'V> + + [] + val inline internal mapi2<'T,'U,'V> : mapping:(int -> 'T->'U->'V) -> source1:IConsumableSeq<'T> -> source2:IConsumableSeq<'U> -> IConsumableSeq<'V> + + [] + val inline internal map3<'T,'U,'V,'W> : mapping:('T->'U->'V->'W) -> source1:IConsumableSeq<'T> -> source2:IConsumableSeq<'U> -> source3:IConsumableSeq<'V> -> IConsumableSeq<'W> + + [] + val inline internal compareWith : comparer:('T->'T->int) -> source1 :IConsumableSeq<'T> -> source2:IConsumableSeq<'T> -> int + + [] + val inline internal choose : f:('a->option<'b>) -> source: IConsumableSeq<'a> -> IConsumableSeq<'b> + + [] + val inline internal distinct : source:IConsumableSeq<'T> -> IConsumableSeq<'T> when 'T:equality + + [] + val inline internal distinctBy : keyf:('T->'Key) -> source:IConsumableSeq<'T> -> IConsumableSeq<'T> when 'Key:equality + + [] + val inline max : source:IConsumableSeq<'T> -> 'T when 'T:comparison + + [] + val inline maxBy : f:('T->'U) -> source:IConsumableSeq<'T> -> 'T when 'U:comparison + + [] + val inline min : source:IConsumableSeq<'T> -> 'T when 'T:comparison + + [] + val inline minBy : f:('T->'U) -> source:IConsumableSeq<'T> -> 'T when 'U:comparison + + [] + val internal pairwise : source:IConsumableSeq<'T> -> IConsumableSeq<'T * 'T> + + [] + val inline internal reduce : f:('T->'T->'T) -> source:IConsumableSeq<'T> -> 'T + + [] + val internal scan : folder:('State->'T->'State) -> initialState:'State -> source:IConsumableSeq<'T> -> IConsumableSeq<'State> + + [] + val internal skip : skipCount:int -> source:IConsumableSeq<'T> -> IConsumableSeq<'T> + + [] + val inline internal skipWhile : predicate:('T->bool) -> source:IConsumableSeq<'T> -> IConsumableSeq<'T> + + [] + val inline sum : source:IConsumableSeq<'T> -> 'T + when 'T:(static member Zero : ^T) + and 'T:(static member (+) : ^T * ^T -> ^T) + + [] + val inline sumBy : f :('T -> ^U) -> source:IConsumableSeq<'T> -> ^U + when ^U:(static member Zero : ^U) + and ^U:(static member (+) : ^U * ^U -> ^U) + + [] + val internal take : takeCount:int -> source:IConsumableSeq<'T> -> IConsumableSeq<'T> + + [] + val inline internal takeWhile : predicate:('T->bool) -> source:IConsumableSeq<'T> -> IConsumableSeq<'T> + + [] + val internal tail : source:IConsumableSeq<'T> -> IConsumableSeq<'T> + + [] + val internal truncate : truncateCount:int -> source:IConsumableSeq<'T> -> IConsumableSeq<'T> + + [] + val internal indexed : source: IConsumableSeq<'a> -> IConsumableSeq + + [] + val internal tryItem : index:int -> source:IConsumableSeq<'T> -> option<'T> + + [] + val inline internal tryPick : f:('T -> option<'U>) -> source:IConsumableSeq<'T> -> option<'U> + + [] + val inline internal tryFind : f:('T -> bool) -> source:IConsumableSeq<'T> -> option<'T> + + [] + val inline internal tryFindIndex: predicate:('T->bool) -> source:IConsumableSeq<'T> -> option + + [] + val internal last: source:IConsumableSeq<'T> -> 'T + + [] + val internal tryLast : source:IConsumableSeq<'T> -> option<'T> + + [] + val internal windowed : windowSize:int -> source:IConsumableSeq<'T> -> IConsumableSeq> + + [] + val internal concat : sources:IConsumableSeq<'Collection> -> IConsumableSeq<'T> when 'Collection :> IConsumableSeq<'T> + + [] + val internal append: source1:IConsumableSeq<'T> -> source2:IConsumableSeq<'T> -> IConsumableSeq<'T> + + [] + val internal delay : (unit -> IConsumableSeq<'T>) -> IConsumableSeq<'T> + + [] + val inline internal groupByVal : projection:('T -> 'Key) -> source:IConsumableSeq<'T> -> IConsumableSeq<'Key * IConsumableSeq<'T>> when 'Key : equality and 'Key : struct + + [] + val inline internal groupByRef : projection:('T -> 'Key) -> source:IConsumableSeq<'T> -> IConsumableSeq<'Key * IConsumableSeq<'T>> when 'Key : equality and 'Key : not struct + + [] + val inline internal countByVal : projection:('T -> 'Key) -> source:IConsumableSeq<'T> -> IConsumableSeq<'Key * int> when 'Key : equality and 'Key : struct + + [] + val inline internal countByRef : projection:('T -> 'Key) -> source:IConsumableSeq<'T> -> IConsumableSeq<'Key * int> when 'Key : equality and 'Key : not struct + + [] + val internal length: source:IConsumableSeq<'T> -> int + + [] + val internal toArray: source:IConsumableSeq<'T> -> array<'T> + + [] + val internal toResizeArray: source:IConsumableSeq<'T> -> ResizeArray<'T> + + [] + val internal sortBy : projection:('T->'Key) -> source:IConsumableSeq<'T> -> IConsumableSeq<'T> when 'Key : comparison + + [] + val internal sort : source:IConsumableSeq<'T> -> IConsumableSeq<'T> when 'T : comparison + + [] + val sortWith : comparer:('T->'T->int) -> source:IConsumableSeq<'T> -> IConsumableSeq<'T> + + [] + val internal rev: source:IConsumableSeq<'T> -> IConsumableSeq<'T> + + [] + val internal permute: indexMap:(int->int) -> source:IConsumableSeq<'T> -> IConsumableSeq<'T> + + [] + val internal scanBack<'T,'State> : folder:('T->'State->'State) -> source:IConsumableSeq<'T> -> state:'State -> IConsumableSeq<'State> + + [] + val internal zip: source1:IConsumableSeq<'T1> -> source2:IConsumableSeq<'T2> -> IConsumableSeq<'T1 * 'T2> + + [] + val inline internal reduceBack: reduction:('T->'T->'T) -> source:IConsumableSeq<'T> -> 'T + + [] + val inline internal foldBack<'T,'State> : folder:('T->'State->'State) -> source:IConsumableSeq<'T> -> state:'State -> 'State + + [] + val inline internal foldBack2<'T1,'T2,'State> : folder:('T1->'T2->'State->'State) -> source1:IConsumableSeq<'T1> -> source2:IConsumableSeq<'T2> -> state:'State -> 'State + + module internal GroupBy = + val inline byVal : projection:('T -> 'Key) -> source:IConsumableSeq<'T> -> IConsumableSeq<'Key * IConsumableSeq<'T>> when 'Key : equality + val inline byRef : projection:('T -> 'Key) -> source:IConsumableSeq<'T> -> IConsumableSeq<'Key * IConsumableSeq<'T>> when 'Key : equality + + module internal CountBy = + val inline byVal : projection:('T -> 'Key) -> source:IConsumableSeq<'T> -> IConsumableSeq<'Key * int> when 'Key : equality + val inline byRef : projection:('T -> 'Key) -> source:IConsumableSeq<'T> -> IConsumableSeq<'Key * int> when 'Key : equality + + [] + val internal cache: source:IConsumableSeq<'T> -> IConsumableSeq<'T> + + [] + val internal collect: mapping:('T -> 'Collection) -> source:IConsumableSeq<'T> -> IConsumableSeq<'U> when 'Collection :> IConsumableSeq<'U> + + [] + val internal allPairs: source1:IConsumableSeq<'T1> -> source2:IConsumableSeq<'T2> -> IConsumableSeq<'T1 * 'T2> + + [] + val internal toList: source:IConsumableSeq<'T> -> 'T list + + [] + val internal replicate: count:int -> initial:'T -> IConsumableSeq<'T> + + [] + val internal isEmpty: source:IConsumableSeq<'T> -> bool + + [] + val internal cast: source:IEnumerable -> IConsumableSeq<'T> + + [] + val internal chunkBySize: chunkSize:int -> source:IConsumableSeq<'T> -> IConsumableSeq<'T[]> + + [] + val internal splitInto: count:int -> source:IConsumableSeq<'T> -> IConsumableSeq<'T[]> + + [] + val internal find: predicate:('T -> bool) -> source:IConsumableSeq<'T> -> 'T + + [] + val internal findBack: predicate:('T -> bool) -> source:IConsumableSeq<'T> -> 'T + + [] + val internal findIndex: predicate:('T -> bool) -> source:IConsumableSeq<'T> -> int + + [] + val internal findIndexBack: predicate:('T -> bool) -> source:IConsumableSeq<'T> -> int + + [] + val internal pick: chooser:('T -> 'U option) -> source:IConsumableSeq<'T> -> 'U + + [] + val internal mapFold<'T,'State,'Result> : mapping:('State -> 'T -> 'Result * 'State) -> state:'State -> source:IConsumableSeq<'T> -> IConsumableSeq<'Result> * 'State + + [] + val internal mapFoldBack<'T,'State,'Result> : mapping:('T -> 'State -> 'Result * 'State) -> source:IConsumableSeq<'T> -> state:'State -> IConsumableSeq<'Result> * 'State + + [] + val internal item: index:int -> source:IConsumableSeq<'T> -> 'T + + [] + val internal singleton: value:'T -> IConsumableSeq<'T> + + [] + val inline sortDescending : source:IConsumableSeq<'T> -> IConsumableSeq<'T> when 'T : comparison + + [] + val inline sortByDescending : projection:('T -> 'Key) -> source:IConsumableSeq<'T> -> IConsumableSeq<'T> when 'Key : comparison + + [] + val internal tryFindBack: predicate:('T -> bool) -> source:IConsumableSeq<'T> -> 'T option + + [] + val internal tryFindIndexBack : predicate:('T -> bool) -> source:IConsumableSeq<'T> -> int option + + [] + val internal zip3: source1:IConsumableSeq<'T1> -> source2:IConsumableSeq<'T2> -> source3:IConsumableSeq<'T3> -> IConsumableSeq<'T1 * 'T2 * 'T3> diff --git a/src/fsharp/FSharp.Core/list.fs b/src/fsharp/FSharp.Core/list.fs index aea7ef55ea9..ddf75869e53 100644 --- a/src/fsharp/FSharp.Core/list.fs +++ b/src/fsharp/FSharp.Core/list.fs @@ -7,7 +7,6 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Core.LanguagePrimitives open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators open Microsoft.FSharp.Collections - open Microsoft.FSharp.Core.CompilerServices open System.Collections.Generic #if FX_RESHAPED_REFLECTION open System.Reflection @@ -64,7 +63,7 @@ namespace Microsoft.FSharp.Collections let countByValueType (projection:'T->'Key) (list:'T list) = countByImpl HashIdentity.Structural<'Key> projection id list // Wrap a StructBox around all keys in case the key type is itself a type using null as a representation - let countByRefType (projection:'T->'Key) (list:'T list) = countByImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun t -> RuntimeHelpers.StructBox (projection t)) (fun sb -> sb.Value) list + let countByRefType (projection:'T->'Key) (list:'T list) = countByImpl StructBox<'Key>.Comparer (fun t -> StructBox (projection t)) (fun sb -> sb.Value) list [] let countBy (projection:'T->'Key) (list:'T list) = @@ -433,7 +432,7 @@ namespace Microsoft.FSharp.Collections let groupByValueType (keyf:'T->'Key) (list:'T list) = groupByImpl HashIdentity.Structural<'Key> keyf id list // Wrap a StructBox around all keys in case the key type is itself a type using null as a representation - let groupByRefType (keyf:'T->'Key) (list:'T list) = groupByImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun t -> RuntimeHelpers.StructBox (keyf t)) (fun sb -> sb.Value) list + let groupByRefType (keyf:'T->'Key) (list:'T list) = groupByImpl StructBox<'Key>.Comparer (fun t -> StructBox (keyf t)) (fun sb -> sb.Value) list [] let groupBy (projection:'T->'Key) (list:'T list) = @@ -523,10 +522,10 @@ namespace Microsoft.FSharp.Collections sortWith compareDescending list [] - let ofSeq source = Seq.toList source + let ofSeq<'T> (source:seq<'T>) : list<'T> = Microsoft.FSharp.Primitives.Basics.List.ofSeq source [] - let toSeq list = Seq.ofList list + let toSeq<'T> (list:list<'T>) : seq<'T> = (list :> seq<'T>) [] let findIndex predicate list = diff --git a/src/fsharp/FSharp.Core/local.fs b/src/fsharp/FSharp.Core/local.fs index f89ae5b3c07..c0d7c26c17c 100644 --- a/src/fsharp/FSharp.Core/local.fs +++ b/src/fsharp/FSharp.Core/local.fs @@ -82,6 +82,7 @@ open System.Collections.Generic module internal List = + open Microsoft.FSharp.Collections.SeqComposition let arrayZeroCreate (n:int) = (# "newarr !0" type ('T) n : 'T array #) @@ -540,10 +541,36 @@ module internal List = res <- arr.[i] :: res res + /// A consumer that collects elements as a list + type ConsumeToList<'T> () = + inherit SeqConsumer<'T, list<'T>>([]) + + let mutable first = true + let mutable cons = Unchecked.defaultof<_> + + override this.ProcessNext input = + if first then + first <- false + this.Result <- freshConsNoTail input + cons <- this.Result + else + let cons2 = freshConsNoTail input + setFreshConsTail cons cons2 + cons <- cons2 + true (* result unused in fold *) + + override this.ChainComplete _ = + if not first then + setFreshConsTail cons [] + + let ofConsumableSeq (s : IConsumableSeq<'T>) = + s.Consume (fun _ -> upcast ConsumeToList()) + let inline ofSeq (e : IEnumerable<'T>) = match e with | :? list<'T> as l -> l | :? ('T[]) as arr -> ofArray arr + | :? IConsumableSeq<'T> as s -> ofConsumableSeq s | _ -> use ie = e.GetEnumerator() if not (ie.MoveNext()) then [] @@ -984,6 +1011,8 @@ module internal List = module internal Array = open System + open System.Collections.Generic + open Microsoft.FSharp.Collections.SeqComposition let inline fastComparerForArraySort<'t when 't : comparison> () = LanguagePrimitives.FastGenericComparerCanBeNull<'t> @@ -1077,7 +1106,7 @@ module internal Array = res.[i - start] <- state res - let unstableSortInPlaceBy (projection: 'T -> 'U) (array : array<'T>) = + let unstableSortInPlaceBy (projection: 'T -> 'U) (array : 'T[]) = let len = array.Length if len < 2 then () else @@ -1086,19 +1115,19 @@ module internal Array = keys.[i] <- projection array.[i] Array.Sort<_,_>(keys, array, fastComparerForArraySort()) - let unstableSortInPlace (array : array<'T>) = + let unstableSortInPlace (array : 'T[]) = let len = array.Length if len < 2 then () else Array.Sort<_>(array, fastComparerForArraySort()) - let stableSortWithKeysAndComparer (cFast:IComparer<'Key>) (c:IComparer<'Key>) (array:array<'T>) (keys:array<'Key>) = + let stableSortWithKeysAndComparer (cFast:IComparer<'Key>) (c:IComparer<'Key>) (array:'T[]) (keys:array<'Key>) = // 'places' is an array or integers storing the permutation performed by the sort let places = zeroCreateUnchecked array.Length for i = 0 to array.Length - 1 do places.[i] <- i System.Array.Sort<_,_>(keys, places, cFast) // 'array2' is a copy of the original values - let array2 = (array.Clone() :?> array<'T>) + let array2 = (array.Clone() :?> 'T[]) // Walk through any chunks where the keys are equal let mutable i = 0 @@ -1117,12 +1146,12 @@ module internal Array = Array.Sort<_,_>(places, array, i, j-i, intCompare) i <- j - let stableSortWithKeys (array:array<'T>) (keys:array<'Key>) = + let stableSortWithKeys (array:'T[]) (keys:array<'Key>) = let cFast = fastComparerForArraySort() let c = LanguagePrimitives.FastGenericComparer<'Key> stableSortWithKeysAndComparer cFast c array keys - let stableSortInPlaceBy (projection: 'T -> 'U) (array : array<'T>) = + let stableSortInPlaceBy (projection: 'T -> 'U) (array : 'T[]) = let len = array.Length if len < 2 then () else @@ -1132,7 +1161,7 @@ module internal Array = keys.[i] <- projection array.[i] stableSortWithKeys array keys - let stableSortInPlace (array : array<'T>) = + let stableSortInPlace (array : 'T[]) = let len = array.Length if len < 2 then () else @@ -1144,13 +1173,13 @@ module internal Array = Array.Sort<_,_>(array, null) | _ -> // 'keys' is an array storing the projected keys - let keys = (array.Clone() :?> array<'T>) + let keys = (array.Clone() :?> 'T[]) stableSortWithKeys array keys - let stableSortInPlaceWith (comparer:'T -> 'T -> int) (array : array<'T>) = + let stableSortInPlaceWith (comparer:'T -> 'T -> int) (array : 'T[]) = let len = array.Length if len > 1 then - let keys = (array.Clone() :?> array<'T>) + let keys = (array.Clone() :?> 'T[]) let comparer = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(comparer) let c = { new IComparer<'T> with member __.Compare(x,y) = comparer.Invoke(x,y) } stableSortWithKeysAndComparer c c array keys @@ -1172,11 +1201,65 @@ module internal Array = let count = min count len let res = zeroCreateUnchecked count : 'T[][] let minChunkSize = len / count - let startIndex = ref 0 + let mutable startIndex = 0 for i = 0 to len % count - 1 do - res.[i] <- subUnchecked !startIndex (minChunkSize + 1) array - startIndex := !startIndex + minChunkSize + 1 + res.[i] <- subUnchecked startIndex (minChunkSize + 1) array + startIndex <- startIndex + minChunkSize + 1 for i = len % count to count - 1 do - res.[i] <- subUnchecked !startIndex minChunkSize array - startIndex := !startIndex + minChunkSize + res.[i] <- subUnchecked startIndex minChunkSize array + startIndex <- startIndex + minChunkSize res + + type ConsumeToArray<'T> () = + inherit SeqConsumer<'T, 'T[]>(Unchecked.defaultof<_>) + + let mutable tmp = ResizeArray () + + override this.ProcessNext input = + tmp.Add input + true (* result unused *) + + override this.ChainComplete _ = + this.Result <- tmp.ToArray () + + let ofConsumableSeq (s : IConsumableSeq<'T>) = + s.Consume (fun _ -> upcast ConsumeToArray()) + + let ofSeq (source : seq<'T>) = + match source with + | :? ('T[]) as res -> (res.Clone() :?> 'T[]) + | :? ('T list) as res -> List.toArray res + | :? ICollection<'T> as res -> + // Directly create an array and copy ourselves. + // This avoids an extra copy if using ResizeArray in fallback below. + let arr = zeroCreateUnchecked res.Count + res.CopyTo(arr, 0) + arr + | :? IConsumableSeq<'T> as s -> ofConsumableSeq s + | :? IReadOnlyCollection<'T> as col -> + let res = zeroCreateUnchecked col.Count : 'T[] + let mutable idx = 0 + for x in source do + res.[idx] <- x + idx <- idx + 1 + res + | _ -> + let res = ResizeArray source + res.ToArray() + + let toSeq (source : 'T[]) : seq<'T> = + { new IEnumerable<'T> with + member this.GetEnumerator(): Collections.IEnumerator = + (source:>System.Collections.IEnumerable).GetEnumerator () + member this.GetEnumerator(): IEnumerator<'T> = + (source:>IEnumerable<'T>).GetEnumerator () } + +module internal IConsumableSeq = + open Microsoft.FSharp.Collections.SeqComposition + + let length (source:IConsumableSeq<_>) = + source.Consume (fun _ -> + { new SeqConsumer<'T,int>(0) with + override this.ProcessNext v = + this.Result <- this.Result + 1 + Unchecked.defaultof<_> (* return value unused in Fold context *) }) diff --git a/src/fsharp/FSharp.Core/local.fsi b/src/fsharp/FSharp.Core/local.fsi index 3181dcbc6ec..08446419feb 100644 --- a/src/fsharp/FSharp.Core/local.fsi +++ b/src/fsharp/FSharp.Core/local.fsi @@ -22,6 +22,7 @@ namespace Microsoft.FSharp.Primitives.Basics open Microsoft.FSharp.Core open Microsoft.FSharp.Collections +open Microsoft.FSharp.Collections.SeqComposition module internal List = val allPairs : 'T1 list -> 'T2 list -> ('T1 * 'T2) list @@ -61,6 +62,7 @@ module internal List = val take : int -> 'T list -> 'T list val takeWhile : ('T -> bool) -> 'T list -> 'T list val toArray : 'T list -> 'T[] + val ofConsumableSeq : IConsumableSeq<'T> -> 'T List val inline ofSeq : seq<'T> -> 'T List val splitAt : int -> 'T list -> ('T list * 'T list) val transpose : 'T list list -> 'T list list @@ -69,35 +71,25 @@ module internal List = module internal Array = // The input parameter should be checked by callers if necessary val inline zeroCreateUnchecked : int -> 'T[] - val inline init : int -> (int -> 'T) -> 'T[] - val splitInto : int -> 'T[] -> 'T[][] - val findBack: predicate:('T -> bool) -> array:'T[] -> 'T - val tryFindBack: predicate:('T -> bool) -> array:'T[] -> 'T option - val findIndexBack: predicate:('T -> bool) -> array:'T[] -> int - val tryFindIndexBack: predicate:('T -> bool) -> array:'T[] -> int option - val mapFold : ('State -> 'T -> 'U * 'State) -> 'State -> 'T[] -> 'U[] * 'State - val mapFoldBack : ('T -> 'State -> 'U * 'State) -> 'T[] -> 'State -> 'U[] * 'State - val permute : indexMap:(int -> int) -> 'T[] -> 'T[] - val scanSubRight: f:('T -> 'State -> 'State) -> array:'T[] -> start:int -> fin:int -> initState:'State -> 'State[] - val inline subUnchecked : int -> int -> 'T[] -> 'T[] - val unstableSortInPlaceBy: projection:('T -> 'Key) -> array:'T[] -> unit when 'Key : comparison - val unstableSortInPlace: array:'T[] -> unit when 'T : comparison - val stableSortInPlaceBy: projection:('T -> 'Key) -> array:'T[] -> unit when 'Key : comparison - val stableSortInPlaceWith: comparer:('T -> 'T -> int) -> array:'T[] -> unit - val stableSortInPlace: array:'T[] -> unit when 'T : comparison + val ofSeq : seq<'T> -> 'T[] + val ofConsumableSeq : IConsumableSeq<'T> -> 'T[] + val toSeq : 'T[] -> seq<'T> + +module internal IConsumableSeq = + val length : IConsumableSeq<'T> -> int \ No newline at end of file diff --git a/src/fsharp/FSharp.Core/map.fs b/src/fsharp/FSharp.Core/map.fs index 97c747e4ae5..7b1051a4b64 100644 --- a/src/fsharp/FSharp.Core/map.fs +++ b/src/fsharp/FSharp.Core/map.fs @@ -332,12 +332,6 @@ namespace Microsoft.FSharp.Collections let toArray m = m |> toList |> Array.ofList let ofList comparer l = List.fold (fun acc (k,v) -> add comparer k v acc) empty l - let rec mkFromEnumerator comparer acc (e : IEnumerator<_>) = - if e.MoveNext() then - let (x,y) = e.Current - mkFromEnumerator comparer (add comparer x y acc) e - else acc - let ofArray comparer (arr : array<_>) = let mutable res = empty for (x,y) in arr do @@ -348,10 +342,7 @@ namespace Microsoft.FSharp.Collections match c with | :? array<'Key * 'T> as xs -> ofArray comparer xs | :? list<'Key * 'T> as xs -> ofList comparer xs - | _ -> - use ie = c.GetEnumerator() - mkFromEnumerator comparer empty ie - + | _ -> Seq.fold (fun acc (k,v) -> add comparer k v acc) empty c let copyToArray s (arr: _[]) i = let j = ref i diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 24195cbfbb0..922f5a57bba 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -2969,6 +2969,68 @@ namespace Microsoft.FSharp.Core | Error of ErrorValue:'TError +namespace Microsoft.FSharp.Collections.SeqComposition + open System + open System.Collections + open System.Collections.Generic + open Microsoft.FSharp.Core + open BasicInlinedOperations + open LanguagePrimitives.IntrinsicOperators + + type PipeIdx = int + + type ISeqConsumer = + abstract StopFurtherProcessing : PipeIdx -> unit + abstract ListenForStopFurtherProcessing : Action -> unit + + [] + type SeqConsumerActivity() = + abstract ChainComplete : PipeIdx -> unit + abstract ChainDispose : unit -> unit + + [] + type SeqConsumerActivity<'T> () = + inherit SeqConsumerActivity() + abstract ProcessNext : input:'T -> bool + + [] + type SeqConsumerActivity<'T,'U> () = + inherit SeqConsumerActivity<'T>() + + [] + type SeqConsumer<'T,'Result>(initalResult:'Result) = + inherit SeqConsumerActivity<'T,'T>() + + let mutable listeners = BasicInlinedOperations.unsafeDefault> + let mutable result = initalResult + let mutable haltedIdx = 0 + + member __.Result with get() = result and set value = result <- value + member __.HaltedIdx = haltedIdx + + interface ISeqConsumer with + member this.StopFurtherProcessing pipeIdx = + let currentIdx = haltedIdx + haltedIdx <- pipeIdx + if currentIdx = 0 && haltedIdx <> 0 then + match listeners with + | null -> () + | a -> a.Invoke pipeIdx + + member this.ListenForStopFurtherProcessing action = + listeners <- Delegate.Combine (listeners, action) :?> Action + + override this.ChainComplete _ = () + override this.ChainDispose () = () + + type ISeqTransform<'T,'U> = + abstract Compose<'V> : ISeqConsumer -> PipeIdx -> SeqConsumerActivity<'U,'V> -> SeqConsumerActivity<'T,'V> + + type IConsumableSeq<'T> = + inherit IEnumerable<'T> + abstract member Transform<'U> : ISeqTransform<'T,'U> -> IConsumableSeq<'U> + abstract member Consume<'Result> : getConsumer:(PipeIdx->SeqConsumer<'T,'Result>) -> 'Result + namespace Microsoft.FSharp.Collections //------------------------------------------------------------------------- @@ -2982,6 +3044,7 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions open Microsoft.FSharp.Core.BasicInlinedOperations + open Microsoft.FSharp.Collections.SeqComposition [] [>)>] @@ -2992,6 +3055,7 @@ namespace Microsoft.FSharp.Collections type List<'T> = | ([]) : 'T list | (::) : Head: 'T * Tail: 'T list -> 'T list + interface Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq<'T> interface System.Collections.Generic.IEnumerable<'T> interface System.Collections.IEnumerable interface System.Collections.Generic.IReadOnlyCollection<'T> @@ -3043,6 +3107,7 @@ namespace Microsoft.FSharp.Collections let notStarted() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationNotStarted))) let alreadyFinished() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationAlreadyFinished))) let outOfRange() = raise (System.IndexOutOfRangeException(SR.GetString(SR.indexOutOfBounds))) + let noReset() = raise (new System.NotSupportedException(SR.GetString(SR.resetNotSupported))) let nonempty x = match x with [] -> false | _ -> true // optimized mutation-based implementation. This code is only valid in fslib, where mutation of private @@ -3138,6 +3203,92 @@ namespace Microsoft.FSharp.Collections | [] -> outOfRange() loop n l + module ListSeqImplementation = + type CompositionTransform<'T,'U,'V> private (first:ISeqTransform<'T,'U>, second:ISeqTransform<'U,'V>) = + interface ISeqTransform<'T,'V> with + member this.Compose<'W> (outOfBand:ISeqConsumer) (pipeIdx:PipeIdx) (next:SeqConsumerActivity<'V,'W>) : SeqConsumerActivity<'T,'W> = + first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) + + static member Combine (first:ISeqTransform<'T,'U>) (second:ISeqTransform<'U,'V>) : ISeqTransform<'T,'V> = + upcast CompositionTransform(first, second) + + type Result<'T>() = + inherit SeqConsumer<'T,'T>(unsafeDefault<'T>) + + member val SeqState = 1(*NotStarted*) with get, set + + override this.ProcessNext (input:'T) : bool = + this.Result <- input + true + + type ListEnumerator<'T,'U>(alist:list<'T>, activity:SeqConsumerActivity<'T,'U>, result:Result<'U>) = + let mutable list = alist + + let rec moveNext current = + match result.HaltedIdx, current with + | 0, head::tail -> + if activity.ProcessNext head then + list <- tail + true + else + moveNext tail + | _ -> + result.SeqState <- 2(*Finished*) + activity.ChainComplete result.HaltedIdx + false + + interface System.IDisposable with + member __.Dispose () : unit = + activity.ChainDispose () + + interface System.Collections.IEnumerator with + member this.Current : obj = box (this :> IEnumerator<'U>).Current + member __.MoveNext () = + result.SeqState <- 0(*InProcess*) + moveNext list + + member __.Reset () : unit = PrivateListHelpers.noReset () + + interface IEnumerator<'U> with + member __.Current = + if result.SeqState = 0(*InProcess*) then result.Result + elif result.SeqState = 1(*NotStarted*) then PrivateListHelpers.notStarted() + else PrivateListHelpers.alreadyFinished() + + type ListEnumerable<'T,'U>(alist:list<'T>, transform:ISeqTransform<'T,'U>, pipeIdx:PipeIdx) = + interface System.Collections.IEnumerable with + member this.GetEnumerator () : System.Collections.IEnumerator = + upcast (this :> IEnumerable<'U>).GetEnumerator () + + interface System.Collections.Generic.IEnumerable<'U> with + member this.GetEnumerator () : System.Collections.Generic.IEnumerator<'U> = + let result = Result<'U> () + let activity = transform.Compose (result :> ISeqConsumer) pipeIdx result + upcast (new ListEnumerator<'T,'U>(alist, activity, result)) + + interface IConsumableSeq<'U> with + member __.Transform (next:ISeqTransform<'U,'V>) : IConsumableSeq<'V> = + upcast (new ListEnumerable<'T,'V>(alist, CompositionTransform.Combine transform next, pipeIdx+1)) + + member this.Consume<'Result> (createFolder:PipeIdx->SeqConsumer<'U,'Result>) = + let result = createFolder (pipeIdx+1) + let consumer = transform.Compose (result :> ISeqConsumer) pipeIdx result + try + let mutable lst = alist + while + ( match lst with + | hd :: tl when result.HaltedIdx = 0 -> + ignore (consumer.ProcessNext hd) + lst <- tl + true + | _ -> false + ) do () + + consumer.ChainComplete result.HaltedIdx + finally + consumer.ChainDispose () + result.Result + type List<'T> with [] member l.Length = PrivateListHelpers.lengthAcc 0 l @@ -3178,6 +3329,28 @@ namespace Microsoft.FSharp.Collections if i > j then [] else PrivateListHelpers.sliceTake (j-i) (PrivateListHelpers.sliceSkip i l) + interface IConsumableSeq<'T> with + member this.Transform<'U> (next:ISeqTransform<'T,'U>) = + upcast (new ListSeqImplementation.ListEnumerable<'T,'U>(this, next, 1)) + + member this.Consume<'Result> (createFolder:PipeIdx->SeqConsumer<'T,'Result>) = + let result = createFolder 1 + try + let mutable lst = this + while + ( match lst with + | hd :: tl when result.HaltedIdx = 0 -> + ignore (result.ProcessNext hd) + lst <- tl + true + | _ -> false + ) do () + + result.ChainComplete result.HaltedIdx + finally + result.ChainDispose () + result.Result + interface IEnumerable<'T> with member l.GetEnumerator() = PrivateListHelpers.mkListEnumerator l @@ -3192,12 +3365,11 @@ namespace Microsoft.FSharp.Collections type seq<'T> = IEnumerable<'T> - + //------------------------------------------------------------------------- // Operators //------------------------------------------------------------------------- - namespace Microsoft.FSharp.Core open System @@ -3210,8 +3382,7 @@ namespace Microsoft.FSharp.Core open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions open Microsoft.FSharp.Core.BasicInlinedOperations open Microsoft.FSharp.Collections - - + open Microsoft.FSharp.Collections.SeqComposition [] module Operators = @@ -4527,6 +4698,99 @@ namespace Microsoft.FSharp.Core | Running = 1 | Finished = 2 + type CompositionTransform<'T,'U,'V> private (first:ISeqTransform<'T,'U>, second:ISeqTransform<'U,'V>) = + interface ISeqTransform<'T,'V> with + member this.Compose<'W> (outOfBand:ISeqConsumer) (pipeIdx:PipeIdx) (next:SeqConsumerActivity<'V,'W>) : SeqConsumerActivity<'T,'W> = + first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) + + static member Combine (first:ISeqTransform<'T,'U>) (second:ISeqTransform<'U,'V>) : ISeqTransform<'T,'V> = + upcast CompositionTransform(first, second) + + type IdentityTransform<'T> private () = + static let singleton : ISeqTransform<'T,'T> = upcast (IdentityTransform<'T>()) + static member Instance = singleton + interface ISeqTransform<'T,'T> with + member __.Compose<'V> (_outOfBand:ISeqConsumer) (_pipeIdx:PipeIdx) (next:SeqConsumerActivity<'T,'V>) : SeqConsumerActivity<'T,'V> = next + + type SetResultToInput<'T>() = + inherit SeqConsumer<'T,'T>(Unchecked.defaultof<'T>) + override this.ProcessNext (input:'T) : bool = + this.Result <- input + true + + type SeqSourceEnumerator<'T,'U>(source:IEnumerator<'T>, activity:SeqConsumerActivity<'T,'U>, folder:SetResultToInput<'U>) = + let mutable state = Mode.NotStarted + + let rec moveNext () = + if (folder.HaltedIdx = 0) && source.MoveNext () then + if activity.ProcessNext source.Current then + true + else + moveNext () + else + state <- Mode.Finished + activity.ChainComplete folder.HaltedIdx + false + + interface IEnumerator with + member this.Current : obj = box (this :> IEnumerator<'U>).Current + member __.Reset () : unit = source.Reset () + member __.MoveNext () = + state <- Mode.Running + moveNext () + + interface IEnumerator<'U> with + member __.Current = + if state = Mode.Running then folder.Result + else + match state with + | Mode.NotStarted -> notStarted() + | Mode.Finished -> alreadyFinished() + | _ -> failwith "library implementation error: all states should have been handled" + + interface IDisposable with + member __.Dispose () = + try + source.Dispose () + finally + activity.ChainDispose () + + type IConsumableSeqSource<'T> = + abstract member GetEnumerator : unit -> IEnumerator<'T> + abstract member Consume<'Result,'U> : f:(PipeIdx->SeqConsumer<'U,'Result>) -> ISeqTransform<'T,'U> -> PipeIdx -> 'Result + + type SeqSourceEnumerable<'T,'U>(source:IConsumableSeqSource<'T>, current:ISeqTransform<'T,'U>, pipeIdx:PipeIdx) = + interface IEnumerable<'U> with + member __.GetEnumerator () = + let folder = SetResultToInput<'U>() + upcast (new SeqSourceEnumerator<'T,'U>(source.GetEnumerator (), current.Compose (folder :> ISeqConsumer) pipeIdx folder, folder)) + + interface IEnumerable with + member __.GetEnumerator () = + let folder = SetResultToInput<'U>() + upcast (new SeqSourceEnumerator<'T,'U>(source.GetEnumerator (), current.Compose (folder :> ISeqConsumer) pipeIdx folder, folder)) + + interface IConsumableSeq<'U> with + member __.Transform (next:ISeqTransform<'U,'V>) : IConsumableSeq<'V> = + upcast (new SeqSourceEnumerable<'T,'V>(source, CompositionTransform.Combine current next, pipeIdx+1)) + + member this.Consume<'Result> (f:PipeIdx->SeqConsumer<'U,'Result>) = + source.Consume f current pipeIdx + + type SeqSourceEnumerableThin<'U>(source:IConsumableSeqSource<'U>) = + interface IEnumerable<'U> with + member __.GetEnumerator () = source.GetEnumerator () + + interface IEnumerable with + member __.GetEnumerator () = upcast (source.GetEnumerator ()) + + interface IConsumableSeq<'U> with + member __.Transform (next:ISeqTransform<'U,'V>) : IConsumableSeq<'V> = + upcast (new SeqSourceEnumerable<'U,'V>(source, next, 1)) + + member this.Consume<'Result> (f:PipeIdx->SeqConsumer<'U,'Result>) = + source.Consume f IdentityTransform.Instance 1 + [] type BaseRangeEnumerator<'T>() = // Generate enumerator from mutable state "z". @@ -4741,11 +5005,24 @@ namespace Microsoft.FSharp.Core false else false } - { new IEnumerable<'T> with + let source = + { new IConsumableSeqSource<'T> with member __.GetEnumerator () = singleStepRangeEnumerator () - - interface IEnumerable with - member __.GetEnumerator () = (singleStepRangeEnumerator ()) :> IEnumerator } + member __.Consume<'Result,'Output> (createFolder:PipeIdx->SeqConsumer<'Output,'Result>) (transform:ISeqTransform<'T,'Output>) pipeIdx : 'Result = + let result = createFolder (pipeIdx+1) + let consumer = transform.Compose (result :> ISeqConsumer) pipeIdx result + try + let mutable i : 'T = n + while result.HaltedIdx = 0 && i <= m do + consumer.ProcessNext i |> ignore + i <- i + LanguagePrimitives.GenericOne + + consumer.ChainComplete result.HaltedIdx + result.Result + finally + consumer.ChainDispose () } + + upcast (SeqSourceEnumerableThin<'T> source) // For RangeStepGeneric, zero and add are functions representing the static resolution of GenericZero and (+) // for the particular static type. diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index 9e9bb34c2ba..b1b8124b088 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -1745,6 +1745,84 @@ namespace Microsoft.FSharp.Core /// Represents an Error or a Failure. The code failed with a value of 'TError representing what went wrong. | Error of ErrorValue:'TError +namespace Microsoft.FSharp.Collections.SeqComposition + open System + open System.Collections + open System.Collections.Generic + open Microsoft.FSharp.Core + + /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the + /// source of the chain. + type PipeIdx = int + + /// Represents the overall executing consumer and its chain of activities. Used within the + /// pipline to provide "out of band" communications affecting the overall Consume + /// operation, such as early termination. + type ISeqConsumer = + + /// Stop the processing of any further items down the pipeline + abstract StopFurtherProcessing : PipeIdx -> unit + + /// Add a Action delegate that gets notified if StopFurtherProcessing is called + abstract ListenForStopFurtherProcessing : Action -> unit + + /// SeqConsumerActivity is the root class for chains of activities. It is in a non-generic + /// form so that it can be used by subsequent activities + [] + type SeqConsumerActivity = + + /// ChainComplete is called at the end of processing and can + /// set the overall result. It can also determine if the object has been processed correctly, + /// and possibly throw exceptions to denote incorrect application (i.e. such as a Take + /// operation which didn't have a source at least as large as was required). It is + /// not called in the case of an exception being thrown whilst the stream is still + /// being processed. + abstract ChainComplete : PipeIdx -> unit + + /// ChainDispose is used to cleanup the stream. It is always called at the last operation + /// after the enumeration has completed. + abstract ChainDispose : unit -> unit + + /// SeqConsumerActivity is the base class of all elements within the pipeline + [] + type SeqConsumerActivity<'T> = + inherit SeqConsumerActivity + new : unit -> SeqConsumerActivity<'T> + + /// Process an element from the sequence + abstract member ProcessNext : input:'T -> bool + + /// SeqConsumerActivity is the base class of all elements within the pipeline, carrying result type + [] + type SeqConsumerActivity<'T,'U> = + inherit SeqConsumerActivity<'T> + new : unit -> SeqConsumerActivity<'T,'U> + + /// SeqConsumer is a base class to assist with fold-like operations. It's intended usage + /// is as a base class for an object expression that will be used from within + /// the Fold function. + [] + type SeqConsumer<'T,'Result> = + inherit SeqConsumerActivity<'T,'T> + new : 'Result -> SeqConsumer<'T,'Result> + interface ISeqConsumer + member Result : 'Result with get, set + member HaltedIdx : PipeIdx with get + override ChainComplete : PipeIdx -> unit + override ChainDispose : unit -> unit + + /// ISeqTransform provides composition of Activities. Its intended to have a specialization + /// for each type of SeqConsumerActivity. IConsumableSeq's Transform method is used to build a stack + /// of Actvities that will be composed. + type ISeqTransform<'T,'U> = + abstract member Compose : outOfBand: ISeqConsumer -> pipeIdx: PipeIdx -> activity: SeqConsumerActivity<'U,'V> -> SeqConsumerActivity<'T,'V> + + /// IConsumableSeq<'T> is an extension to seq<'T> that can be consumed using a composition of Activities. + type IConsumableSeq<'T> = + inherit System.Collections.Generic.IEnumerable<'T> + abstract member Transform<'U> : ISeqTransform<'T,'U> -> IConsumableSeq<'U> + abstract member Consume<'Result> : getConsumer:(PipeIdx -> SeqConsumer<'T,'Result>) -> 'Result + namespace Microsoft.FSharp.Collections open System @@ -1797,6 +1875,7 @@ namespace Microsoft.FSharp.Collections /// The list with head appended to the front of tail. static member Cons : head:'T * tail:'T list -> 'T list + interface Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq<'T> interface IEnumerable<'T> interface IEnumerable interface IReadOnlyCollection<'T> diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 1397c2475d7..9c4dcbd9484 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1,434 +1,6 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. namespace Microsoft.FSharp.Collections - #nowarn "52" // The value has been copied to ensure the original is not mutated by this operation - - open System - open System.Diagnostics - open System.Collections - open System.Collections.Generic - open Microsoft.FSharp.Core - open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators - open Microsoft.FSharp.Core.Operators - open Microsoft.FSharp.Control - open Microsoft.FSharp.Collections - - module Internal = - module IEnumerator = - open Microsoft.FSharp.Collections.IEnumerator - - let rec tryItem index (e : IEnumerator<'T>) = - if not (e.MoveNext()) then None - elif index = 0 then Some(e.Current) - else tryItem (index-1) e - - let rec nth index (e : IEnumerator<'T>) = - if not (e.MoveNext()) then - let shortBy = index + 1 - invalidArgFmt "index" - "{0}\nseq was short by {1} {2}" - [|SR.GetString SR.notEnoughElements; shortBy; (if shortBy = 1 then "element" else "elements")|] - if index = 0 then e.Current - else nth (index-1) e - - [] - type MapEnumeratorState = - | NotStarted - | InProcess - | Finished - - [] - type MapEnumerator<'T> () = - let mutable state = NotStarted - [] - val mutable private curr : 'T - - member this.GetCurrent () = - match state with - | NotStarted -> notStarted() - | Finished -> alreadyFinished() - | InProcess -> () - this.curr - - abstract DoMoveNext : byref<'T> -> bool - abstract Dispose : unit -> unit - - interface IEnumerator<'T> with - member this.Current = this.GetCurrent() - - interface IEnumerator with - member this.Current = box(this.GetCurrent()) - member this.MoveNext () = - state <- InProcess - if this.DoMoveNext(&this.curr) then - true - else - state <- Finished - false - member this.Reset() = noReset() - interface System.IDisposable with - member this.Dispose() = this.Dispose() - - let map f (e : IEnumerator<_>) : IEnumerator<_>= - upcast - { new MapEnumerator<_>() with - member this.DoMoveNext (curr : byref<_>) = - if e.MoveNext() then - curr <- (f e.Current) - true - else - false - member this.Dispose() = e.Dispose() - } - - let mapi f (e : IEnumerator<_>) : IEnumerator<_> = - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let i = ref (-1) - upcast - { new MapEnumerator<_>() with - member this.DoMoveNext curr = - i := !i + 1 - if e.MoveNext() then - curr <- f.Invoke(!i, e.Current) - true - else - false - member this.Dispose() = e.Dispose() - } - - let map2 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) : IEnumerator<_>= - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - upcast - { new MapEnumerator<_>() with - member this.DoMoveNext curr = - let n1 = e1.MoveNext() - let n2 = e2.MoveNext() - if n1 && n2 then - curr <- f.Invoke(e1.Current, e2.Current) - true - else - false - member this.Dispose() = - try - e1.Dispose() - finally - e2.Dispose() - } - - let mapi2 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) : IEnumerator<_> = - let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) - let i = ref (-1) - upcast - { new MapEnumerator<_>() with - member this.DoMoveNext curr = - i := !i + 1 - if (e1.MoveNext() && e2.MoveNext()) then - curr <- f.Invoke(!i, e1.Current, e2.Current) - true - else - false - member this.Dispose() = - try - e1.Dispose() - finally - e2.Dispose() - } - - let map3 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) (e3 : IEnumerator<_>) : IEnumerator<_> = - let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) - upcast - { new MapEnumerator<_>() with - member this.DoMoveNext curr = - let n1 = e1.MoveNext() - let n2 = e2.MoveNext() - let n3 = e3.MoveNext() - - if n1 && n2 && n3 then - curr <- f.Invoke(e1.Current, e2.Current, e3.Current) - true - else - false - member this.Dispose() = - try - e1.Dispose() - finally - try - e2.Dispose() - finally - e3.Dispose() - } - - let choose f (e : IEnumerator<'T>) = - let started = ref false - let curr = ref None - let get() = check !started; (match !curr with None -> alreadyFinished() | Some x -> x) - { new IEnumerator<'U> with - member x.Current = get() - interface IEnumerator with - member x.Current = box (get()) - member x.MoveNext() = - if not !started then started := true - curr := None - while ((!curr).IsNone && e.MoveNext()) do - curr := f e.Current - Option.isSome !curr - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = e.Dispose() } - - let filter f (e : IEnumerator<'T>) = - let started = ref false - let this = - { new IEnumerator<'T> with - member x.Current = check !started; e.Current - interface IEnumerator with - member x.Current = check !started; box e.Current - member x.MoveNext() = - let rec next() = - if not !started then started := true - e.MoveNext() && (f e.Current || next()) - next() - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = e.Dispose() } - this - - let unfold f x : IEnumerator<_> = - let state = ref x - upcast - { new MapEnumerator<_>() with - member this.DoMoveNext curr = - match f !state with - | None -> false - | Some(r,s) -> - curr <- r - state := s - true - member this.Dispose() = () - } - - let upto lastOption f = - match lastOption with - | Some b when b<0 -> Empty() // a request for -ve length returns empty sequence - | _ -> - let unstarted = -1 // index value means unstarted (and no valid index) - let completed = -2 // index value means completed (and no valid index) - let unreachable = -3 // index is unreachable from 0,1,2,3,... - let finalIndex = match lastOption with - | Some b -> b // here b>=0, a valid end value. - | None -> unreachable // run "forever", well as far as Int32.MaxValue since indexing with a bounded type. - // The Current value for a valid index is "f i". - // Lazy<_> values are used as caches, to store either the result or an exception if thrown. - // These "Lazy<_>" caches are created only on the first call to current and forced immediately. - // The lazy creation of the cache nodes means enumerations that skip many Current values are not delayed by GC. - // For example, the full enumeration of Seq.initInfinite in the tests. - // state - let index = ref unstarted - // a Lazy node to cache the result/exception - let current = ref (Unchecked.defaultof<_>) - let setIndex i = index := i; current := (Unchecked.defaultof<_>) // cache node unprimed, initialised on demand. - let getCurrent() = - if !index = unstarted then notStarted() - if !index = completed then alreadyFinished() - match box !current with - | null -> current := Lazy<_>.Create(fun () -> f !index) - | _ -> () - // forced or re-forced immediately. - (!current).Force() - { new IEnumerator<'U> with - member x.Current = getCurrent() - interface IEnumerator with - member x.Current = box (getCurrent()) - member x.MoveNext() = - if !index = completed then - false - elif !index = unstarted then - setIndex 0 - true - else ( - if !index = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) - if !index = finalIndex then - false - else - setIndex (!index + 1) - true - ) - member self.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = () } - - [] - type ArrayEnumerator<'T>(arr: 'T array) = - let mutable curr = -1 - let mutable len = arr.Length - member x.Get() = - if curr >= 0 then - if curr >= len then alreadyFinished() - else arr.[curr] - else - notStarted() - interface IEnumerator<'T> with - member x.Current = x.Get() - interface System.Collections.IEnumerator with - member x.MoveNext() = - if curr >= len then false - else - curr <- curr + 1 - (curr < len) - member x.Current = box(x.Get()) - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = () - - let ofArray arr = (new ArrayEnumerator<'T>(arr) :> IEnumerator<'T>) - - // Use generators for some implementations of IEnumerables. - // - module Generator = - - open System.Collections - open System.Collections.Generic - - [] - type Step<'T> = - | Stop - | Yield of 'T - | Goto of Generator<'T> - - and Generator<'T> = - abstract Apply: (unit -> Step<'T>) - abstract Disposer: (unit -> unit) option - - let disposeG (g:Generator<'T>) = - match g.Disposer with - | None -> () - | Some f -> f() - - let appG (g:Generator<_>) = - //System.Console.WriteLine("{0}.appG", box g) - let res = g.Apply() - match res with - | Goto(next) -> - Goto(next) - | Yield _ -> - res - | Stop -> - //System.Console.WriteLine("appG: Stop") - disposeG g - res - - // Binding. - // - // We use a type definition to apply a local dynamic optimization. - // We automatically right-associate binding, i.e. push the continuations to the right. - // That is, bindG (bindG G1 cont1) cont2 --> bindG G1 (cont1 o cont2) - // This makes constructs such as the following linear rather than quadratic: - // - // let rec rwalk n = { if n > 0 then - // yield! rwalk (n-1) - // yield n } - - type GenerateThen<'T>(g:Generator<'T>, cont : unit -> Generator<'T>) = - member self.Generator = g - member self.Cont = cont - interface Generator<'T> with - member x.Apply = (fun () -> - match appG g with - | Stop -> - // OK, move onto the generator given by the continuation - Goto(cont()) - - | Yield _ as res -> - res - - | Goto next -> - Goto(GenerateThen<_>.Bind(next,cont))) - member x.Disposer = - g.Disposer - - - static member Bind (g:Generator<'T>, cont) = - match g with - | :? GenerateThen<'T> as g -> GenerateThen<_>.Bind(g.Generator,(fun () -> GenerateThen<_>.Bind (g.Cont(), cont))) - | g -> (new GenerateThen<'T>(g, cont) :> Generator<'T>) - - - let bindG g cont = GenerateThen<_>.Bind(g,cont) - - - // Internal type. Drive an underlying generator. Crucially when the generator returns - // a new generator we simply update our current generator and continue. Thus the enumerator - // effectively acts as a reference cell holding the current generator. This means that - // infinite or large generation chains (e.g. caused by long sequences of append's, including - // possible delay loops) can be referenced via a single enumerator. - // - // A classic case where this arises in this sort of sequence expression: - // let rec data s = { yield s; - // yield! data (s + random()) } - // - // This translates to - // let rec data s = Seq.delay (fun () -> Seq.append (Seq.singleton s) (Seq.delay (fun () -> data (s+random())))) - // - // When you unwind through all the Seq, IEnumerator and Generator objects created, - // you get (data s).GetEnumerator being an "GenerateFromEnumerator(EnumeratorWrappingLazyGenerator(...))" for the append. - // After one element is yielded, we move on to the generator for the inner delay, which in turn - // comes back to be a "GenerateFromEnumerator(EnumeratorWrappingLazyGenerator(...))". - // - // Defined as a type so we can optimize Enumerator/Generator chains in enumerateFromLazyGenerator - // and GenerateFromEnumerator. - - [] - type EnumeratorWrappingLazyGenerator<'T>(g:Generator<'T>) = - let mutable g = g - let mutable curr = None - let mutable finished = false - member e.Generator = g - interface IEnumerator<'T> with - member x.Current= match curr with Some(v) -> v | None -> raise <| System.InvalidOperationException (SR.GetString(SR.moveNextNotCalledOrFinished)) - interface System.Collections.IEnumerator with - member x.Current = box (x :> IEnumerator<_>).Current - member x.MoveNext() = - not finished && - (match appG g with - | Stop -> - curr <- None - finished <- true - false - | Yield(v) -> - curr <- Some(v) - true - | Goto(next) -> - (g <- next) - (x :> IEnumerator).MoveNext()) - member x.Reset() = IEnumerator.noReset() - interface System.IDisposable with - member x.Dispose() = - if not finished then disposeG g - - // Internal type, used to optimize Enumerator/Generator chains - type LazyGeneratorWrappingEnumerator<'T>(e:IEnumerator<'T>) = - member g.Enumerator = e - interface Generator<'T> with - member g.Apply = (fun () -> - if e.MoveNext() then - Yield(e.Current) - else - Stop) - member g.Disposer= Some(e.Dispose) - - let EnumerateFromGenerator(g:Generator<'T>) = - match g with - | :? LazyGeneratorWrappingEnumerator<'T> as g -> g.Enumerator - | _ -> (new EnumeratorWrappingLazyGenerator<'T>(g) :> IEnumerator<'T>) - - let GenerateFromEnumerator (e:IEnumerator<'T>) = - match e with - | :? EnumeratorWrappingLazyGenerator<'T> as e -> e.Generator - | _ -> (new LazyGeneratorWrappingEnumerator<'T>(e) :> Generator<'T>) - - -namespace Microsoft.FSharp.Collections - open System open System.Diagnostics open System.Collections @@ -440,247 +12,208 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Core.CompilerServices open Microsoft.FSharp.Control open Microsoft.FSharp.Collections - open Microsoft.FSharp.Primitives.Basics - - [] - type CachedSeq<'T>(cleanup,res:seq<'T>) = - interface System.IDisposable with - member x.Dispose() = cleanup() - interface System.Collections.Generic.IEnumerable<'T> with - member x.GetEnumerator() = res.GetEnumerator() - interface System.Collections.IEnumerable with - member x.GetEnumerator() = (res :> System.Collections.IEnumerable).GetEnumerator() - member obj.Clear() = cleanup() - + open Microsoft.FSharp.Collections.IEnumerator + open Microsoft.FSharp.Collections.SeqComposition [] [] module Seq = - open Microsoft.FSharp.Collections.Internal - open Microsoft.FSharp.Collections.IEnumerator + // these helpers are just to consolidate the null checking + let inline toIConsumableSeq (source:seq<'T>) : IConsumableSeq<'T> = checkNonNull "source" source; IConsumableSeq.ofSeq source + let inline toIConsumableSeq1 (source1:seq<'T>) : IConsumableSeq<'T> = checkNonNull "source1" source1; IConsumableSeq.ofSeq source1 + let inline toIConsumableSeq2 (source2:seq<'T>) : IConsumableSeq<'T> = checkNonNull "source2" source2; IConsumableSeq.ofSeq source2 + let inline toIConsumableSeq3 (source3:seq<'T>) : IConsumableSeq<'T> = checkNonNull "source3" source3; IConsumableSeq.ofSeq source3 + let inline toIConsumableSeqs (sources:seq<'T>) : IConsumableSeq<'T> = checkNonNull "sources" sources; IConsumableSeq.ofSeq sources + + let getRaw (source:IConsumableSeq<_>) = + match source with + | :? Core.EnumerableBase<'T> as s -> s.GetRaw () + | _ -> upcast source + + let rawOrOriginal (raw:seq<_>) (original:IConsumableSeq<_>) = + if obj.ReferenceEquals (raw, original) then original else toIConsumableSeq raw let mkDelayedSeq (f: unit -> IEnumerable<'T>) = mkSeq (fun () -> f().GetEnumerator()) - let mkUnfoldSeq f x = mkSeq (fun () -> IEnumerator.unfold f x) - let inline indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) [] let delay generator = mkDelayedSeq generator [] - let unfold generator state = mkUnfoldSeq generator state + let unfold generator state = + IConsumableSeq.unfold generator state :> seq<_> [] - let empty<'T> = (EmptyEnumerable :> seq<'T>) + let empty<'T> = + IConsumableSeq.empty<'T> :> seq<'T> [] - let initInfinite initializer = mkSeq (fun () -> IEnumerator.upto None initializer) + let initInfinite initializer = + IConsumableSeq.initInfinite initializer :> seq<_> [] let init count initializer = - if count < 0 then invalidArgInputMustBeNonNegative "count" count - mkSeq (fun () -> IEnumerator.upto (Some (count-1)) initializer) + IConsumableSeq.init count initializer :> seq<_> [] - let iter action (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() - while e.MoveNext() do - action e.Current + let iter action (source:seq<'T>) = + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.iter action arr + | :? list<'T> as lst -> List.iter action lst + | raw -> IConsumableSeq.iter action (rawOrOriginal raw original) + + let rec enumeratorItem index (e : IEnumerator<'T>) = + if not (e.MoveNext()) then + let shortBy = index + 1 + invalidArgFmt "index" + "{0}\nseq was short by {1} {2}" + [|SR.GetString SR.notEnoughElements; shortBy; (if shortBy = 1 then "element" else "elements")|] + if index = 0 then e.Current + else enumeratorItem (index-1) e [] let item index (source : seq<'T>) = checkNonNull "source" source if index < 0 then invalidArgInputMustBeNonNegative "index" index use e = source.GetEnumerator() - IEnumerator.nth index e + enumeratorItem index e [] let tryItem index (source : seq<'T>) = - checkNonNull "source" source - if index < 0 then None else - use e = source.GetEnumerator() - IEnumerator.tryItem index e + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.tryItem index arr + | :? list<'T> as lst -> List.tryItem index lst + | raw -> IConsumableSeq.tryItem index (rawOrOriginal raw original) [] let nth index (source : seq<'T>) = item index source [] - let iteri action (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(action) - let mutable i = 0 - while e.MoveNext() do - f.Invoke(i, e.Current) - i <- i + 1 + let iteri action (source:seq<'T>) = + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.iteri action arr + | :? list<'T> as lst -> List.iteri action lst + | raw -> + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt action + IConsumableSeq.iteri (fun idx a -> f.Invoke (idx,a)) (rawOrOriginal raw original) [] - let exists predicate (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() - let mutable state = false - while (not state && e.MoveNext()) do - state <- predicate e.Current - state + let exists predicate (source:seq<'T>) = + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.exists predicate arr + | :? list<'T> as lst -> List.exists predicate lst + | raw -> IConsumableSeq.exists predicate (rawOrOriginal raw original) [] - let inline contains value (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() - let mutable state = false - while (not state && e.MoveNext()) do - state <- value = e.Current - state + let inline contains value (source:seq<'T>) = + IConsumableSeq.contains value (toIConsumableSeq source) [] - let forall predicate (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() - let mutable state = true - while (state && e.MoveNext()) do - state <- predicate e.Current - state + let forall predicate (source:seq<'T>) = + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.forall predicate arr + | :? list<'T> as lst -> List.forall predicate lst + | raw -> IConsumableSeq.forall predicate (rawOrOriginal raw original) [] - let iter2 action (source1 : seq<_>) (source2 : seq<_>) = - checkNonNull "source1" source1 - checkNonNull "source2" source2 - use e1 = source1.GetEnumerator() - use e2 = source2.GetEnumerator() - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(action) - while (e1.MoveNext() && e2.MoveNext()) do - f.Invoke(e1.Current, e2.Current) + let iter2 action (source1:seq<_>) (source2:seq<_>) = + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt action + IConsumableSeq.iter2 (fun a b -> f.Invoke(a,b)) (source1 |> toIConsumableSeq1) (source2 |> toIConsumableSeq2) [] let iteri2 action (source1 : seq<_>) (source2 : seq<_>) = - checkNonNull "source1" source1 - checkNonNull "source2" source2 - use e1 = source1.GetEnumerator() - use e2 = source2.GetEnumerator() - let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(action) - let mutable i = 0 - while (e1.MoveNext() && e2.MoveNext()) do - f.Invoke(i, e1.Current, e2.Current) - i <- i + 1 - - // Build an IEnumerable by wrapping/transforming iterators as they get generated. - let revamp f (ie : seq<_>) = mkSeq (fun () -> f (ie.GetEnumerator())) - let revamp2 f (ie1 : seq<_>) (source2 : seq<_>) = - mkSeq (fun () -> f (ie1.GetEnumerator()) (source2.GetEnumerator())) - let revamp3 f (ie1 : seq<_>) (source2 : seq<_>) (source3 : seq<_>) = - mkSeq (fun () -> f (ie1.GetEnumerator()) (source2.GetEnumerator()) (source3.GetEnumerator())) + let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt action + IConsumableSeq.iteri2 (fun idx a b -> f.Invoke(idx,a,b)) (source1 |> toIConsumableSeq1) (source2 |> toIConsumableSeq2) [] - let filter predicate source = - checkNonNull "source" source - revamp (IEnumerator.filter predicate) source + let filter predicate source = + IConsumableSeq.filter predicate (toIConsumableSeq source) :> seq<_> [] let where predicate source = filter predicate source [] - let map mapping source = - checkNonNull "source" source - revamp (IEnumerator.map mapping) source + let map mapping source = + IConsumableSeq.map mapping (toIConsumableSeq source) :> seq<_> [] - let mapi mapping source = - checkNonNull "source" source - revamp (IEnumerator.mapi mapping) source + let mapi mapping source = + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapping + IConsumableSeq.mapi (fun idx a ->f.Invoke(idx,a)) (toIConsumableSeq source) :> seq<_> [] let mapi2 mapping source1 source2 = - checkNonNull "source1" source1 - checkNonNull "source2" source2 - revamp2 (IEnumerator.mapi2 mapping) source1 source2 + let f = OptimizedClosures.FSharpFunc.Adapt mapping + IConsumableSeq.mapi2 (fun idx a b -> f.Invoke (idx,a,b)) (source1 |> toIConsumableSeq1) (source2 |> toIConsumableSeq2) :> seq<_> [] let map2 mapping source1 source2 = - checkNonNull "source1" source1 - checkNonNull "source2" source2 - revamp2 (IEnumerator.map2 mapping) source1 source2 + IConsumableSeq.map2 mapping (source1 |> toIConsumableSeq1) (source2 |> toIConsumableSeq2) :> seq<_> [] let map3 mapping source1 source2 source3 = - checkNonNull "source1" source1 - checkNonNull "source2" source2 - checkNonNull "source3" source3 - revamp3 (IEnumerator.map3 mapping) source1 source2 source3 + IConsumableSeq.map3 mapping (source1 |> toIConsumableSeq1) (source2 |> toIConsumableSeq2) (source3 |> toIConsumableSeq3) :> seq<_> [] - let choose chooser source = - checkNonNull "source" source - revamp (IEnumerator.choose chooser) source + let choose chooser source = + IConsumableSeq.choose chooser (toIConsumableSeq source) :> seq<_> [] let indexed source = - checkNonNull "source" source - mapi (fun i x -> i,x) source + IConsumableSeq.indexed (toIConsumableSeq source) :> seq<_> [] let zip source1 source2 = - checkNonNull "source1" source1 - checkNonNull "source2" source2 - map2 (fun x y -> x,y) source1 source2 + IConsumableSeq.zip (source1 |> toIConsumableSeq1) (source2 |> toIConsumableSeq2) :> seq<_> [] let zip3 source1 source2 source3 = - checkNonNull "source1" source1 - checkNonNull "source2" source2 - checkNonNull "source3" source3 - map2 (fun x (y,z) -> x,y,z) source1 (zip source2 source3) + IConsumableSeq.zip3 (source1 |> toIConsumableSeq1) (source2 |> toIConsumableSeq2) (source3 |> toIConsumableSeq3) :> seq<_> [] let cast (source: IEnumerable) = - checkNonNull "source" source - mkSeq (fun () -> IEnumerator.cast (source.GetEnumerator())) + source |> IConsumableSeq.cast :> seq<_> [] let tryPick chooser (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() - let mutable res = None - while (Option.isNone res && e.MoveNext()) do - res <- chooser e.Current - res + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.tryPick chooser arr + | :? list<'T> as lst -> List.tryPick chooser lst + | raw -> IConsumableSeq.tryPick chooser (rawOrOriginal raw original) [] let pick chooser source = - checkNonNull "source" source - match tryPick chooser source with - | None -> indexNotFound() - | Some x -> x + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.pick chooser arr + | :? list<'T> as lst -> List.pick chooser lst + | raw -> IConsumableSeq.pick chooser (rawOrOriginal raw original) [] let tryFind predicate (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() - let mutable res = None - while (Option.isNone res && e.MoveNext()) do - let c = e.Current - if predicate c then res <- Some(c) - res + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.tryFind predicate arr + | :? list<'T> as lst -> List.tryFind predicate lst + | raw -> IConsumableSeq.tryFind predicate (rawOrOriginal raw original) [] let find predicate source = - checkNonNull "source" source - match tryFind predicate source with - | None -> indexNotFound() - | Some x -> x + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.find predicate arr + | :? list<'T> as lst -> List.find predicate lst + | raw -> IConsumableSeq.find predicate (rawOrOriginal raw original) [] let take count (source : seq<'T>) = - checkNonNull "source" source - if count < 0 then invalidArgInputMustBeNonNegative "count" count - (* Note: don't create or dispose any IEnumerable if n = 0 *) - if count = 0 then empty else - seq { use e = source.GetEnumerator() - for x in 0 .. count - 1 do - if not (e.MoveNext()) then - invalidOpFmt "tried to take {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - yield e.Current } + IConsumableSeq.take count (toIConsumableSeq source) :> seq<_> [] let isEmpty (source : seq<'T>) = @@ -693,334 +226,154 @@ namespace Microsoft.FSharp.Collections use ie = source.GetEnumerator() not (ie.MoveNext()) - [] let concat sources = - checkNonNull "sources" sources - RuntimeHelpers.mkConcatSeq sources + sources |> toIConsumableSeqs |> IConsumableSeq.map toIConsumableSeq |> IConsumableSeq.concat :> seq<_> [] let length (source : seq<'T>) = - checkNonNull "source" source - match source with - | :? ('T[]) as a -> a.Length - | :? ('T list) as a -> a.Length - | :? ICollection<'T> as a -> a.Count - | _ -> - use e = source.GetEnumerator() - let mutable state = 0 - while e.MoveNext() do - state <- state + 1 - state + IConsumableSeq.length (toIConsumableSeq source) [] - let fold<'T,'State> folder (state:'State) (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(folder) - let mutable state = state - while e.MoveNext() do - state <- f.Invoke(state, e.Current) - state + let fold<'T,'State> folder (state:'State) (source:seq<'T>) = + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.fold folder state arr + | :? list<'T> as lst -> List.fold folder state lst + | raw -> + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + IConsumableSeq.fold (fun acc item -> f.Invoke (acc, item)) state (rawOrOriginal raw original) [] - let fold2<'T1,'T2,'State> folder (state:'State) (source1: seq<'T1>) (source2: seq<'T2>) = - checkNonNull "source1" source1 - checkNonNull "source2" source2 - - use e1 = source1.GetEnumerator() - use e2 = source2.GetEnumerator() - - let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(folder) - - let mutable state = state - while e1.MoveNext() && e2.MoveNext() do - state <- f.Invoke(state, e1.Current, e2.Current) - - state + let fold2<'T1,'T2,'State> folder (state:'State) (source1:seq<'T1>) (source2:seq<'T2>) = + let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt folder + IConsumableSeq.fold2 (fun acc item1 item2 -> f.Invoke (acc, item1, item2)) state (source1 |> toIConsumableSeq1) (source2 |> toIConsumableSeq2) [] let reduce reduction (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(reduction) - let mutable state = e.Current - while e.MoveNext() do - state <- f.Invoke(state, e.Current) - state - - let fromGenerator f = mkSeq(fun () -> Generator.EnumerateFromGenerator (f())) - let toGenerator (ie : seq<_>) = Generator.GenerateFromEnumerator (ie.GetEnumerator()) + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.reduce reduction arr + | :? list<'T> as lst -> List.reduce reduction lst + | raw -> + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt reduction + IConsumableSeq.reduce (fun acc item -> f.Invoke (acc, item)) (rawOrOriginal raw original) [] let replicate count initial = - System.Linq.Enumerable.Repeat(initial,count) + IConsumableSeq.replicate count initial :> seq<_> [] let append (source1: seq<'T>) (source2: seq<'T>) = - checkNonNull "source1" source1 - checkNonNull "source2" source2 - fromGenerator(fun () -> Generator.bindG (toGenerator source1) (fun () -> toGenerator source2)) - + IConsumableSeq.append (source1 |> toIConsumableSeq1) (source2 |> toIConsumableSeq2) :> seq<_> [] - let collect mapping source = map mapping source |> concat + let collect mapping source = + map mapping source |> concat [] - let compareWith (comparer:'T -> 'T -> int) (source1 : seq<'T>) (source2: seq<'T>) = - checkNonNull "source1" source1 - checkNonNull "source2" source2 - use e1 = source1.GetEnumerator() - use e2 = source2.GetEnumerator() - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(comparer) - let rec go () = - let e1ok = e1.MoveNext() - let e2ok = e2.MoveNext() - let c = if e1ok = e2ok then 0 else if e1ok then 1 else -1 - if c <> 0 then c else - if not e1ok || not e2ok then 0 - else - let c = f.Invoke(e1.Current, e2.Current) - if c <> 0 then c else - go () - go() + let compareWith (comparer:'T->'T->int) (source1:seq<'T>) (source2:seq<'T>) = + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt comparer + IConsumableSeq.compareWith (fun a b -> f.Invoke(a,b)) (source1 |> toIConsumableSeq1) (source2 |> toIConsumableSeq2) [] let ofList (source : 'T list) = - (source :> seq<'T>) + IConsumableSeq.ofList source :> seq<_> [] let toList (source : seq<'T>) = - checkNonNull "source" source - Microsoft.FSharp.Primitives.Basics.List.ofSeq source + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.toList arr + | :? list<'T> as lst -> lst + | raw -> IConsumableSeq.toList (rawOrOriginal raw original) - // Create a new object to ensure underlying array may not be mutated by a backdoor cast [] let ofArray (source : 'T array) = - checkNonNull "source" source - mkSeq (fun () -> IEnumerator.ofArray source) + IConsumableSeq.ofArray source :> seq<_> [] let toArray (source : seq<'T>) = - checkNonNull "source" source - match source with - | :? ('T[]) as res -> (res.Clone() :?> 'T[]) - | :? ('T list) as res -> List.toArray res + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.copy arr + | :? list<'T> as lst -> List.toArray lst | :? ICollection<'T> as res -> // Directly create an array and copy ourselves. // This avoids an extra copy if using ResizeArray in fallback below. - let arr = Array.zeroCreateUnchecked res.Count + let arr = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked res.Count res.CopyTo(arr, 0) arr - | _ -> - let res = ResizeArray<_>(source) - res.ToArray() - - let foldArraySubRight (f:OptimizedClosures.FSharpFunc<'T,_,_>) (arr: 'T[]) start fin acc = - let mutable state = acc - for i = fin downto start do - state <- f.Invoke(arr.[i], state) - state + | raw -> IConsumableSeq.toArray (rawOrOriginal raw original) [] - let foldBack<'T,'State> folder (source : seq<'T>) (state:'State) = - checkNonNull "source" source - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(folder) - let arr = toArray source - let len = arr.Length - foldArraySubRight f arr 0 (len - 1) state + let foldBack<'T,'State> folder (source:seq<'T>) (state:'State) = + IConsumableSeq.foldBack folder (toIConsumableSeq source) state [] - let foldBack2<'T1,'T2,'State> folder (source1 : seq<'T1>) (source2 : seq<'T2>) (state:'State) = - let zipped = zip source1 source2 - foldBack ((<||) folder) zipped state + let foldBack2<'T1,'T2,'State> folder (source1:seq<'T1>) (source2:seq<'T2>) (state:'State) = + IConsumableSeq.foldBack2 folder (toIConsumableSeq1 source1) (toIConsumableSeq2 source2) state [] - let reduceBack reduction (source : seq<'T>) = - checkNonNull "source" source - let arr = toArray source - match arr.Length with - | 0 -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - | len -> - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(reduction) - foldArraySubRight f arr 0 (len - 2) arr.[len - 1] + let reduceBack reduction (source:seq<'T>) = + IConsumableSeq.reduceBack reduction (toIConsumableSeq source) [] - let singleton value = mkSeq (fun () -> IEnumerator.Singleton value) + let singleton value = + IConsumableSeq.singleton value :> seq<_> [] let truncate count (source: seq<'T>) = - checkNonNull "source" source - seq { let i = ref 0 - use ie = source.GetEnumerator() - while !i < count && ie.MoveNext() do - i := !i + 1 - yield ie.Current } + IConsumableSeq.truncate count (toIConsumableSeq source) :> seq<_> [] let pairwise (source: seq<'T>) = - checkNonNull "source" source - seq { use ie = source.GetEnumerator() - if ie.MoveNext() then - let iref = ref ie.Current - while ie.MoveNext() do - let j = ie.Current - yield (!iref, j) - iref := j } + IConsumableSeq.pairwise (toIConsumableSeq source) :> seq<_> [] let scan<'T,'State> folder (state:'State) (source : seq<'T>) = - checkNonNull "source" source - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(folder) - seq { let zref = ref state - yield !zref - use ie = source.GetEnumerator() - while ie.MoveNext() do - zref := f.Invoke(!zref, ie.Current) - yield !zref } + IConsumableSeq.scan folder state (toIConsumableSeq source) :> seq<_> [] let tryFindBack predicate (source : seq<'T>) = - checkNonNull "source" source - source |> toArray |> Array.tryFindBack predicate + IConsumableSeq.tryFindBack predicate (toIConsumableSeq source) [] let findBack predicate source = - checkNonNull "source" source - source |> toArray |> Array.findBack predicate + IConsumableSeq.findBack predicate (toIConsumableSeq source) [] - let scanBack<'T,'State> folder (source : seq<'T>) (state:'State) = - checkNonNull "source" source - mkDelayedSeq(fun () -> - let arr = source |> toArray - let res = Array.scanSubRight folder arr 0 (arr.Length - 1) state - res :> seq<_>) + let scanBack<'T,'State> folder (source:seq<'T>) (state:'State) = + IConsumableSeq.scanBack folder (toIConsumableSeq source) state :> seq<_> [] let findIndex predicate (source:seq<_>) = - checkNonNull "source" source - use ie = source.GetEnumerator() - let rec loop i = - if ie.MoveNext() then - if predicate ie.Current then - i - else loop (i+1) - else - indexNotFound() - loop 0 + IConsumableSeq.findIndex predicate (toIConsumableSeq source) [] let tryFindIndex predicate (source:seq<_>) = - checkNonNull "source" source - use ie = source.GetEnumerator() - let rec loop i = - if ie.MoveNext() then - if predicate ie.Current then - Some i - else loop (i+1) - else - None - loop 0 + IConsumableSeq.tryFindIndex predicate (toIConsumableSeq source) [] let tryFindIndexBack predicate (source : seq<'T>) = - checkNonNull "source" source - source |> toArray |> Array.tryFindIndexBack predicate + IConsumableSeq.tryFindIndexBack predicate (toIConsumableSeq source) [] let findIndexBack predicate source = - checkNonNull "source" source - source |> toArray |> Array.findIndexBack predicate + IConsumableSeq.findIndexBack predicate (toIConsumableSeq source) // windowed : int -> seq<'T> -> seq<'T[]> [] let windowed windowSize (source: seq<_>) = - checkNonNull "source" source - if windowSize <= 0 then invalidArgFmt "windowSize" "{0}\nwindowSize = {1}" - [|SR.GetString SR.inputMustBePositive; windowSize|] - seq { - let arr = Array.zeroCreateUnchecked windowSize - let r = ref (windowSize - 1) - let i = ref 0 - use e = source.GetEnumerator() - while e.MoveNext() do - arr.[!i] <- e.Current - i := (!i + 1) % windowSize - if !r = 0 then - if windowSize < 32 then - yield Array.init windowSize (fun j -> arr.[(!i+j) % windowSize]) - else - let result = Array.zeroCreateUnchecked windowSize - Array.Copy(arr, !i, result, 0, windowSize - !i) - Array.Copy(arr, 0, result, windowSize - !i, !i) - yield result - else r := (!r - 1) - } + IConsumableSeq.windowed windowSize (toIConsumableSeq source) :> seq<_> [] let cache (source : seq<'T>) = - checkNonNull "source" source - // Wrap a seq to ensure that it is enumerated just once and only as far as is necessary. - // - // This code is required to be thread safe. - // The necessary calls should be called at most once (include .MoveNext() = false). - // The enumerator should be disposed (and dropped) when no longer required. - //------ - // The state is (prefix,enumerator) with invariants: - // * the prefix followed by elts from the enumerator are the initial sequence. - // * the prefix contains only as many elements as the longest enumeration so far. - let prefix = ResizeArray<_>() - let enumeratorR = ref None : IEnumerator<'T> option option ref // nested options rather than new type... - // None = Unstarted. - // Some(Some e) = Started. - // Some None = Finished. - let oneStepTo i = - // If possible, step the enumeration to prefix length i (at most one step). - // Be speculative, since this could have already happened via another thread. - if not (i < prefix.Count) then // is a step still required? - // If not yet started, start it (create enumerator). - match !enumeratorR with - | None -> enumeratorR := Some (Some (source.GetEnumerator())) - | Some _ -> () - match (!enumeratorR).Value with - | Some enumerator -> if enumerator.MoveNext() then - prefix.Add(enumerator.Current) - else - enumerator.Dispose() // Move failed, dispose enumerator, - enumeratorR := Some None // drop it and record finished. - | None -> () - let result = - unfold (fun i -> - // i being the next position to be returned - // A lock is needed over the reads to prefix.Count since the list may be being resized - // NOTE: we could change to a reader/writer lock here - lock enumeratorR (fun () -> - if i < prefix.Count then - Some (prefix.[i],i+1) - else - oneStepTo i - if i < prefix.Count then - Some (prefix.[i],i+1) - else - None)) 0 - let cleanup() = - lock enumeratorR (fun () -> - prefix.Clear() - begin match !enumeratorR with - | Some (Some e) -> IEnumerator.dispose e - | _ -> () - end - enumeratorR := None) - (new CachedSeq<_>(cleanup, result) :> seq<_>) + IConsumableSeq.cache (toIConsumableSeq source) :> seq<_> [] let allPairs source1 source2 = - checkNonNull "source1" source1 - checkNonNull "source2" source2 - let cached = cache source2 - source1 |> collect (fun x -> cached |> map (fun y -> x,y)) + IConsumableSeq.allPairs (source1 |> toIConsumableSeq1) (source2 |> toIConsumableSeq2) :> seq<_> [] [] @@ -1028,50 +381,21 @@ namespace Microsoft.FSharp.Collections checkNonNull "source" source mkSeq (fun () -> source.GetEnumerator()) - let inline groupByImpl (comparer:IEqualityComparer<'SafeKey>) (keyf:'T->'SafeKey) (getKey:'SafeKey->'Key) (seq:seq<'T>) = - checkNonNull "seq" seq - - let dict = Dictionary<_,ResizeArray<_>> comparer - - // Previously this was 1, but I think this is rather stingy, considering that we are already paying - // for at least a key, the ResizeArray reference, which includes an array reference, an Entry in the - // Dictionary, plus any empty space in the Dictionary of unfilled hash buckets. - let minimumBucketSize = 4 - - // Build the groupings - seq |> iter (fun v -> - let safeKey = keyf v - let mutable prev = Unchecked.defaultof<_> - match dict.TryGetValue (safeKey, &prev) with - | true -> prev.Add v - | false -> - let prev = ResizeArray () - dict.[safeKey] <- prev - prev.Add v) - - // Trim the size of each result group, don't trim very small buckets, as excessive work, and garbage for - // minimal gain - dict |> iter (fun group -> if group.Value.Count > minimumBucketSize then group.Value.TrimExcess()) - - // Return the sequence-of-sequences. Don't reveal the - // internal collections: just reveal them as sequences - dict |> map (fun group -> (getKey group.Key, readonly group.Value)) - - // We avoid wrapping a StructBox, because under 64 JIT we get some "hard" tailcalls which affect performance - let groupByValueType (keyf:'T->'Key) (seq:seq<'T>) = seq |> groupByImpl HashIdentity.Structural<'Key> keyf id - - // Wrap a StructBox around all keys in case the key type is itself a type using null as a representation - let groupByRefType (keyf:'T->'Key) (seq:seq<'T>) = seq |> groupByImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun t -> RuntimeHelpers.StructBox (keyf t)) (fun sb -> sb.Value) - [] let groupBy (projection:'T->'Key) (source:seq<'T>) = + delay (fun () -> + let grouped = #if FX_RESHAPED_REFLECTION - if (typeof<'Key>).GetTypeInfo().IsValueType + if (typeof<'Key>).GetTypeInfo().IsValueType #else - if typeof<'Key>.IsValueType + if typeof<'Key>.IsValueType #endif - then mkDelayedSeq (fun () -> groupByValueType projection source) - else mkDelayedSeq (fun () -> groupByRefType projection source) + then source |> toIConsumableSeq |> IConsumableSeq.GroupBy.byVal projection + else source |> toIConsumableSeq |> IConsumableSeq.GroupBy.byRef projection + + grouped + |> IConsumableSeq.map (fun (key,value) -> key, value :> seq<_>) + :> seq<_>) [] let transpose (source: seq<#seq<'T>>) = @@ -1083,404 +407,169 @@ namespace Microsoft.FSharp.Collections [] let distinct source = - checkNonNull "source" source - seq { let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) - for v in source do - if hashSet.Add(v) then - yield v } + IConsumableSeq.distinct (toIConsumableSeq source) :> seq<_> [] let distinctBy projection source = - checkNonNull "source" source - seq { let hashSet = HashSet<_>(HashIdentity.Structural<_>) - for v in source do - if hashSet.Add(projection v) then - yield v } + IConsumableSeq.distinctBy projection (toIConsumableSeq source) :> seq<_> [] let sortBy projection source = - checkNonNull "source" source - mkDelayedSeq (fun () -> - let array = source |> toArray - Array.stableSortInPlaceBy projection array - array :> seq<_>) + IConsumableSeq.sortBy projection (toIConsumableSeq source) :> seq<_> [] let sort source = - checkNonNull "source" source - mkDelayedSeq (fun () -> - let array = source |> toArray - Array.stableSortInPlace array - array :> seq<_>) + IConsumableSeq.sort (toIConsumableSeq source) :> seq<_> [] let sortWith comparer source = - checkNonNull "source" source - mkDelayedSeq (fun () -> - let array = source |> toArray - Array.stableSortInPlaceWith comparer array - array :> seq<_>) + IConsumableSeq.sortWith comparer (toIConsumableSeq source) :> seq<_> [] let inline sortByDescending projection source = - checkNonNull "source" source - let inline compareDescending a b = compare (projection b) (projection a) - sortWith compareDescending source + IConsumableSeq.sortByDescending projection (toIConsumableSeq source) :> seq<_> [] let inline sortDescending source = - checkNonNull "source" source - let inline compareDescending a b = compare b a - sortWith compareDescending source - - let inline countByImpl (comparer:IEqualityComparer<'SafeKey>) (keyf:'T->'SafeKey) (getKey:'SafeKey->'Key) (source:seq<'T>) = - checkNonNull "source" source - - let dict = Dictionary comparer - - // Build the groupings - source |> iter (fun v -> - let safeKey = keyf v - let mutable prev = Unchecked.defaultof<_> - if dict.TryGetValue(safeKey, &prev) - then dict.[safeKey] <- prev + 1 - else dict.[safeKey] <- 1) - - dict |> map (fun group -> (getKey group.Key, group.Value)) - - // We avoid wrapping a StructBox, because under 64 JIT we get some "hard" tailcalls which affect performance - let countByValueType (keyf:'T->'Key) (seq:seq<'T>) = seq |> countByImpl HashIdentity.Structural<'Key> keyf id - - // Wrap a StructBox around all keys in case the key type is itself a type using null as a representation - let countByRefType (keyf:'T->'Key) (seq:seq<'T>) = seq |> countByImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun t -> RuntimeHelpers.StructBox (keyf t)) (fun sb -> sb.Value) + IConsumableSeq.sortDescending (toIConsumableSeq source) :> seq<_> [] let countBy (projection:'T->'Key) (source:seq<'T>) = - checkNonNull "source" source - #if FX_RESHAPED_REFLECTION if (typeof<'Key>).GetTypeInfo().IsValueType #else if typeof<'Key>.IsValueType #endif - then mkDelayedSeq (fun () -> countByValueType projection source) - else mkDelayedSeq (fun () -> countByRefType projection source) + then IConsumableSeq.CountBy.byVal projection (toIConsumableSeq source) :> seq<_> + else IConsumableSeq.CountBy.byRef projection (toIConsumableSeq source) :> seq<_> [] let inline sum (source: seq< ^a>) : ^a = - use e = source.GetEnumerator() - let mutable acc = LanguagePrimitives.GenericZero< ^a> - while e.MoveNext() do - acc <- Checked.(+) acc e.Current - acc + IConsumableSeq.sum (toIConsumableSeq source) [] - let inline sumBy (projection : 'T -> ^U) (source: seq<'T>) : ^U = - use e = source.GetEnumerator() - let mutable acc = LanguagePrimitives.GenericZero< ^U> - while e.MoveNext() do - acc <- Checked.(+) acc (projection e.Current) - acc + let inline sumBy (projection:'T-> ^U) (source:seq<'T>) : ^U = + IConsumableSeq.sumBy projection (toIConsumableSeq source) [] - let inline average (source: seq< ^a>) : ^a = - checkNonNull "source" source - use e = source.GetEnumerator() - let mutable acc = LanguagePrimitives.GenericZero< ^a> - let mutable count = 0 - while e.MoveNext() do - acc <- Checked.(+) acc e.Current - count <- count + 1 - if count = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - LanguagePrimitives.DivideByInt< ^a> acc count + let inline average (source:seq< ^a>) : ^a = + IConsumableSeq.average (toIConsumableSeq source) [] - let inline averageBy (projection : 'T -> ^U) (source: seq< 'T >) : ^U = - checkNonNull "source" source - use e = source.GetEnumerator() - let mutable acc = LanguagePrimitives.GenericZero< ^U> - let mutable count = 0 - while e.MoveNext() do - acc <- Checked.(+) acc (projection e.Current) - count <- count + 1 - if count = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - LanguagePrimitives.DivideByInt< ^U> acc count + let inline averageBy (projection:'T-> ^U) (source:seq<'T>) : ^U = + IConsumableSeq.averageBy projection (toIConsumableSeq source) [] - let inline min (source: seq<_>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let mutable acc = e.Current - while e.MoveNext() do - let curr = e.Current - if curr < acc then - acc <- curr - acc + let inline min (source:seq<_>) = + IConsumableSeq.min (toIConsumableSeq source) [] - let inline minBy (projection : 'T -> 'U) (source: seq<'T>) : 'T = - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let first = e.Current - let mutable acc = projection first - let mutable accv = first - while e.MoveNext() do - let currv = e.Current - let curr = projection currv - if curr < acc then - acc <- curr - accv <- currv - accv - -(* - [] - let inline minValBy (f : 'T -> 'U) (source: seq<'T>) : 'U = - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" InputSequenceEmptyString - let first = e.Current - let mutable acc = f first - while e.MoveNext() do - let currv = e.Current - let curr = f currv - if curr < acc then - acc <- curr - acc - -*) + let inline minBy (projection:'T->'U) (source:seq<'T>) : 'T = + IConsumableSeq.minBy projection (toIConsumableSeq source) + [] let inline max (source: seq<_>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let mutable acc = e.Current - while e.MoveNext() do - let curr = e.Current - if curr > acc then - acc <- curr - acc + IConsumableSeq.max (toIConsumableSeq source) [] - let inline maxBy (projection : 'T -> 'U) (source: seq<'T>) : 'T = - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let first = e.Current - let mutable acc = projection first - let mutable accv = first - while e.MoveNext() do - let currv = e.Current - let curr = projection currv - if curr > acc then - acc <- curr - accv <- currv - accv - - -(* - [] - let inline maxValBy (f : 'T -> 'U) (source: seq<'T>) : 'U = - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" InputSequenceEmptyString - let first = e.Current - let mutable acc = f first - while e.MoveNext() do - let currv = e.Current - let curr = f currv - if curr > acc then - acc <- curr - acc - -*) + let inline maxBy (projection:'T->'U) (source:seq<'T>) : 'T = + IConsumableSeq.maxBy projection (toIConsumableSeq source) + [] let takeWhile predicate (source: seq<_>) = - checkNonNull "source" source - seq { use e = source.GetEnumerator() - let latest = ref Unchecked.defaultof<_> - while e.MoveNext() && (latest := e.Current; predicate !latest) do - yield !latest } + IConsumableSeq.takeWhile predicate (toIConsumableSeq source) :> seq<_> [] let skip count (source: seq<_>) = - checkNonNull "source" source - seq { use e = source.GetEnumerator() - for x in 1 .. count do - if not (e.MoveNext()) then - invalidOpFmt "tried to skip {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - while e.MoveNext() do - yield e.Current } + IConsumableSeq.skip count (toIConsumableSeq source) :> seq<_> [] let skipWhile predicate (source: seq<_>) = - checkNonNull "source" source - seq { use e = source.GetEnumerator() - let latest = ref (Unchecked.defaultof<_>) - let ok = ref false - while e.MoveNext() do - if (latest := e.Current; (!ok || not (predicate !latest))) then - ok := true - yield !latest } + IConsumableSeq.skipWhile predicate (toIConsumableSeq source) :> seq<_> [] - let forall2 predicate (source1: seq<_>) (source2: seq<_>) = - checkNonNull "source1" source1 - checkNonNull "source2" source2 - use e1 = source1.GetEnumerator() - use e2 = source2.GetEnumerator() - let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(predicate) - let mutable ok = true - while (ok && e1.MoveNext() && e2.MoveNext()) do - ok <- p.Invoke(e1.Current, e2.Current) - ok + let forall2 predicate (source1:seq<_>) (source2:seq<_>) = + let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt predicate + IConsumableSeq.forall2 (fun a b -> p.Invoke(a,b)) (source1 |> toIConsumableSeq1) (source2 |> toIConsumableSeq2) [] - let exists2 predicate (source1: seq<_>) (source2: seq<_>) = - checkNonNull "source1" source1 - checkNonNull "source2" source2 - use e1 = source1.GetEnumerator() - use e2 = source2.GetEnumerator() - let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(predicate) - let mutable ok = false - while (not ok && e1.MoveNext() && e2.MoveNext()) do - ok <- p.Invoke(e1.Current, e2.Current) - ok + let exists2 predicate (source1:seq<_>) (source2:seq<_>) = + let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt predicate + IConsumableSeq.exists2 (fun a b -> p.Invoke(a,b)) (source1 |> toIConsumableSeq1) (source2 |> toIConsumableSeq2) [] let head (source : seq<_>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if (e.MoveNext()) then e.Current - else invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.head arr + | :? list<'T> as lst -> List.head lst + | raw -> IConsumableSeq.head (rawOrOriginal raw original) [] let tryHead (source : seq<_>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if (e.MoveNext()) then Some e.Current - else None + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.tryHead arr + | :? list<'T> as lst -> List.tryHead lst + | raw -> IConsumableSeq.tryHead (rawOrOriginal raw original) [] let tail (source: seq<'T>) = - checkNonNull "source" source - seq { use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" (SR.GetString(SR.notEnoughElements)) - while e.MoveNext() do - yield e.Current } + IConsumableSeq.tail (toIConsumableSeq source) :> seq<_> [] let last (source : seq<_>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if e.MoveNext() then - let mutable res = e.Current - while (e.MoveNext()) do res <- e.Current - res - else - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.last arr + | :? list<'T> as lst -> List.last lst + | raw -> IConsumableSeq.last (rawOrOriginal raw original) [] let tryLast (source : seq<_>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if e.MoveNext() then - let mutable res = e.Current - while (e.MoveNext()) do res <- e.Current - Some res - else - None + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.tryLast arr + | :? list<'T> as lst -> List.tryLast lst + | raw -> IConsumableSeq.tryLast (rawOrOriginal raw original) [] let exactlyOne (source : seq<_>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if e.MoveNext() then - let v = e.Current - if e.MoveNext() then - invalidArg "source" (SR.GetString(SR.inputSequenceTooLong)) - else - v - else - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.exactlyOne arr + | :? list<'T> as lst -> List.exactlyOne lst + | raw -> IConsumableSeq.exactlyOne (rawOrOriginal raw original) [] let rev source = - checkNonNull "source" source - mkDelayedSeq (fun () -> - let array = source |> toArray - Array.Reverse array - array :> seq<_>) + IConsumableSeq.delay (fun () -> + let original = toIConsumableSeq source + match getRaw original with + | :? array<'T> as arr -> Array.rev arr |> IConsumableSeq.ofArray + | :? list<'T> as lst -> List.rev lst :> _ + | raw -> IConsumableSeq.rev (rawOrOriginal raw original)) :> seq<_> [] let permute indexMap (source : seq<_>) = - checkNonNull "source" source - mkDelayedSeq (fun () -> - source |> toArray |> Array.permute indexMap :> seq<_>) + IConsumableSeq.permute indexMap (toIConsumableSeq source) :> seq<_> [] - let mapFold<'T,'State,'Result> (mapping: 'State -> 'T -> 'Result * 'State) state source = - checkNonNull "source" source - let arr,state = source |> toArray |> Array.mapFold mapping state - readonly arr, state + let mapFold<'T,'State,'Result> (mapping:'State->'T->'Result*'State) state source = + IConsumableSeq.mapFold mapping state (toIConsumableSeq source) |> fun (iseq, state) -> iseq :> seq<_>, state [] - let mapFoldBack<'T,'State,'Result> (mapping: 'T -> 'State -> 'Result * 'State) source state = - checkNonNull "source" source - let array = source |> toArray - let arr,state = Array.mapFoldBack mapping array state - readonly arr, state + let mapFoldBack<'T,'State,'Result> (mapping:'T->'State->'Result*'State) source state = + IConsumableSeq.mapFoldBack mapping (toIConsumableSeq source) state |> fun (iseq, state) -> iseq :> seq<_>, state [] let except (itemsToExclude: seq<'T>) (source: seq<'T>) = - checkNonNull "itemsToExclude" itemsToExclude - checkNonNull "source" source - - seq { - use e = source.GetEnumerator() - if e.MoveNext() then - let cached = HashSet(itemsToExclude, HashIdentity.Structural) - let next = e.Current - if (cached.Add next) then yield next - while e.MoveNext() do - let next = e.Current - if (cached.Add next) then yield next } + IConsumableSeq.except itemsToExclude (toIConsumableSeq source) :> seq<_> [] let chunkBySize chunkSize (source : seq<_>) = - checkNonNull "source" source - if chunkSize <= 0 then invalidArgFmt "chunkSize" "{0}\nchunkSize = {1}" - [|SR.GetString SR.inputMustBePositive; chunkSize|] - seq { use e = source.GetEnumerator() - let nextChunk() = - let res = Array.zeroCreateUnchecked chunkSize - res.[0] <- e.Current - let i = ref 1 - while !i < chunkSize && e.MoveNext() do - res.[!i] <- e.Current - i := !i + 1 - if !i = chunkSize then - res - else - res |> Array.subUnchecked 0 !i - while e.MoveNext() do - yield nextChunk() } + IConsumableSeq.chunkBySize chunkSize (toIConsumableSeq source) :> seq<_> [] let splitInto count source = - checkNonNull "source" source - if count <= 0 then invalidArgFmt "count" "{0}\ncount = {1}" - [|SR.GetString SR.inputMustBePositive; count|] - mkDelayedSeq (fun () -> - source |> toArray |> Array.splitInto count :> seq<_>) + IConsumableSeq.splitInto count (toIConsumableSeq source) :> seq<_> \ No newline at end of file diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index 71bfc1601ca..70d502ea6db 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -56,13 +56,6 @@ namespace Microsoft.FSharp.Collections let Empty<'T> () = (new EmptyEnumerator<'T>() :> IEnumerator<'T>) - [] - type EmptyEnumerable<'T> = - | EmptyEnumerable - interface IEnumerable<'T> with - member x.GetEnumerator() = Empty<'T>() - interface IEnumerable with - member x.GetEnumerator() = (Empty<'T>() :> IEnumerator) let readAndClear r = lock r (fun () -> match !r with None -> None | Some _ as res -> r := None; res) @@ -135,6 +128,820 @@ namespace Microsoft.FSharp.Collections interface IEnumerable with member x.GetEnumerator() = (f() :> IEnumerator) } +namespace Microsoft.FSharp.Collections.SeqComposition + open System + open System.Collections + open System.Collections.Generic + open System.Runtime.InteropServices + open Microsoft.FSharp.Core + open Microsoft.FSharp.Collections + open Microsoft.FSharp.Collections.IEnumerator + open Microsoft.FSharp.Collections.SeqComposition + open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators + open Microsoft.FSharp.Primitives.Basics + open Microsoft.FSharp.Control + + module Core = + [] + type NoValue = struct end + + module internal TailCall = + // used for performance reasons; these are not recursive calls, so should be safe + // ** it should be noted that potential changes to the f# compiler may render this function + // ineffictive ** + let inline avoid boolean = match boolean with true -> true | false -> false + + module internal Closure = + // F# inlines simple functions, which can mean that it some case you keep creating closures when + // a single function object would have done. This forces the compiler to create the object + let inline forceCapture<'a,'b> (f:'a->'b) : 'a->'b = (# "" f : 'a->'b #) + + type IdentityTransform<'T> private () = + static let singleton : ISeqTransform<'T,'T> = upcast (IdentityTransform<'T>()) + static member Instance = singleton + interface ISeqTransform<'T,'T> with + member __.Compose<'V> (_outOfBand:ISeqConsumer) (_pipeIdx:PipeIdx) (next:SeqConsumerActivity<'T,'V>) : SeqConsumerActivity<'T,'V> = next + + type CompositionTransform<'T,'U,'V> private (first:ISeqTransform<'T,'U>, second:ISeqTransform<'U,'V>) = + interface ISeqTransform<'T,'V> with + member this.Compose<'W> (outOfBand:ISeqConsumer) (pipeIdx:PipeIdx) (next:SeqConsumerActivity<'V,'W>) : SeqConsumerActivity<'T,'W> = + first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) + + static member Combine (first:ISeqTransform<'T,'U>) (second:ISeqTransform<'U,'V>) : ISeqTransform<'T,'V> = + upcast CompositionTransform(first, second) + + type ISkipable = + // Seq.init(Infinite)? lazily uses Current. The only IConsumableSeq component that can do that is Skip + // and it can only do it at the start of a sequence + abstract CanSkip : unit -> bool + + type SeqProcessNextStates = + | InProcess = 0 + | NotStarted = 1 + | Finished = 2 + + type EmptyEnumerator<'T>() = + let current () = failwith "library implementation error: Current should never be called" + + interface IEnumerator<'T> with + member __.Current = current () + + interface IEnumerator with + member __.Current = current () + member __.MoveNext () = false + member __.Reset (): unit = noReset () + + interface IDisposable with + member __.Dispose () = () + + type EmptyEnumerators<'T>() = + static let element : IEnumerator<'T> = upcast (new EmptyEnumerator<'T> ()) + static member Element = element + + [] + type EnumerableBase<'T> () = + let derivedClassShouldImplement () = + failwith "library implementation error: derived class should implement (should be abstract)" + + abstract member Append : IConsumableSeq<'T> -> IConsumableSeq<'T> + abstract member Length : unit -> int + abstract member GetRaw : unit -> seq<'T> + + default this.Append source = upcast (AppendEnumerable [source; this]) + default this.Length () = Microsoft.FSharp.Primitives.Basics.IConsumableSeq.length this + default this.GetRaw () = upcast this + + interface IEnumerable with + member this.GetEnumerator () : IEnumerator = + upcast ((this:>IEnumerable<'T>).GetEnumerator ()) + + interface IEnumerable<'T> with + // fsharp doesn't allow abstract interface methods + member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () + + interface IConsumableSeq<'T> with + // fsharp doesn't allow abstract interface methods + member __.Transform _ = derivedClassShouldImplement () + member __.Consume _ = derivedClassShouldImplement () + + and [] EnumerableWithTransform<'T,'U>(transform:ISeqTransform<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() + + member __.CreateActivityPipeline<'Result> (consumer:SeqConsumer<'U,'Result>) : SeqConsumerActivity<'T,'U> = + transform.Compose (consumer :> ISeqConsumer) pipeIdx consumer + + member this.CreatePipeline<'Result> (getConsumer:PipeIdx -> SeqConsumer<'U,'Result>, [] activity:byref>) = + let consumer = getConsumer (pipeIdx+1) + activity <- this.CreateActivityPipeline consumer + consumer + + member __.ComposeWith next = CompositionTransform.Combine transform next + + member __.PipeIdx = pipeIdx + + and [] EnumeratorBase<'T>() = + inherit SeqConsumer<'T,'T>(Unchecked.defaultof<'T>) + + member val SeqState = SeqProcessNextStates.NotStarted with get, set + abstract Activity : SeqConsumerActivity + + override this.ProcessNext (input:'T) : bool = + this.Result <- input + true + + interface IDisposable with + member this.Dispose () : unit = + this.Activity.ChainDispose () + + interface IEnumerator with + member this.Current : obj = box (this :> IEnumerator<'T>).Current + member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)" + member __.Reset () : unit = noReset () + + interface IEnumerator<'T> with + member this.Current = + if this.SeqState = SeqProcessNextStates.InProcess then this.Result + else + match this.SeqState with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> failwith "library implementation error: all states should have been handled" + + and VanillaEnumerator<'T,'U> private (source:IEnumerator<'T>) = + inherit EnumeratorBase<'U>() + + let mutable activity = Unchecked.defaultof> + + member private __.FinaliseConstruct(actualActivity: SeqConsumerActivity<'T,'U>) = + activity <- actualActivity + + override __.Activity = upcast activity + + member private this.MoveNext () = + if this.HaltedIdx = 0 && source.MoveNext () then + if activity.ProcessNext source.Current then + true + else + this.MoveNext () + else + this.SeqState <- SeqProcessNextStates.Finished + activity.ChainComplete this.HaltedIdx + false + + interface IEnumerator with + member this.MoveNext () = + this.SeqState <- SeqProcessNextStates.InProcess + this.MoveNext () + + interface IDisposable with + member __.Dispose () = + try + source.Dispose () + finally + activity.ChainDispose () + + static member Create (source:IEnumerator<'T>) (factory:EnumerableWithTransform<'T,'U>) : IEnumerator<'U> = + let enumerator = new VanillaEnumerator<'T,'U>(source) + enumerator.FinaliseConstruct (factory.CreateActivityPipeline enumerator) + upcast enumerator + + and VanillaEnumerable<'T,'U>(enumerable:IEnumerable<'T>, transform:ISeqTransform<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableWithTransform<'T,'U>(transform, pipeIdx) + + interface IEnumerable<'U> with + member this.GetEnumerator () = VanillaEnumerator<'T,'U>.Create (enumerable.GetEnumerator()) this + + interface IConsumableSeq<'U> with + member this.Transform (next:ISeqTransform<'U,'V>) : IConsumableSeq<'V> = + upcast (new VanillaEnumerable<'T,'V>(enumerable, this.ComposeWith next, this.PipeIdx+1)) + + member this.Consume<'Result> (getConsumer:PipeIdx->SeqConsumer<'U,'Result>) = + let result, consumer = this.CreatePipeline getConsumer + try + use enumerator = enumerable.GetEnumerator () + while result.HaltedIdx = 0 && enumerator.MoveNext () do + consumer.ProcessNext enumerator.Current |> ignore + + consumer.ChainComplete result.HaltedIdx + finally + consumer.ChainDispose () + result.Result + + and ConcatCommon<'T>(consumer:SeqConsumerActivity<'T>) = + inherit SeqConsumer<'T,NoValue>(Unchecked.defaultof<_>) + + member __.Consumer = consumer + + override me.ProcessNext value = TailCall.avoid (consumer.ProcessNext value) + + and ConcatFold<'T,'U,'Collection,'Result when 'Collection :> IConsumableSeq<'T>>(result:SeqConsumer<'U,'Result>, consumer:SeqConsumerActivity<'T,'U>, common:SeqConsumer<'T,NoValue>) as this = + inherit SeqConsumer<'Collection, 'Result>(Unchecked.defaultof<_>) + + do + (this :> ISeqConsumer).ListenForStopFurtherProcessing (fun idx -> + (result :> ISeqConsumer).StopFurtherProcessing idx + (common :> ISeqConsumer).StopFurtherProcessing PipeIdx.MinValue) + + (result :> ISeqConsumer).ListenForStopFurtherProcessing (fun idx -> + (this :> ISeqConsumer).StopFurtherProcessing idx + (common :> ISeqConsumer).StopFurtherProcessing PipeIdx.MaxValue) + + let getCommonFolder = Closure.forceCapture (fun (_:PipeIdx) -> + (common :> ISeqConsumer).StopFurtherProcessing 0 + common) + + override __.ProcessNext value = + value.Consume getCommonFolder |> ignore + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.ChainComplete _ = + consumer.ChainComplete result.HaltedIdx + this.Result <- result.Result + + override this.ChainDispose () = + consumer.ChainDispose () + + and ConcatEnumerator<'T,'U,'Collection when 'Collection :> IEnumerable<'T>> private (sources:IEnumerable<'Collection>) = + inherit EnumeratorBase<'U>() + + let main = sources.GetEnumerator () + let mutable active = EmptyEnumerators.Element + let mutable activity = Unchecked.defaultof> + + override __.Activity = upcast activity + + member private __.FinaliseConstruct(actualActivity: SeqConsumerActivity<'T,'U>) = + activity <- actualActivity + + member private this.MoveNext () = + if this.HaltedIdx <> 0 then false + else + if active.MoveNext () then + if activity.ProcessNext active.Current then + true + else + this.MoveNext () + elif main.MoveNext () then + active.Dispose () + active <- main.Current.GetEnumerator () + this.MoveNext () + else + this.SeqState <- SeqProcessNextStates.Finished + activity.ChainComplete this.HaltedIdx + false + + interface IEnumerator with + member this.MoveNext () = + this.SeqState <- SeqProcessNextStates.InProcess + this.MoveNext () + + interface IDisposable with + member __.Dispose () = + try + main.Dispose () + active.Dispose () + finally + activity.ChainDispose () + + static member Create (sources:IEnumerable<'Collection>) (factory:EnumerableWithTransform<'T,'U>) : IEnumerator<'U> = + let enumerator = new ConcatEnumerator<'T,'U,'Collection>(sources) + enumerator.FinaliseConstruct (factory.CreateActivityPipeline enumerator) + upcast enumerator + + and ConcatEnumerable<'T,'U,'Collection when 'Collection :> IConsumableSeq<'T>> (sources:IConsumableSeq<'Collection>, transform:ISeqTransform<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableWithTransform<'T,'U>(transform, pipeIdx) + + interface IEnumerable<'U> with + member this.GetEnumerator () = ConcatEnumerator<'T,'U,'Collection>.Create sources this + + interface IConsumableSeq<'U> with + member this.Transform (next:ISeqTransform<'U,'V>) : IConsumableSeq<'V> = + upcast (new ConcatEnumerable<'T,'V,'Collection>(sources, this.ComposeWith next, this.PipeIdx+1)) + + member this.Consume<'Result> (getConsumer:PipeIdx->SeqConsumer<'U,'Result>) = + sources.Consume (fun lowerPipeIdx -> + let thisPipeIdx = lowerPipeIdx + pipeIdx + + let result = getConsumer (thisPipeIdx+1) + + let outOfBand = result :> ISeqConsumer + + let consumer = transform.Compose outOfBand thisPipeIdx result + + let common = + match box consumer with + | :? ConcatCommon<'T> as c -> ConcatCommon c.Consumer + | _ -> ConcatCommon consumer + + upcast ConcatFold (result, consumer, common)) + + and ThinConcatEnumerable<'T, 'Sources, 'Collection when 'Collection :> IConsumableSeq<'T>> (sources:'Sources, preEnumerate:'Sources->IConsumableSeq<'Collection>) = + inherit EnumerableBase<'T>() + + member private __.Fatten : IConsumableSeq<'T> = upcast (ConcatEnumerable<'T,'T,'Collection>(preEnumerate sources, IdentityTransform.Instance, 1)) + + interface IEnumerable<'T> with + member this.GetEnumerator () = this.Fatten.GetEnumerator () + + interface IConsumableSeq<'T> with + member this.Transform (next:ISeqTransform<'T,'U>) : IConsumableSeq<'U> = + upcast (ConcatEnumerable<'T,'V,'Collection>(preEnumerate sources, next, 1)) + + member this.Consume<'Result> (getConsumer:PipeIdx->SeqConsumer<'T,'Result>) = + this.Fatten.Consume getConsumer + + and AppendEnumerable<'T> (sources:list>) = + inherit ThinConcatEnumerable<'T, list>, IConsumableSeq<'T>>(sources, fun sources -> upcast (List.rev sources)) + + override this.Append source = + upcast (AppendEnumerable (source::sources)) + + /// ThinEnumerable is used when the IEnumerable provided to ofSeq is neither an array or a list + type ThinEnumerable<'T>(enumerable:IEnumerable<'T>) = + inherit VanillaEnumerable<'T,'T>(enumerable, IdentityTransform.Instance, 0) + + override __.Length () = + match enumerable with + | :? ICollection<'T> as a -> a.Count + | :? IReadOnlyCollection<'T> as a -> a.Count + | _ -> + use e = enumerable.GetEnumerator () + let mutable count = 0 + while e.MoveNext () do + count <- count + 1 + count + + override __.GetRaw () = enumerable + + interface IEnumerable<'T> with + member __.GetEnumerator () = enumerable.GetEnumerator () + + type DelayedEnumerable<'T>(delayed:unit->IConsumableSeq<'T>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'T>() + + override __.Length () = + match delayed() with + | :? EnumerableBase<'T> as s -> s.Length () + | s -> Microsoft.FSharp.Primitives.Basics.IConsumableSeq.length s + + override __.GetRaw () = + match delayed() with + | :? EnumerableBase<'T> as s -> s.GetRaw () + | s -> upcast s + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = (delayed()).GetEnumerator () + + interface IConsumableSeq<'T> with + member __.Transform (next:ISeqTransform<'T,'U>) : IConsumableSeq<'U> = + upcast (new DelayedEnumerable<'U>((fun () -> (delayed()).Transform next), pipeIdx+1)) + + member __.Consume<'Result> (f:PipeIdx->SeqConsumer<'T,'Result>) = + (delayed()).Consume f + + type EmptyEnumerable<'T> private () = + inherit EnumerableBase<'T>() + + static let singleton = EmptyEnumerable<'T>() :> IConsumableSeq<'T> + static member Instance = singleton + + override __.Length () = 0 + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = IEnumerator.Empty<'T>() + + override this.Append source = source + + interface IConsumableSeq<'T> with + member this.Transform (next:ISeqTransform<'T,'U>) : IConsumableSeq<'U> = + upcast (VanillaEnumerable<'T,'V>(this, next, 1)) + + member this.Consume<'Result> (getConsumer:PipeIdx->SeqConsumer<'T,'Result>) = + let result = getConsumer 1 + try + result.ChainComplete result.HaltedIdx + finally + result.ChainDispose () + result.Result + + type ArrayEnumerator<'T,'U> private (array:array<'T>) = + inherit EnumeratorBase<'U>() + + let mutable idx = 0 + let mutable activity = Unchecked.defaultof> + + member private __.FinaliseConstruct(actualActivity: SeqConsumerActivity<'T,'U>) = + activity <- actualActivity + + override __.Activity = upcast activity + + member private this.MoveNext () = + if this.HaltedIdx = 0 && idx < array.Length then + idx <- idx+1 + if activity.ProcessNext array.[idx-1] then + true + else + this.MoveNext () + else + this.SeqState <- SeqProcessNextStates.Finished + activity.ChainComplete this.HaltedIdx + false + + interface IEnumerator with + member this.MoveNext () = + this.SeqState <- SeqProcessNextStates.InProcess + this.MoveNext () + + static member Create (array:array<'T>) (factory:EnumerableWithTransform<'T,'U>) : IEnumerator<'U> = + let enumerator = new ArrayEnumerator<'T,'U>(array) + enumerator.FinaliseConstruct (factory.CreateActivityPipeline enumerator) + upcast enumerator + + type ArrayEnumerable<'T,'U>(array:array<'T>, transform:ISeqTransform<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableWithTransform<'T,'U>(transform, pipeIdx) + + interface IEnumerable<'U> with + member this.GetEnumerator () = ArrayEnumerator<'T,'U>.Create array this + + interface IConsumableSeq<'U> with + member this.Transform (next:ISeqTransform<'U,'V>) : IConsumableSeq<'V> = + upcast (new ArrayEnumerable<'T,'V>(array, this.ComposeWith next, this.PipeIdx+1)) + + member this.Consume<'Result> (getConsumer:PipeIdx->SeqConsumer<'U,'Result>) = + let result, consumer = this.CreatePipeline getConsumer + try + let array = array + let mutable idx = 0 + while result.HaltedIdx = 0 && idx < array.Length do + consumer.ProcessNext array.[idx] |> ignore + idx <- idx + 1 + + consumer.ChainComplete result.HaltedIdx + finally + consumer.ChainDispose () + result.Result + + type ThinArrayEnumerable<'T>(array:array<'T>) = + inherit ArrayEnumerable<'T,'T>(array, IdentityTransform.Instance, 0) + + override __.Length () = array.Length + override __.GetRaw () = upcast array + + interface IEnumerable<'T> with + member __.GetEnumerator () = (array:>IEnumerable<'T>).GetEnumerator () + + type SingletonEnumerable<'T>(item:'T) = + inherit EnumerableBase<'T>() + + override __.Length () = 1 + + interface IEnumerable<'T> with + member this.GetEnumerator () = (new Singleton<'T>(item)) :> IEnumerator<'T> + + interface IConsumableSeq<'T> with + member __.Transform (next:ISeqTransform<'T,'U>) : IConsumableSeq<'U> = + ([item] :> IConsumableSeq<'T>).Transform next + + member this.Consume<'Result> (getConsumer:PipeIdx->SeqConsumer<'T,'Result>) = + let result = getConsumer 1 + try + if result.HaltedIdx = 0 then + result.ProcessNext item |> ignore + + result.ChainComplete result.HaltedIdx + finally + result.ChainDispose () + result.Result + + type ResizeArrayEnumerator<'T,'U> private (array:ResizeArray<'T>) = + inherit EnumeratorBase<'U>() + + let mutable idx = 0 + let mutable activity = Unchecked.defaultof> + + member private __.FinaliseConstruct(actualActivity: SeqConsumerActivity<'T,'U>) = + activity <- actualActivity + + override __.Activity = upcast activity + + member private this.MoveNext () = + if this.HaltedIdx = 0 && idx < array.Count then + idx <- idx+1 + if activity.ProcessNext array.[idx-1] then + true + else + this.MoveNext () + else + this.SeqState <- SeqProcessNextStates.Finished + activity.ChainComplete this.HaltedIdx + false + + interface IEnumerator with + member this.MoveNext () = + this.SeqState <- SeqProcessNextStates.InProcess + this.MoveNext () + + static member Create (array:ResizeArray<'T>) (factory:EnumerableWithTransform<'T,'U>) : IEnumerator<'U> = + let enumerator = new ResizeArrayEnumerator<'T,'U>(array) + enumerator.FinaliseConstruct (factory.CreateActivityPipeline enumerator) + upcast enumerator + + type ResizeArrayEnumerable<'T,'U>(resizeArray:ResizeArray<'T>, transform:ISeqTransform<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableWithTransform<'T,'U>(transform, pipeIdx) + + interface IEnumerable<'U> with + member this.GetEnumerator () = ResizeArrayEnumerator<'T,'U>.Create resizeArray this + + interface IConsumableSeq<'U> with + member this.Transform (next:ISeqTransform<'U,'V>) : IConsumableSeq<'V> = + upcast (new ResizeArrayEnumerable<'T,'V>(resizeArray, this.ComposeWith next, this.PipeIdx+1)) + + member this.Consume<'Result> (getConsumer:PipeIdx->SeqConsumer<'U,'Result>) = + let result, consumer = this.CreatePipeline getConsumer + try + let array = resizeArray + let mutable idx = 0 + while result.HaltedIdx = 0 && idx < array.Count do + consumer.ProcessNext array.[idx] |> ignore + idx <- idx + 1 + + consumer.ChainComplete result.HaltedIdx + finally + consumer.ChainDispose () + result.Result + + type ThinResizeArrayEnumerable<'T>(resizeArray:ResizeArray<'T>) = + inherit ResizeArrayEnumerable<'T,'T>(resizeArray, IdentityTransform.Instance, 0) + + override __.Length () = resizeArray.Count + + type UnfoldEnumerator<'T,'U,'State> private (generator:'State->option<'T*'State>, state:'State) = + inherit EnumeratorBase<'U>() + + let mutable current = state + + let mutable activity = Unchecked.defaultof> + + member private __.FinaliseConstruct(actualActivity: SeqConsumerActivity<'T,'U>) = + activity <- actualActivity + + override __.Activity = upcast activity + + member private this.MoveNext () = + if this.HaltedIdx <> 0 then + false + else + match generator current with + | Some (item, nextState) -> + current <- nextState + if activity.ProcessNext item then + true + else + this.MoveNext () + | _ -> false + + interface IEnumerator with + member this.MoveNext () = + this.SeqState <- SeqProcessNextStates.InProcess + this.MoveNext () + + static member Create (generator:'State->option<'T*'State>) (state:'State) (factory:EnumerableWithTransform<'T,'U>) : IEnumerator<'U> = + let enumerator = new UnfoldEnumerator<'T,'U,'State>(generator, state) + enumerator.FinaliseConstruct (factory.CreateActivityPipeline enumerator) + upcast enumerator + + type UnfoldEnumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, transform:ISeqTransform<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableWithTransform<'T,'U>(transform, pipeIdx) + + interface IEnumerable<'U> with + member this.GetEnumerator () = UnfoldEnumerator<'T,'U,'GeneratorState>.Create generator state this + + interface IConsumableSeq<'U> with + member this.Transform (next:ISeqTransform<'U,'V>) : IConsumableSeq<'V> = + upcast (new UnfoldEnumerable<'T,'V,'GeneratorState>(generator, state, this.ComposeWith next, this.PipeIdx+1)) + + member this.Consume<'Result> (getConsumer:PipeIdx->SeqConsumer<'U,'Result>) = + let result, consumer = this.CreatePipeline getConsumer + try + let generator = generator + let rec iterate current = + if result.HaltedIdx <> 0 then () + else + match generator current with + | Some (item, next) -> + consumer.ProcessNext item |> ignore + iterate next + | _ -> () + iterate state + + consumer.ChainComplete result.HaltedIdx + finally + consumer.ChainDispose () + result.Result + + let getInitTerminatingIdx (count:Nullable) = + // we are offset by 1 to allow for values going up to System.Int32.MaxValue + // System.Int32.MaxValue is an illegal value for the "infinite" sequence + if count.HasValue then + count.Value - 1 + else + System.Int32.MaxValue + + type InitEnumerator<'T,'U>(count:Nullable, f:int->'T) = + inherit EnumeratorBase<'U>() + + let terminatingIdx = + getInitTerminatingIdx count + + let mutable maybeSkipping = true + let mutable idx = -1 + + let mutable activity = Unchecked.defaultof> + let mutable isSkipping = Unchecked.defaultofbool> + + member private __.FinaliseConstruct(actualActivity: SeqConsumerActivity<'T,'U>) = + activity <- actualActivity + + isSkipping <- + match box activity with + | :? ISkipable as skip -> skip.CanSkip + | _ -> fun () -> false + + override __.Activity = upcast activity + + member private this.MoveNext () = + if this.HaltedIdx = 0 && idx < terminatingIdx then + idx <- idx + 1 + + if maybeSkipping then + // Skip can only is only checked at the start of the sequence, so once + // triggered, we stay triggered. + maybeSkipping <- isSkipping () + + if maybeSkipping then + this.MoveNext () + elif activity.ProcessNext (f idx) then + true + else + this.MoveNext () + elif this.HaltedIdx = 0 && idx = System.Int32.MaxValue then + raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + else + this.SeqState <- SeqProcessNextStates.Finished + activity.ChainComplete this.HaltedIdx + false + + interface IEnumerator with + member this.MoveNext () = + this.SeqState <- SeqProcessNextStates.InProcess + this.MoveNext () + + static member Create (count:Nullable) (f:int->'T) (factory:EnumerableWithTransform<'T,'U>) : IEnumerator<'U> = + let enumerator = new InitEnumerator<'T,'U>(count, f) + enumerator.FinaliseConstruct (factory.CreateActivityPipeline enumerator) + upcast enumerator + + type InitEnumerable<'T,'U>(count:Nullable, f:int->'T, transform:ISeqTransform<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableWithTransform<'T,'U>(transform, pipeIdx) + + interface IEnumerable<'U> with + member this.GetEnumerator () = InitEnumerator<'T,'U>.Create count f this + + interface IConsumableSeq<'U> with + member this.Transform (next:ISeqTransform<'U,'V>) : IConsumableSeq<'V> = + upcast (new InitEnumerable<'T,'V>(count, f, this.ComposeWith next, this.PipeIdx+1)) + + member this.Consume<'Result> (getConsumer:PipeIdx->SeqConsumer<'U,'Result>) = + let terminatingIdx = getInitTerminatingIdx count + let result, consumer = this.CreatePipeline getConsumer + try + let firstIdx = + match box consumer with + | :? ISkipable as skipping -> + let rec skip idx = + if idx = terminatingIdx || result.HaltedIdx <> 0 then + terminatingIdx + elif skipping.CanSkip () then + skip (idx+1) + else + idx + skip -1 + | _ -> -1 + + let rec iterate idx = + if idx < terminatingIdx then + consumer.ProcessNext (f (idx+1)) |> ignore + if result.HaltedIdx = 0 then + iterate (idx+1) + else + idx + else + idx + + let finalIdx = iterate firstIdx + if result.HaltedIdx = 0 && finalIdx = System.Int32.MaxValue then + raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + + consumer.ChainComplete result.HaltedIdx + finally + consumer.ChainDispose () + result.Result + + // The original implementation of "init" delayed the calculation of Current, and so it was possible + // to do MoveNext without it's value being calculated. + // I can imagine only two scenerios where that is possibly sane, although a simple solution is readily + // at hand in both cases. The first is that of an expensive generator function, where you skip the + // first n elements. The simple solution would have just been to have a map ((+) n) as the first operation + // instead. The second case would be counting elements, but that is only of use if you're not filtering + // or mapping or doing anything else (as that would cause Current to be evaluated!) and + // so you already know what the count is!! Anyway, someone thought it was a good idea, so + // I have had to add an extra function that is used in Skip to determine if we are touching + // Current or not. + // InitEnumerableDecider returns the original implementation of init when GetEnumerator is called + // If any Activites are added to the pipeline then the original implementation is ignored, as special + // handling has been added to Current isn't calculated whilst skipping enumerated items. + type InitEnumerableDecider<'T>(count:Nullable, f:int->'T, pipeIdx:PipeIdx) = + inherit EnumerableBase<'T>() + + let upto lastOption f = + match lastOption with + | Some b when b<0 -> failwith "library implementation error: upto can never be called with a negative value" + | _ -> + let unstarted = -1 // index value means unstarted (and no valid index) + let completed = -2 // index value means completed (and no valid index) + let unreachable = -3 // index is unreachable from 0,1,2,3,... + let finalIndex = match lastOption with + | Some b -> b // here b>=0, a valid end value. + | None -> unreachable // run "forever", well as far as Int32.MaxValue since indexing with a bounded type. + // The Current value for a valid index is "f i". + // Lazy<_> values are used as caches, to store either the result or an exception if thrown. + // These "Lazy<_>" caches are created only on the first call to current and forced immediately. + // The lazy creation of the cache nodes means enumerations that skip many Current values are not delayed by GC. + // For example, the full enumeration of Seq.initInfinite in the tests. + // state + let index = ref unstarted + // a Lazy node to cache the result/exception + let current = ref (Unchecked.defaultof<_>) + let setIndex i = index := i; current := (Unchecked.defaultof<_>) // cache node unprimed, initialised on demand. + let getCurrent() = + if !index = unstarted then notStarted() + if !index = completed then alreadyFinished() + match box !current with + | null -> current := Lazy<_>.Create(fun () -> f !index) + | _ -> () + // forced or re-forced immediately. + (!current).Force() + { new IEnumerator<'U> with + member x.Current = getCurrent() + interface IEnumerator with + member x.Current = box (getCurrent()) + member x.MoveNext() = + if !index = completed then + false + elif !index = unstarted then + setIndex 0 + true + else ( + if !index = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + if !index = finalIndex then + false + else + setIndex (!index + 1) + true + ) + member this.Reset() = noReset() + interface System.IDisposable with + member x.Dispose () = () } + + override this.Length () = + if count.HasValue then + count.Value + else + raise (System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue))) + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = + // we defer back to the original implementation as, as it's quite idiomatic in it's decision + // to calculate Current in a lazy fashion. I doubt anyone is really using this functionality + // in the way presented, but it's possible. + upto (if count.HasValue then Some (count.Value-1) else None) f + + interface IConsumableSeq<'T> with + member this.Transform (next:ISeqTransform<'T,'U>) : IConsumableSeq<'U> = + upcast (InitEnumerable<'T,'V>(count, f, next, pipeIdx+1)) + + member this.Consume<'Result> (getConsumer:PipeIdx->SeqConsumer<'T,'Result>) = + let result = getConsumer 1 + try + use enumerator = (this:>IEnumerable<'T>).GetEnumerator () + while result.HaltedIdx = 0 && enumerator.MoveNext () do + result.ProcessNext enumerator.Current |> ignore + + result.ChainComplete result.HaltedIdx + finally + result.ChainDispose () + result.Result + namespace Microsoft.FSharp.Core.CompilerServices open System @@ -148,18 +955,10 @@ namespace Microsoft.FSharp.Core.CompilerServices open Microsoft.FSharp.Primitives.Basics open System.Collections open System.Collections.Generic + open Microsoft.FSharp.Collections.SeqComposition + open Microsoft.FSharp.Collections.SeqComposition.Core module RuntimeHelpers = - - [] - type internal StructBox<'T when 'T:equality>(value:'T) = - member x.Value = value - static member Comparer = - let gcomparer = HashIdentity.Structural<'T> - { new IEqualityComparer> with - member __.GetHashCode(v) = gcomparer.GetHashCode(v.Value) - member __.Equals(v1,v2) = gcomparer.Equals(v1.Value,v2.Value) } - let Generate openf compute closef = mkSeq (fun () -> IEnumerator.generateWhileSome openf compute closef) @@ -354,47 +1153,68 @@ namespace Microsoft.FSharp.Core.CompilerServices [] type GeneratedSequenceBase<'T>() = + inherit EnumerableBase<'T>() + let mutable redirectTo : GeneratedSequenceBase<'T> = Unchecked.defaultof<_> let mutable redirect : bool = false + member internal x.GetCurrent () = if redirect then redirectTo.LastGenerated else x.LastGenerated + abstract GetFreshEnumerator : unit -> IEnumerator<'T> abstract GenerateNext : result:byref> -> int // 0 = Stop, 1 = Yield, 2 = Goto abstract Close: unit -> unit abstract CheckClose: bool abstract LastGenerated : 'T + static member CreateRedirect e (active:GeneratedSequenceBase<'T>) = + { new GeneratedSequenceBase<'T>() with + member __.GetFreshEnumerator() = e + member __.GenerateNext(_) = if e.MoveNext() then 1 else 0 + member __.Close() = try e.Dispose() finally active.Close() + member __.CheckClose = true + member __.LastGenerated = e.Current } + + static member GetRedirect (target:IEnumerable<'T>) (active:GeneratedSequenceBase<'T>) = + match target.GetEnumerator() with + | :? GeneratedSequenceBase<'T> as g when not active.CheckClose -> g + | e -> GeneratedSequenceBase.CreateRedirect e active + + static member Consume<'U, 'Result> (result:SeqConsumer<'U,'Result>) (consumer:SeqConsumerActivity<'T,'U>) (active:GeneratedSequenceBase<'T>) = + if result.HaltedIdx = 0 then + let mutable target = null + match active.GenerateNext (&target) with + | 1 -> + consumer.ProcessNext active.LastGenerated |> ignore + GeneratedSequenceBase.Consume result consumer active + | 2 -> + GeneratedSequenceBase.Consume result consumer (GeneratedSequenceBase.GetRedirect target active) + | _ (*0*) -> () + + static member Count (active:GeneratedSequenceBase<'T>) count = + let mutable target = null + match active.GenerateNext (&target) with + | 1 -> GeneratedSequenceBase.Count active (count+1) + | 2 -> GeneratedSequenceBase.Count (GeneratedSequenceBase.GetRedirect target active) count + | _ (*0*) -> count + //[] member x.MoveNextImpl() = - let active = - if redirect then redirectTo - else x + let active = if redirect then redirectTo else x let mutable target = null - match active.GenerateNext(&target) with - | 1 -> - true + match active.GenerateNext (&target) with + | 1 -> true | 2 -> - match target.GetEnumerator() with - | :? GeneratedSequenceBase<'T> as g when not active.CheckClose -> - redirectTo <- g - | e -> - redirectTo <- - { new GeneratedSequenceBase<'T>() with - member x.GetFreshEnumerator() = e - member x.GenerateNext(_) = if e.MoveNext() then 1 else 0 - member x.Close() = try e.Dispose() finally active.Close() - member x.CheckClose = true - member x.LastGenerated = e.Current } redirect <- true + redirectTo <- GeneratedSequenceBase.GetRedirect target active x.MoveNextImpl() - | _ (* 0 *) -> - false + | _ (*0*) -> false interface IEnumerable<'T> with member x.GetEnumerator() = x.GetFreshEnumerator() interface IEnumerable with member x.GetEnumerator() = (x.GetFreshEnumerator() :> IEnumerator) interface IEnumerator<'T> with - member x.Current = if redirect then redirectTo.LastGenerated else x.LastGenerated + member x.Current = x.GetCurrent () interface System.IDisposable with member x.Dispose() = if redirect then redirectTo.Close() else x.Close() interface IEnumerator with @@ -404,3 +1224,58 @@ namespace Microsoft.FSharp.Core.CompilerServices member x.MoveNext() = x.MoveNextImpl() member x.Reset() = raise <| new System.NotSupportedException() + + interface IConsumableSeq<'T> with + member this.Transform<'U> (next:ISeqTransform<'T,'U>) : IConsumableSeq<'U> = + upcast (new GeneratedSequenceBaseEnumerable<'T,'U>(this, next, 1)) + + member this.Consume<'Result> (getConsumer:PipeIdx->SeqConsumer<'T,'Result>) = + let result = getConsumer 1 + try + use maybeGeneratedSequenceBase = this.GetFreshEnumerator () + match maybeGeneratedSequenceBase with + | :? GeneratedSequenceBase<'T> as e -> GeneratedSequenceBase.Consume result result e + | e -> + while result.HaltedIdx = 0 && e.MoveNext () do + result.ProcessNext e.Current |> ignore + + result.ChainComplete result.HaltedIdx + finally + result.ChainDispose () + result.Result + + override this.Length () = + use maybeGeneratedSequenceBase = this.GetFreshEnumerator () + match maybeGeneratedSequenceBase with + | :? GeneratedSequenceBase<'T> as e -> GeneratedSequenceBase.Count e 0 + | e -> + let mutable count = 0 + while e.MoveNext () do + count <- count + 1 + count + + and GeneratedSequenceBaseEnumerable<'T,'U>(generatedSequence:GeneratedSequenceBase<'T>, transform:ISeqTransform<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableWithTransform<'T,'U>(transform, pipeIdx) + + interface IEnumerable<'U> with + member this.GetEnumerator () = VanillaEnumerator<'T,'U>.Create (generatedSequence.GetFreshEnumerator()) this + + interface IConsumableSeq<'U> with + member this.Transform (next:ISeqTransform<'U,'V>) : IConsumableSeq<'V> = + upcast (new GeneratedSequenceBaseEnumerable<'T,'V>(generatedSequence, this.ComposeWith next, this.PipeIdx+1)) + + member this.Consume<'Result> (getConsumer:PipeIdx->SeqConsumer<'U,'Result>) = + let result, consumer = this.CreatePipeline getConsumer + try + use maybeGeneratedSequenceBase = generatedSequence.GetFreshEnumerator () + match maybeGeneratedSequenceBase with + | :? GeneratedSequenceBase<'T> as e -> GeneratedSequenceBase.Consume result consumer e + | e -> + while result.HaltedIdx = 0 && e.MoveNext () do + consumer.ProcessNext e.Current |> ignore + + consumer.ChainComplete result.HaltedIdx + finally + consumer.ChainDispose () + result.Result + diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index a1aea443aeb..04a1f810d8a 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -6,54 +6,139 @@ namespace Microsoft.FSharp.Collections open System.Collections.Generic open Microsoft.FSharp.Core open Microsoft.FSharp.Collections + module internal IEnumerator = - val noReset : unit -> 'a - val notStarted : unit -> 'a - val alreadyFinished : unit -> 'a + + val noReset : unit -> 'T + + val notStarted : unit -> 'T + + val alreadyFinished : unit -> 'T + val check : started:bool -> unit + val dispose : r:System.IDisposable -> unit - val cast : - e:System.Collections.IEnumerator -> - System.Collections.Generic.IEnumerator<'T> - [] - type EmptyEnumerator<'T> = - class - interface System.IDisposable - interface System.Collections.IEnumerator - interface System.Collections.Generic.IEnumerator<'T> - new : unit -> EmptyEnumerator<'T> - end + + val cast : e:System.Collections.IEnumerator -> System.Collections.Generic.IEnumerator<'T> + val Empty : unit -> System.Collections.Generic.IEnumerator<'T> - [] - type EmptyEnumerable<'T> = - | EmptyEnumerable - with - interface System.Collections.IEnumerable - interface System.Collections.Generic.IEnumerable<'T> - end - - val readAndClear : r:'a option ref -> 'a option - val generateWhileSome : - openf:(unit -> 'a) -> - compute:('a -> 'U option) -> - closef:('a -> unit) -> System.Collections.Generic.IEnumerator<'U> - [] - type Singleton<'T> = - class - interface System.IDisposable - interface System.Collections.IEnumerator - interface System.Collections.Generic.IEnumerator<'T> - new : v:'T -> Singleton<'T> - end + val Singleton : x:'T -> System.Collections.Generic.IEnumerator<'T> - val EnumerateThenFinally : - f:(unit -> unit) -> - e:System.Collections.Generic.IEnumerator<'T> -> - System.Collections.Generic.IEnumerator<'T> - val inline checkNonNull : argName:string -> arg:'a -> unit - val mkSeq : - f:(unit -> System.Collections.Generic.IEnumerator<'U>) -> - System.Collections.Generic.IEnumerable<'U> + + val EnumerateThenFinally : f:(unit -> unit) -> e:System.Collections.Generic.IEnumerator<'T> -> System.Collections.Generic.IEnumerator<'T> + + val inline checkNonNull : argName:string -> arg:'T -> unit + + val mkSeq : f:(unit -> System.Collections.Generic.IEnumerator<'U>) -> System.Collections.Generic.IEnumerable<'U> + + +namespace Microsoft.FSharp.Collections.SeqComposition + open System + open System.Collections + open System.Collections.Generic + open Microsoft.FSharp.Core + open Microsoft.FSharp.Collections + open Microsoft.FSharp.Collections.SeqComposition + + module Core = + [] + type NoValue = struct end + + [] + type internal EnumerableBase<'T> = + new : unit -> EnumerableBase<'T> + abstract member Append : IConsumableSeq<'T> -> IConsumableSeq<'T> + abstract member Length : unit -> int + abstract member GetRaw : unit -> seq<'T> + default Append : IConsumableSeq<'T> -> IConsumableSeq<'T> + default Length : unit -> int + default GetRaw : unit -> seq<'T> + interface IConsumableSeq<'T> + + [] + type internal EnumerableWithTransform<'T,'U> = + inherit EnumerableBase<'U> + new : ISeqTransform<'T,'U> * PipeIdx -> EnumerableWithTransform<'T,'U> + + [] + type internal IdentityTransform<'T> = + interface ISeqTransform<'T,'T> + static member Instance : ISeqTransform<'T,'T> + + type internal ISkipable = + // Seq.init(Infinite)? lazily uses Current. The only IConsumableSeq component that can do that is Skip + // and it can only do it at the start of a sequence + abstract CanSkip : unit -> bool + + type internal ThinConcatEnumerable<'T, 'Sources, 'Collection when 'Collection :> IConsumableSeq<'T>> = + inherit EnumerableBase<'T> + new : 'Sources * ('Sources->IConsumableSeq<'Collection>) -> ThinConcatEnumerable<'T, 'Sources, 'Collection> + interface IConsumableSeq<'T> + + type internal AppendEnumerable<'T> = + inherit ThinConcatEnumerable<'T, list>, IConsumableSeq<'T>> + new : list> -> AppendEnumerable<'T> + override Append : IConsumableSeq<'T> -> IConsumableSeq<'T> + + type internal ResizeArrayEnumerable<'T,'U> = + inherit EnumerableWithTransform<'T,'U> + new : ResizeArray<'T> * ISeqTransform<'T,'U> * PipeIdx -> ResizeArrayEnumerable<'T,'U> + interface IConsumableSeq<'U> + + type internal ThinResizeArrayEnumerable<'T> = + inherit ResizeArrayEnumerable<'T,'T> + new : ResizeArray<'T> -> ThinResizeArrayEnumerable<'T> + + type internal ArrayEnumerable<'T,'U> = + inherit EnumerableWithTransform<'T,'U> + new : array<'T> * ISeqTransform<'T,'U> * PipeIdx -> ArrayEnumerable<'T,'U> + interface IConsumableSeq<'U> + + type internal ThinArrayEnumerable<'T> = + inherit ArrayEnumerable<'T, 'T> + new : array<'T> -> ThinArrayEnumerable<'T> + interface IEnumerable<'T> + + type internal VanillaEnumerable<'T,'U> = + inherit EnumerableWithTransform<'T,'U> + new : IEnumerable<'T> * ISeqTransform<'T,'U> * PipeIdx -> VanillaEnumerable<'T,'U> + interface IConsumableSeq<'U> + + type internal ThinEnumerable<'T> = + inherit VanillaEnumerable<'T,'T> + new : IEnumerable<'T> -> ThinEnumerable<'T> + interface IEnumerable<'T> + + type internal UnfoldEnumerable<'T,'U,'GeneratorState> = + inherit EnumerableWithTransform<'T,'U> + new : ('GeneratorState->option<'T*'GeneratorState>)*'GeneratorState*ISeqTransform<'T,'U>*PipeIdx -> UnfoldEnumerable<'T,'U,'GeneratorState> + interface IConsumableSeq<'U> + + type internal InitEnumerableDecider<'T> = + inherit EnumerableBase<'T> + new : Nullable* (int->'T) * PipeIdx -> InitEnumerableDecider<'T> + interface IConsumableSeq<'T> + + type internal SingletonEnumerable<'T> = + inherit EnumerableBase<'T> + new : 'T -> SingletonEnumerable<'T> + interface IConsumableSeq<'T> + + type internal InitEnumerable<'T,'U> = + inherit EnumerableWithTransform<'T,'U> + new : Nullable * (int->'T) * ISeqTransform<'T,'U> * PipeIdx -> InitEnumerable<'T,'U> + interface IConsumableSeq<'U> + + type internal DelayedEnumerable<'T> = + inherit EnumerableBase<'T> + new : (unit->IConsumableSeq<'T>) * PipeIdx -> DelayedEnumerable<'T> + interface IConsumableSeq<'T> + + type internal EmptyEnumerable<'T> = + inherit EnumerableBase<'T> + private new : unit -> EmptyEnumerable<'T> + static member Instance : IConsumableSeq<'T> + interface IConsumableSeq<'T> namespace Microsoft.FSharp.Core.CompilerServices @@ -67,12 +152,6 @@ namespace Microsoft.FSharp.Core.CompilerServices /// A group of functions used as part of the compiled representation of F# sequence expressions. module RuntimeHelpers = - [] - type internal StructBox<'T when 'T : equality> = - new : value:'T -> StructBox<'T> - member Value : 'T - static member Comparer : IEqualityComparer> - val internal mkConcatSeq : sources:(seq<#seq<'T>>) -> seq<'T> /// The F# compiler emits calls to this function to @@ -124,6 +203,7 @@ namespace Microsoft.FSharp.Core.CompilerServices [] /// The F# compiler emits implementations of this type for compiled sequence expressions. type GeneratedSequenceBase<'T> = + inherit SeqComposition.Core.EnumerableBase<'T> /// The F# compiler emits implementations of this type for compiled sequence expressions. /// /// A new sequence generator for the expression. @@ -149,3 +229,4 @@ namespace Microsoft.FSharp.Core.CompilerServices interface IEnumerator<'T> interface IEnumerator interface IDisposable + interface SeqComposition.IConsumableSeq<'T> diff --git a/src/fsharp/FSharp.Core/set.fs b/src/fsharp/FSharp.Core/set.fs index 85c04a2c241..2da39afce49 100644 --- a/src/fsharp/FSharp.Core/set.fs +++ b/src/fsharp/FSharp.Core/set.fs @@ -495,21 +495,12 @@ namespace Microsoft.FSharp.Collections let res = Array.zeroCreate n copyToArray s res 0; res - - - - let rec mkFromEnumerator comparer acc (e: IEnumerator<_>) = - if e.MoveNext() then - mkFromEnumerator comparer (add comparer e.Current acc) e - else acc - let ofSeq comparer (c: IEnumerable<_>) = - use ie = c.GetEnumerator() - mkFromEnumerator comparer SetEmpty ie + let ofSeq comparer (c : IEnumerable<_>) = + Seq.fold (fun acc k -> add comparer k acc) SetEmpty c let ofArray comparer l = Array.fold (fun acc k -> add comparer k acc) SetEmpty l - [] [] [>)>] @@ -832,7 +823,7 @@ namespace Microsoft.FSharp.Collections let toSeq (set: Set<'T>) = (set:> seq<'T>) [] - let ofSeq (elements: seq<_>) = Set(elements) + let ofSeq (elements:seq<_>) = new Set<_>(elements) [] let difference (set1: Set<'T>) (set2: Set<'T>) = set1 - set2 diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.Unittests.fsproj b/tests/FSharp.Core.UnitTests/FSharp.Core.Unittests.fsproj index aca29fe00ad..6fc317c620f 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.Unittests.fsproj +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.Unittests.fsproj @@ -93,6 +93,11 @@ + + + + + diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/IConsumableSeqModule.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/IConsumableSeqModule.fs new file mode 100644 index 00000000000..01ae6508b98 --- /dev/null +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/IConsumableSeqModule.fs @@ -0,0 +1,1170 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace FSharp.Core.UnitTests.FSharp_Core.Microsoft_FSharp_Collections + +open System +open NUnit.Framework + +open FSharp.Core.UnitTests.LibraryTestFx + +#if IConsumableSeqIsPublic + +// Various tests for the: +// Microsoft.FSharp.Collections.iseq type + +(* +[Test Strategy] +Make sure each method works on: +* Integer IConsumableSeq (value type) +* String IConsumableSeq (reference type) +* Empty IConsumableSeq (0 elements) +* Null IConsumableSeq (null) +*) + +type iseq<'a> = FSharp.Collections.SeqComposition.IConsumableSeq<'a> + +[] +type IConsumableSeqModule() = + let iseq (x:seq<_>) = x |> IConsumableSeq.ofSeq + + [] + member this.AllPairs() = + + // integer IConsumableSeq + let resultInt = IConsumableSeq.allPairs (iseq [1..7]) (iseq [11..17]) + let expectedInt = + iseq <| seq { for i in 1..7 do + for j in 11..17 do + yield i, j } + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + let resultStr = IConsumableSeq.allPairs (iseq ["str3";"str4"]) (iseq ["str1";"str2"]) + let expectedStr = iseq ["str3","str1";"str3","str2";"str4","str1";"str4","str2"] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + VerifySeqsEqual IConsumableSeq.empty <| IConsumableSeq.allPairs IConsumableSeq.empty IConsumableSeq.empty + VerifySeqsEqual IConsumableSeq.empty <| IConsumableSeq.allPairs (iseq { 1..7 }) IConsumableSeq.empty + VerifySeqsEqual IConsumableSeq.empty <| IConsumableSeq.allPairs IConsumableSeq.empty (iseq { 1..7 }) + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.allPairs null null |> ignore) + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.allPairs null (iseq [1..7]) |> ignore) + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.allPairs (iseq [1..7]) null |> ignore) + () + + [] + member this.CachedSeq_Clear() = + + let evaluatedItems : int list ref = ref [] + let cachedSeq = + IConsumableSeq.initInfinite (fun i -> evaluatedItems := i :: !evaluatedItems; i) + |> IConsumableSeq.cache + + // Verify no items have been evaluated from the IConsumableSeq yet + Assert.AreEqual(List.length !evaluatedItems, 0) + + // Force evaluation of 10 elements + IConsumableSeq.take 10 cachedSeq + |> IConsumableSeq.toList + |> ignore + + // verify ref clear switch length + Assert.AreEqual(List.length !evaluatedItems, 10) + + // Force evaluation of 10 elements + IConsumableSeq.take 10 cachedSeq + |> IConsumableSeq.toList + |> ignore + + // Verify ref clear switch length (should be cached) + Assert.AreEqual(List.length !evaluatedItems, 10) + + + // Clear + (box cachedSeq :?> System.IDisposable) .Dispose() + + // Force evaluation of 10 elements + IConsumableSeq.take 10 cachedSeq + |> IConsumableSeq.toList + |> ignore + + // Verify length of evaluatedItemList is 20 + Assert.AreEqual(List.length !evaluatedItems, 20) + () + + [] + member this.Append() = + + // empty IConsumableSeq + let emptySeq1 = IConsumableSeq.empty + let emptySeq2 = IConsumableSeq.empty + let appendEmptySeq = IConsumableSeq.append emptySeq1 emptySeq2 + let expectResultEmpty = IConsumableSeq.empty + + VerifySeqsEqual expectResultEmpty appendEmptySeq + + // Integer IConsumableSeq + let integerSeq1:iseq = iseq [0..4] + let integerSeq2:iseq = iseq [5..9] + + let appendIntergerSeq = IConsumableSeq.append integerSeq1 integerSeq2 + + let expectResultInteger = iseq <| seq { for i in 0..9 -> i} + + VerifySeqsEqual expectResultInteger appendIntergerSeq + + + // String IConsumableSeq + let stringSeq1:iseq = iseq ["1";"2"] + let stringSeq2:iseq = iseq ["3";"4"] + + let appendStringSeq = IConsumableSeq.append stringSeq1 stringSeq2 + + let expectedResultString = iseq ["1";"2";"3";"4"] + + VerifySeqsEqual expectedResultString appendStringSeq + + // null IConsumableSeq + let nullSeq1 = iseq [null;null] + + let nullSeq2 =iseq [null;null] + + let appendNullSeq = IConsumableSeq.append nullSeq1 nullSeq2 + + let expectedResultNull = iseq [ null;null;null;null] + + VerifySeqsEqual expectedResultNull appendNullSeq + + () + + [] + member this.replicate() = + // replicate should create multiple copies of the given value + Assert.IsTrue(IConsumableSeq.isEmpty <| IConsumableSeq.replicate 0 null) + Assert.IsTrue(IConsumableSeq.isEmpty <| IConsumableSeq.replicate 0 1) + Assert.AreEqual(null, IConsumableSeq.head <| IConsumableSeq.replicate 1 null) + Assert.AreEqual(["1";"1"],IConsumableSeq.replicate 2 "1" |> IConsumableSeq.toList) + + CheckThrowsArgumentException (fun () -> IConsumableSeq.replicate -1 null |> ignore) + + + [] + member this.Average() = + // empty IConsumableSeq + let emptySeq:iseq = IConsumableSeq.empty + + CheckThrowsArgumentException (fun () -> IConsumableSeq.average emptySeq |> ignore) + + + // double IConsumableSeq + let doubleSeq:iseq = iseq [1.0;2.2;2.5;4.3] + + let averageDouble = IConsumableSeq.average doubleSeq + + Assert.IsFalse( averageDouble <> 2.5) + + // float32 IConsumableSeq + let floatSeq:iseq = iseq [ 2.0f;4.4f;5.0f;8.6f] + + let averageFloat = IConsumableSeq.average floatSeq + + Assert.IsFalse( averageFloat <> 5.0f) + + // decimal IConsumableSeq + let decimalSeq:iseq = iseq [ 0M;19M;19.03M] + + let averageDecimal = IConsumableSeq.average decimalSeq + + Assert.IsFalse( averageDecimal <> 12.676666666666666666666666667M ) + + //// null IConsumableSeq + //let nullSeq:iseq = null + + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.average nullSeq |> ignore) + () + + + [] + member this.AverageBy() = + // empty IConsumableSeq + let emptySeq:iseq = IConsumableSeq.empty + + CheckThrowsArgumentException (fun () -> IConsumableSeq.averageBy (fun x -> x+1.0) emptySeq |> ignore) + + // double IConsumableSeq + let doubleSeq:iseq = iseq [1.0;2.2;2.5;4.3] + + let averageDouble = IConsumableSeq.averageBy (fun x -> x-2.0) doubleSeq + + Assert.IsFalse( averageDouble <> 0.5 ) + + // float32 IConsumableSeq + let floatSeq:iseq = iseq [ 2.0f;4.4f;5.0f;8.6f] + + let averageFloat = IConsumableSeq.averageBy (fun x -> x*3.3f) floatSeq + + Assert.IsFalse( averageFloat <> 16.5f ) + + // decimal IConsumableSeq + let decimalSeq:iseq = iseq [ 0M;19M;19.03M] + + let averageDecimal = IConsumableSeq.averageBy (fun x -> x/10.7M) decimalSeq + + Assert.IsFalse( averageDecimal <> 1.1847352024922118380062305296M ) + + //// null IConsumableSeq + //let nullSeq:iseq = null + + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.averageBy (fun (x:double)->x+4.0) nullSeq |> ignore) + () + + [] + member this.Cache() = + // empty IConsumableSeq + let emptySeq:iseq = IConsumableSeq.empty + + let cacheEmpty = IConsumableSeq.cache emptySeq + + let expectedResultEmpty = IConsumableSeq.empty + + VerifySeqsEqual expectedResultEmpty cacheEmpty + + // double IConsumableSeq + let doubleSeq:iseq = iseq [1.0;2.2;2.5;4.3] + + let cacheDouble = IConsumableSeq.cache doubleSeq + + VerifySeqsEqual doubleSeq cacheDouble + + + // float32 IConsumableSeq + let floatSeq:iseq = iseq [ 2.0f;4.4f;5.0f;8.6f] + + let cacheFloat = IConsumableSeq.cache floatSeq + + VerifySeqsEqual floatSeq cacheFloat + + // decimal IConsumableSeq + let decimalSeq:iseq = iseq [ 0M; 19M; 19.03M] + + let cacheDecimal = IConsumableSeq.cache decimalSeq + + VerifySeqsEqual decimalSeq cacheDecimal + + // null IConsumableSeq + let nullSeq = iseq [null] + + let cacheNull = IConsumableSeq.cache nullSeq + + VerifySeqsEqual nullSeq cacheNull + () + + [] + member this.Case() = + + // integer IConsumableSeq + let integerArray = [|1;2|] + let integerSeq = IConsumableSeq.cast integerArray + + let expectedIntegerSeq = iseq [1;2] + + VerifySeqsEqual expectedIntegerSeq integerSeq + + // string IConsumableSeq + let stringArray = [|"a";"b"|] + let stringSeq = IConsumableSeq.cast stringArray + + let expectedStringSeq = iseq["a";"b"] + + VerifySeqsEqual expectedStringSeq stringSeq + + // empty IConsumableSeq + let emptySeq = IConsumableSeq.cast IConsumableSeq.empty + let expectedEmptySeq = IConsumableSeq.empty + + VerifySeqsEqual expectedEmptySeq IConsumableSeq.empty + + // null IConsumableSeq + let nullArray = [|null;null|] + let NullSeq = IConsumableSeq.cast nullArray + let expectedNullSeq = iseq [null;null] + + VerifySeqsEqual expectedNullSeq NullSeq + + CheckThrowsExn(fun () -> + let strings = + integerArray + |> IConsumableSeq.cast + for o in strings do ()) + + CheckThrowsExn(fun () -> + let strings = + integerArray + |> IConsumableSeq.cast + :> System.Collections.IEnumerable // without this upcast the for loop throws, so it should with this upcast too + for o in strings do ()) + + () + + [] + member this.Choose() = + + // int IConsumableSeq + let intSeq = iseq [1..20] + let funcInt x = if (x%5=0) then Some x else None + let intChoosed = IConsumableSeq.choose funcInt intSeq + let expectedIntChoosed = iseq <| seq { for i = 1 to 4 do yield i*5} + + + + VerifySeqsEqual expectedIntChoosed intChoosed + + // string IConsumableSeq + let stringSrc = iseq ["list";"List"] + let funcString x = match x with + | "list"-> Some x + | "List" -> Some x + | _ -> None + let strChoosed = IConsumableSeq.choose funcString stringSrc + let expectedStrChoose = iseq ["list";"List"] + + VerifySeqsEqual expectedStrChoose strChoosed + + // empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + let emptyChoosed = IConsumableSeq.choose funcInt emptySeq + + let expectedEmptyChoose = IConsumableSeq.empty + + VerifySeqsEqual expectedEmptyChoose emptySeq + + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.choose funcInt nullSeq |> ignore) + () + + [] + member this.ChunkBySize() = + + let verify expected actual = + IConsumableSeq.zip expected actual + |> IConsumableSeq.iter ((<||) VerifySeqsEqual) + + // int IConsumableSeq + verify (iseq [[1..4];[5..8]]) <| IConsumableSeq.chunkBySize 4 (iseq {1..8}) + verify (iseq [[1..4];[5..8];[9..10]]) <| IConsumableSeq.chunkBySize 4 (iseq {1..10}) + verify (iseq [[1]; [2]; [3]; [4]]) <| IConsumableSeq.chunkBySize 1 (iseq {1..4}) + + IConsumableSeq.chunkBySize 2 (IConsumableSeq.initInfinite id) + |> IConsumableSeq.take 3 + |> verify (iseq [[0;1];[2;3];[4;5]]) + + IConsumableSeq.chunkBySize 1 (IConsumableSeq.initInfinite id) + |> IConsumableSeq.take 5 + |> verify (iseq [[0];[1];[2];[3];[4]]) + + // string IConsumableSeq + verify (iseq [["a"; "b"];["c";"d"];["e"]]) <| IConsumableSeq.chunkBySize 2 (iseq ["a";"b";"c";"d";"e"]) + + // empty IConsumableSeq + verify IConsumableSeq.empty <| IConsumableSeq.chunkBySize 3 IConsumableSeq.empty + + //// null IConsumableSeq + //let nullSeq:iseq<_> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.chunkBySize 3 nullSeq |> ignore) + + // invalidArg + CheckThrowsArgumentException (fun () -> IConsumableSeq.chunkBySize 0 (iseq {1..10}) |> ignore) + CheckThrowsArgumentException (fun () -> IConsumableSeq.chunkBySize -1 (iseq {1..10}) |> ignore) + + () + + [] + member this.SplitInto() = + + let verify expected actual = + IConsumableSeq.zip expected actual + |> IConsumableSeq.iter ((<||) VerifySeqsEqual) + + // int IConsumableSeq + IConsumableSeq.splitInto 3 (iseq {1..10}) |> verify (iseq [ {1..4}; {5..7}; {8..10} ]) + IConsumableSeq.splitInto 3 (iseq {1..11}) |> verify (iseq [ {1..4}; {5..8}; {9..11} ]) + IConsumableSeq.splitInto 3 (iseq {1..12}) |> verify (iseq [ {1..4}; {5..8}; {9..12} ]) + + IConsumableSeq.splitInto 4 (iseq {1..5}) |> verify (iseq [ [1..2]; [3]; [4]; [5] ]) + IConsumableSeq.splitInto 20 (iseq {1..4}) |> verify (iseq [ [1]; [2]; [3]; [4] ]) + + // string IConsumableSeq + IConsumableSeq.splitInto 3 (iseq ["a";"b";"c";"d";"e"]) |> verify (iseq [ ["a"; "b"]; ["c";"d"]; ["e"] ]) + + // empty IConsumableSeq + VerifySeqsEqual [] <| IConsumableSeq.splitInto 3 (iseq []) + + //// null IConsumableSeq + //let nullSeq:iseq<_> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.splitInto 3 nullSeq |> ignore) + + // invalidArg + CheckThrowsArgumentException (fun () -> IConsumableSeq.splitInto 0 (iseq [1..10]) |> ignore) + CheckThrowsArgumentException (fun () -> IConsumableSeq.splitInto -1 (iseq [1..10]) |> ignore) + + () + + [] + member this.Compare() = + + // int IConsumableSeq + let intSeq1 = iseq [1;3;7;9] + let intSeq2 = iseq [2;4;6;8] + let funcInt x y = if (x>y) then x else 0 + let intcompared = IConsumableSeq.compareWith funcInt intSeq1 intSeq2 + + Assert.IsFalse( intcompared <> 7 ) + + // string IConsumableSeq + let stringSeq1 = iseq ["a"; "b"] + let stringSeq2 = iseq ["c"; "d"] + let funcString x y = match (x,y) with + | "a", "c" -> 0 + | "b", "d" -> 1 + |_ -> -1 + let strcompared = IConsumableSeq.compareWith funcString stringSeq1 stringSeq2 + Assert.IsFalse( strcompared <> 1 ) + + // empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + let emptycompared = IConsumableSeq.compareWith funcInt emptySeq emptySeq + + Assert.IsFalse( emptycompared <> 0 ) + + //// null IConsumableSeq + //let nullSeq:iseq = null + + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.compareWith funcInt nullSeq emptySeq |> ignore) + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.compareWith funcInt emptySeq nullSeq |> ignore) + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.compareWith funcInt nullSeq nullSeq |> ignore) + + () + + [] + member this.Concat() = + // integer IConsumableSeq + let seqInt = + iseq <| seq { for i in 0..9 do + yield iseq <| seq {for j in 0..9 do + yield i*10+j}} + let conIntSeq = IConsumableSeq.concat seqInt + let expectedIntSeq = iseq <| seq { for i in 0..99 do yield i} + + VerifySeqsEqual expectedIntSeq conIntSeq + + // string IConsumableSeq + let strSeq = + iseq <| seq { for a in 'a' .. 'b' do + for b in 'a' .. 'b' do + yield iseq [a; b] } + + let conStrSeq = IConsumableSeq.concat strSeq + let expectedStrSeq = iseq ['a';'a';'a';'b';'b';'a';'b';'b';] + VerifySeqsEqual expectedStrSeq conStrSeq + + // Empty IConsumableSeq + let emptySeqs = iseq [iseq[ IConsumableSeq.empty;IConsumableSeq.empty];iseq[ IConsumableSeq.empty;IConsumableSeq.empty]] + let conEmptySeq = IConsumableSeq.concat emptySeqs + let expectedEmptySeq =iseq <| seq { for i in 1..4 do yield IConsumableSeq.empty} + + VerifySeqsEqual expectedEmptySeq conEmptySeq + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.concat nullSeq |> ignore) + + () + + [] + member this.CountBy() = + // integer IConsumableSeq + let funcIntCount_by (x:int) = x%3 + let seqInt = + iseq <| seq { for i in 0..9 do + yield i} + let countIntSeq = IConsumableSeq.countByVal funcIntCount_by seqInt + + let expectedIntSeq = iseq [0,4;1,3;2,3] + + VerifySeqsEqual expectedIntSeq countIntSeq + + // string IConsumableSeq + let funcStrCount_by (s:string) = s.IndexOf("key") + let strSeq = iseq [ "key";"blank key";"key";"blank blank key"] + + let countStrSeq = IConsumableSeq.countByVal funcStrCount_by strSeq + let expectedStrSeq = iseq [0,2;6,1;12,1] + VerifySeqsEqual expectedStrSeq countStrSeq + + // Empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + let countEmptySeq = IConsumableSeq.countByVal funcIntCount_by emptySeq + let expectedEmptySeq =iseq [] + + VerifySeqsEqual expectedEmptySeq countEmptySeq + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.countBy funcIntCount_by nullSeq |> ignore) + () + + [] + member this.Distinct() = + + // integer IConsumableSeq + let IntDistinctSeq = + iseq <| seq { for i in 0..9 do + yield i % 3 } + + let DistinctIntSeq = IConsumableSeq.distinct IntDistinctSeq + + let expectedIntSeq = iseq [0;1;2] + + VerifySeqsEqual expectedIntSeq DistinctIntSeq + + // string IConsumableSeq + let strDistinctSeq = iseq ["elementDup"; "ele1"; "ele2"; "elementDup"] + + let DistnctStrSeq = IConsumableSeq.distinct strDistinctSeq + let expectedStrSeq = iseq ["elementDup"; "ele1"; "ele2"] + VerifySeqsEqual expectedStrSeq DistnctStrSeq + + // Empty IConsumableSeq + let emptySeq : iseq = IConsumableSeq.empty + let distinctEmptySeq : iseq = IConsumableSeq.distinct emptySeq + let expectedEmptySeq : iseq = iseq [] + + VerifySeqsEqual expectedEmptySeq distinctEmptySeq + + //// null IConsumableSeq + //let nullSeq:iseq = null + + //CheckThrowsArgumentNullException(fun () -> IConsumableSeq.distinct nullSeq |> ignore) + () + + [] + member this.DistinctBy () = + // integer IConsumableSeq + let funcInt x = x % 3 + let IntDistinct_bySeq = + iseq <| seq { for i in 0..9 do + yield i } + + let distinct_byIntSeq = IConsumableSeq.distinctBy funcInt IntDistinct_bySeq + + let expectedIntSeq = iseq [0;1;2] + + VerifySeqsEqual expectedIntSeq distinct_byIntSeq + + // string IConsumableSeq + let funcStrDistinct (s:string) = s.IndexOf("key") + let strSeq = iseq [ "key"; "blank key"; "key dup"; "blank key dup"] + + let DistnctStrSeq = IConsumableSeq.distinctBy funcStrDistinct strSeq + let expectedStrSeq = iseq ["key"; "blank key"] + VerifySeqsEqual expectedStrSeq DistnctStrSeq + + // Empty IConsumableSeq + let emptySeq : iseq = IConsumableSeq.empty + let distinct_byEmptySeq : iseq = IConsumableSeq.distinctBy funcInt emptySeq + let expectedEmptySeq : iseq = iseq [] + + VerifySeqsEqual expectedEmptySeq distinct_byEmptySeq + + //// null IConsumableSeq + //let nullSeq : iseq<'a> = null + + //CheckThrowsArgumentNullException(fun () -> IConsumableSeq.distinctBy funcInt nullSeq |> ignore) + () + + [] + member this.Except() = + // integer IConsumableSeq + let intSeq1 = iseq <| seq { yield! {1..100} + yield! {1..100} } + let intSeq2 = {1..10} + let expectedIntSeq = {11..100} + + VerifySeqsEqual expectedIntSeq <| IConsumableSeq.except intSeq2 intSeq1 + + // string IConsumableSeq + let strSeq1 = iseq ["a"; "b"; "c"; "d"; "a"] + let strSeq2 = iseq ["b"; "c"] + let expectedStrSeq = iseq ["a"; "d"] + + VerifySeqsEqual expectedStrSeq <| IConsumableSeq.except strSeq2 strSeq1 + + // double IConsumableSeq + // Sequences with nan do not behave, due to the F# generic equality comparisons +// let floatSeq1 = iseq [1.0; 1.0; System.Double.MaxValue; nan; nan] +// +// VerifySeqsEqual [1.0; System.Double.MaxValue; nan; nan] <| IConsumableSeq.except [] floatSeq1 +// VerifySeqsEqual [1.0; System.Double.MaxValue] <| IConsumableSeq.except [nan] floatSeq1 + + // empty IConsumableSeq + let emptyIntSeq = IConsumableSeq.empty + VerifySeqsEqual {1..100} <| IConsumableSeq.except emptyIntSeq intSeq1 + VerifySeqsEqual emptyIntSeq <| IConsumableSeq.except intSeq1 emptyIntSeq + VerifySeqsEqual emptyIntSeq <| IConsumableSeq.except emptyIntSeq emptyIntSeq + VerifySeqsEqual emptyIntSeq <| IConsumableSeq.except intSeq1 intSeq1 + + //// null IConsumableSeq + //let nullSeq : iseq = null + //CheckThrowsArgumentNullException(fun () -> IConsumableSeq.except nullSeq emptyIntSeq |> ignore) + //CheckThrowsArgumentNullException(fun () -> IConsumableSeq.except emptyIntSeq nullSeq |> ignore) + //CheckThrowsArgumentNullException(fun () -> IConsumableSeq.except nullSeq nullSeq |> ignore) + + () + + [] + member this.Exists() = + + // Integer IConsumableSeq + let funcInt x = (x % 2 = 0) + let IntexistsSeq = + iseq <| seq { for i in 0..9 do + yield i} + + let ifExistInt = IConsumableSeq.exists funcInt IntexistsSeq + + Assert.IsTrue( ifExistInt) + + // String IConsumableSeq + let funcStr (s:string) = s.Contains("key") + let strSeq = iseq ["key"; "blank key"] + + let ifExistStr = IConsumableSeq.exists funcStr strSeq + + Assert.IsTrue( ifExistStr) + + // Empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + let ifExistsEmpty = IConsumableSeq.exists funcInt emptySeq + + Assert.IsFalse( ifExistsEmpty) + + + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.exists funcInt nullSeq |> ignore) + () + + [] + member this.Exists2() = + // Integer IConsumableSeq + let funcInt x y = (x+y)%3=0 + let Intexists2Seq1 = iseq [1;3;7] + let Intexists2Seq2 = iseq [1;6;3] + + let ifExist2Int = IConsumableSeq.exists2 funcInt Intexists2Seq1 Intexists2Seq2 + Assert.IsTrue( ifExist2Int) + + // String IConsumableSeq + let funcStr s1 s2 = ((s1 + s2) = "CombinedString") + let strSeq1 = iseq [ "Combined"; "Not Combined"] + let strSeq2 = iseq ["String"; "Other String"] + let ifexists2Str = IConsumableSeq.exists2 funcStr strSeq1 strSeq2 + Assert.IsTrue(ifexists2Str) + + // Empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + let ifexists2Empty = IConsumableSeq.exists2 funcInt emptySeq emptySeq + Assert.IsFalse( ifexists2Empty) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.exists2 funcInt nullSeq nullSeq |> ignore) + () + + + [] + member this.Filter() = + // integer IConsumableSeq + let funcInt x = if (x % 5 = 0) then true else false + let IntSeq = + iseq <| seq { for i in 1..20 do + yield i } + + let filterIntSeq = IConsumableSeq.filter funcInt IntSeq + + let expectedfilterInt = iseq [ 5;10;15;20] + + VerifySeqsEqual expectedfilterInt filterIntSeq + + // string IConsumableSeq + let funcStr (s:string) = s.Contains("Expected Content") + let strSeq = iseq [ "Expected Content"; "Not Expected"; "Expected Content"; "Not Expected"] + + let filterStrSeq = IConsumableSeq.filter funcStr strSeq + + let expectedfilterStr = iseq ["Expected Content"; "Expected Content"] + + VerifySeqsEqual expectedfilterStr filterStrSeq + // Empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + let filterEmptySeq = IConsumableSeq.filter funcInt emptySeq + + let expectedEmptySeq =iseq [] + + VerifySeqsEqual expectedEmptySeq filterEmptySeq + + + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.filter funcInt nullSeq |> ignore) + () + + [] + member this.Find() = + + // integer IConsumableSeq + let funcInt x = if (x % 5 = 0) then true else false + let IntSeq = + iseq <| seq { for i in 1..20 do + yield i } + + let findInt = IConsumableSeq.find funcInt IntSeq + Assert.AreEqual(findInt, 5) + + // string IConsumableSeq + let funcStr (s:string) = s.Contains("Expected Content") + let strSeq = iseq [ "Expected Content";"Not Expected"] + + let findStr = IConsumableSeq.find funcStr strSeq + Assert.AreEqual(findStr, "Expected Content") + + // Empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + + CheckThrowsKeyNotFoundException(fun () -> IConsumableSeq.find funcInt emptySeq |> ignore) + + // null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.find funcInt nullSeq |> ignore) + () + + [] + member this.FindBack() = + // integer IConsumableSeq + let funcInt x = x % 5 = 0 + Assert.AreEqual(20, IConsumableSeq.findBack funcInt <| (iseq <| seq { 1..20 })) + Assert.AreEqual(15, IConsumableSeq.findBack funcInt <| (iseq <| seq { 1..19 })) + Assert.AreEqual(5, IConsumableSeq.findBack funcInt <| (iseq <| seq { 5..9 })) + + // string IConsumableSeq + let funcStr (s:string) = s.Contains("Expected") + let strSeq = iseq [ "Not Expected"; "Expected Content"] + let findStr = IConsumableSeq.findBack funcStr strSeq + Assert.AreEqual("Expected Content", findStr) + + // Empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + CheckThrowsKeyNotFoundException(fun () -> IConsumableSeq.findBack funcInt emptySeq |> ignore) + + // Not found + let emptySeq = IConsumableSeq.empty + CheckThrowsKeyNotFoundException(fun () -> iseq <| seq { 1..20 } |> IConsumableSeq.findBack (fun _ -> false) |> ignore) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.findBack funcInt nullSeq |> ignore) + () + + [] + member this.FindIndex() = + + // integer IConsumableSeq + let digits = [1 .. 100] |> IConsumableSeq.ofList + let idx = digits |> IConsumableSeq.findIndex (fun i -> i.ToString().Length > 1) + Assert.AreEqual(idx, 9) + + // empty IConsumableSeq + CheckThrowsKeyNotFoundException(fun () -> IConsumableSeq.findIndex (fun i -> true) IConsumableSeq.empty |> ignore) + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.findIndex (fun i -> true) null |> ignore) + () + + [] + member this.Permute() = + let mapIndex i = (i + 1) % 4 + + // integer iseq + let intSeq = iseq <| seq { 1..4 } + let resultInt = IConsumableSeq.permute mapIndex intSeq + VerifySeqsEqual (iseq [4;1;2;3]) resultInt + + // string iseq + let resultStr = IConsumableSeq.permute mapIndex (iseq [|"Lists"; "are"; "commonly"; "list" |]) + VerifySeqsEqual (iseq ["list"; "Lists"; "are"; "commonly" ]) resultStr + + // empty iseq + let resultEpt = IConsumableSeq.permute mapIndex (iseq [||]) + VerifySeqsEqual IConsumableSeq.empty resultEpt + + //// null iseq + //let nullSeq = null:string[] + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.permute mapIndex nullSeq |> ignore) + + // argument exceptions + CheckThrowsArgumentException (fun () -> IConsumableSeq.permute (fun _ -> 10) (iseq [0..9]) |> IConsumableSeq.iter ignore) + CheckThrowsArgumentException (fun () -> IConsumableSeq.permute (fun _ -> 0) (iseq [0..9]) |> IConsumableSeq.iter ignore) + () + + [] + member this.FindIndexBack() = + // integer IConsumableSeq + let digits = iseq <| seq { 1..100 } + let idx = digits |> IConsumableSeq.findIndexBack (fun i -> i.ToString().Length = 1) + Assert.AreEqual(idx, 8) + + // string IConsumableSeq + let funcStr (s:string) = s.Contains("Expected") + let strSeq = iseq [ "Not Expected"; "Expected Content" ] + let findStr = IConsumableSeq.findIndexBack funcStr strSeq + Assert.AreEqual(1, findStr) + + // empty IConsumableSeq + CheckThrowsKeyNotFoundException(fun () -> IConsumableSeq.findIndexBack (fun i -> true) IConsumableSeq.empty |> ignore) + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.findIndexBack (fun i -> true) null |> ignore) + () + + [] + member this.Pick() = + + let digits = [| 1 .. 10 |] |> IConsumableSeq.ofArray + let result = IConsumableSeq.pick (fun i -> if i > 5 then Some(i.ToString()) else None) digits + Assert.AreEqual(result, "6") + + // Empty iseq (Bugged, 4173) + CheckThrowsKeyNotFoundException (fun () -> IConsumableSeq.pick (fun i -> Some('a')) (iseq ([| |] : int[])) |> ignore) + + //// Null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.pick (fun i -> Some(i + 0)) null |> ignore) + () + + [] + member this.Fold() = + let funcInt x y = x+y + + let IntSeq = + iseq <| seq { for i in 1..10 do + yield i} + + let foldInt = IConsumableSeq.fold funcInt 1 IntSeq + if foldInt <> 56 then Assert.Fail() + + // string IConsumableSeq + let funcStr (x:string) (y:string) = x+y + let strSeq = iseq ["B"; "C"; "D" ; "E"] + let foldStr = IConsumableSeq.fold funcStr "A" strSeq + + if foldStr <> "ABCDE" then Assert.Fail() + + + // Empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + let foldEmpty = IConsumableSeq.fold funcInt 1 emptySeq + if foldEmpty <> 1 then Assert.Fail() + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.fold funcInt 1 nullSeq |> ignore) + () + + + + [] + member this.Fold2() = + Assert.AreEqual([(3,5); (2,3); (1,1)],IConsumableSeq.fold2 (fun acc x y -> (x,y)::acc) [] (iseq [ 1..3 ]) (iseq [1..2..6])) + + // integer List + let funcInt x y z = x + y + z + let resultInt = IConsumableSeq.fold2 funcInt 9 (iseq [ 1..10 ]) (iseq [1..2..20]) + Assert.AreEqual(164, resultInt) + + // string List + let funcStr x y z = x + y + z + let resultStr = IConsumableSeq.fold2 funcStr "*" (iseq ["a"; "b"; "c" ; "d" ]) (iseq ["A"; "B"; "C" ; "D" ] ) + Assert.AreEqual("*aAbBcCdD", resultStr) + + // empty List + let emptyArr:int list = [ ] + let resultEpt = IConsumableSeq.fold2 funcInt 5 (iseq emptyArr) (iseq emptyArr) + Assert.AreEqual(5, resultEpt) + + Assert.AreEqual(0,IConsumableSeq.fold2 funcInt 0 IConsumableSeq.empty (iseq [1])) + Assert.AreEqual(-1,IConsumableSeq.fold2 funcInt -1 (iseq [1]) IConsumableSeq.empty) + + Assert.AreEqual(2,IConsumableSeq.fold2 funcInt 0 (iseq [1;2]) (iseq [1])) + Assert.AreEqual(4,IConsumableSeq.fold2 funcInt 0 (iseq [1]) (iseq [3;6])) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.fold2 funcInt 0 nullSeq (iseq [1]) |> ignore) + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.fold2 funcInt 0 (iseq [1]) nullSeq |> ignore) + () + + [] + member this.FoldBack() = + // int IConsumableSeq + let funcInt x y = x-y + let IntSeq = iseq <| seq { 1..4 } + let foldInt = IConsumableSeq.foldBack funcInt IntSeq 6 + Assert.AreEqual((1-(2-(3-(4-6)))), foldInt) + + // string IConsumableSeq + let funcStr (x:string) (y:string) = y.Remove(0,x.Length) + let strSeq = iseq [ "A"; "B"; "C"; "D" ] + let foldStr = IConsumableSeq.foldBack funcStr strSeq "ABCDE" + Assert.AreEqual("E", foldStr) + + // single element + let funcStr2 elem acc = sprintf "%s%s" elem acc + let strSeq2 = iseq [ "A" ] + let foldStr2 = IConsumableSeq.foldBack funcStr2 strSeq2 "X" + Assert.AreEqual("AX", foldStr2) + + // Empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + let foldEmpty = IConsumableSeq.foldBack funcInt emptySeq 1 + Assert.AreEqual(1, foldEmpty) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.foldBack funcInt nullSeq 1 |> ignore) + + // Validate that foldBack with the cons operator and the empty list returns a copy of the sequence + let cons x y = x :: y + let identityFoldr = IConsumableSeq.foldBack cons IntSeq [] + Assert.AreEqual([1;2;3;4], identityFoldr) + + () + + [] + member this.foldBack2() = + // int IConsumableSeq + let funcInt x y z = x + y + z + let intSeq = iseq <| seq { 1..10 } + let resultInt = IConsumableSeq.foldBack2 funcInt intSeq (iseq <| seq { 1..2..20 }) 9 + Assert.AreEqual(164, resultInt) + + // string IConsumableSeq + let funcStr = sprintf "%s%s%s" + let strSeq = iseq [ "A"; "B"; "C"; "D" ] + let resultStr = IConsumableSeq.foldBack2 funcStr strSeq (iseq [ "a"; "b"; "c"; "d"]) "*" + Assert.AreEqual("AaBbCcDd*", resultStr) + + // single element + let strSeqSingle = iseq [ "X" ] + Assert.AreEqual("XAZ", IConsumableSeq.foldBack2 funcStr strSeqSingle strSeq "Z") + Assert.AreEqual("AXZ", IConsumableSeq.foldBack2 funcStr strSeq strSeqSingle "Z") + Assert.AreEqual("XYZ", IConsumableSeq.foldBack2 funcStr strSeqSingle (iseq [ "Y" ]) "Z") + + // empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + Assert.AreEqual(1, IConsumableSeq.foldBack2 funcInt emptySeq emptySeq 1) + Assert.AreEqual(1, IConsumableSeq.foldBack2 funcInt emptySeq intSeq 1) + Assert.AreEqual(1, IConsumableSeq.foldBack2 funcInt intSeq emptySeq 1) + + // infinite IConsumableSeq + let infiniteSeq = IConsumableSeq.initInfinite (fun i -> 2 * i + 1) + Assert.AreEqual(164, IConsumableSeq.foldBack2 funcInt intSeq infiniteSeq 9) + Assert.AreEqual(164, IConsumableSeq.foldBack2 funcInt infiniteSeq intSeq 9) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.foldBack2 funcInt nullSeq intSeq 1 |> ignore) + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.foldBack2 funcInt intSeq nullSeq 1 |> ignore) + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.foldBack2 funcInt nullSeq nullSeq 1 |> ignore) + + () + + [] + member this.ForAll() = + + let funcInt x = if x%2 = 0 then true else false + let IntSeq = + iseq <| seq { for i in 1..10 do + yield i*2} + let for_allInt = IConsumableSeq.forall funcInt IntSeq + + if for_allInt <> true then Assert.Fail() + + + // string IConsumableSeq + let funcStr (x:string) = x.Contains("a") + let strSeq = iseq ["a"; "ab"; "abc" ; "abcd"] + let for_allStr = IConsumableSeq.forall funcStr strSeq + + if for_allStr <> true then Assert.Fail() + + + // Empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + let for_allEmpty = IConsumableSeq.forall funcInt emptySeq + + if for_allEmpty <> true then Assert.Fail() + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.forall funcInt nullSeq |> ignore) + () + + [] + member this.ForAll2() = + + let funcInt x y = if (x+y)%2 = 0 then true else false + let IntSeq = + iseq <| seq { for i in 1..10 do + yield i} + + let for_all2Int = IConsumableSeq.forall2 funcInt IntSeq IntSeq + + if for_all2Int <> true then Assert.Fail() + + // string IConsumableSeq + let funcStr (x:string) (y:string) = (x+y).Length = 5 + let strSeq1 = iseq ["a"; "ab"; "abc" ; "abcd"] + let strSeq2 = iseq ["abcd"; "abc"; "ab" ; "a"] + let for_all2Str = IConsumableSeq.forall2 funcStr strSeq1 strSeq2 + + if for_all2Str <> true then Assert.Fail() + + // Empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + let for_all2Empty = IConsumableSeq.forall2 funcInt emptySeq emptySeq + + if for_all2Empty <> true then Assert.Fail() + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.forall2 funcInt nullSeq nullSeq |> ignore) + + [] + member this.GroupBy() = + + let funcInt x = x%5 + + let IntSeq = + iseq <| seq { for i in 0 .. 9 do + yield i } + + let group_byInt = IConsumableSeq.groupByVal funcInt IntSeq |> IConsumableSeq.map (fun (i, v) -> i, IConsumableSeq.toList v) + + let expectedIntSeq = + iseq <| seq { for i in 0..4 do + yield i, [i; i+5] } + + VerifySeqsEqual group_byInt expectedIntSeq + + // string IConsumableSeq + let funcStr (x:string) = x.Length + let strSeq = iseq ["length7"; "length 8"; "length7" ; "length 9"] + + let group_byStr = IConsumableSeq.groupByVal funcStr strSeq |> IConsumableSeq.map (fun (i, v) -> i, IConsumableSeq.toList v) + let expectedStrSeq = + iseq <| seq { + yield 7, ["length7"; "length7"] + yield 8, ["length 8"] + yield 9, ["length 9"] } + + VerifySeqsEqual expectedStrSeq group_byStr + + // Empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + let group_byEmpty = IConsumableSeq.groupByVal funcInt emptySeq + let expectedEmptySeq = iseq [] + + VerifySeqsEqual expectedEmptySeq group_byEmpty + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //let group_byNull = IConsumableSeq.groupBy funcInt nullSeq + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.iter (fun _ -> ()) group_byNull) + () + + [] + member this.DisposalOfUnstartedEnumerator() = + let run = ref false + let f() = iseq <| seq { + try + () + finally + run := true + } + + f().GetEnumerator().Dispose() + Assert.IsFalse(!run) + + [] + member this.WeirdLocalNames() = + + let f pc = iseq <| seq { + yield pc + yield (pc+1) + yield (pc+2) + } + + let l = f 3 |> IConsumableSeq.toList + Assert.AreEqual([3;4;5], l) + + let f i = iseq <| seq { + let pc = i*2 + yield pc + yield (pc+1) + yield (pc+2) + } + let l = f 3 |> IConsumableSeq.toList + Assert.AreEqual([6;7;8], l) + + [] + member this.Contains() = + + // Integer IConsumableSeq + let intSeq = iseq <| seq { 0..9 } + + let ifContainsInt = IConsumableSeq.contains 5 intSeq + + Assert.IsTrue(ifContainsInt) + + // String IConsumableSeq + let strSeq = iseq ["key"; "blank key"] + + let ifContainsStr = IConsumableSeq.contains "key" strSeq + + Assert.IsTrue(ifContainsStr) + + // Empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + let ifContainsEmpty = IConsumableSeq.contains 5 emptySeq + + Assert.IsFalse(ifContainsEmpty) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.contains 5 nullSeq |> ignore) + +#endif \ No newline at end of file diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/IConsumableSeqModule2.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/IConsumableSeqModule2.fs new file mode 100644 index 00000000000..300f7fcebfa --- /dev/null +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/IConsumableSeqModule2.fs @@ -0,0 +1,1845 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace FSharp.Core.UnitTests.FSharp_Core.Microsoft_FSharp_Collections + +open System +open NUnit.Framework + +open FSharp.Core.UnitTests.LibraryTestFx + +#if IConsumableSeqIsPublic + +//type iseq<'a> = IConsumableSeq.Core.IConsumableSeq<'a> + +type IConsumableSeqWindowedTestInput<'t> = + { + InputSeq : iseq<'t> + WindowSize : int + ExpectedSeq : iseq<'t[]> + Exception : Type option + } + +[] +type IConsumableSeqModule2() = + let iseq (x:seq<_>) = x |> IConsumableSeq.ofSeq + + [] + member this.Hd() = + + let IntSeq = + iseq <| seq { for i in 0 .. 9 do + yield i } + + if IConsumableSeq.head IntSeq <> 0 then Assert.Fail() + + // string IConsumableSeq + let strSeq = iseq ["first"; "second"; "third"] + if IConsumableSeq.head strSeq <> "first" then Assert.Fail() + + // Empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + CheckThrowsArgumentException ( fun() -> IConsumableSeq.head emptySeq) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () ->IConsumableSeq.head nullSeq) + () + + [] + member this.TryHead() = + // int IConsumableSeq + let IntSeq = + iseq <| seq { for i in 0 .. 9 -> i } + + let intResult = IConsumableSeq.tryHead IntSeq + + // string IConsumableSeq + let strResult = IConsumableSeq.tryHead (iseq ["first"; "second"; "third"]) + Assert.AreEqual("first", strResult.Value) + + // Empty IConsumableSeq + let emptyResult = IConsumableSeq.tryHead IConsumableSeq.empty + Assert.AreEqual(None, emptyResult) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () ->IConsumableSeq.head nullSeq) + () + + [] + member this.Tl() = + // integer iseq + let resultInt = IConsumableSeq.tail <| (iseq <| seq { 1..10 } ) + Assert.AreEqual(Array.ofSeq (iseq <| seq { 2..10 }), Array.ofSeq resultInt) + + // string iseq + let resultStr = IConsumableSeq.tail <| (iseq <| seq { yield "a"; yield "b"; yield "c"; yield "d" }) + Assert.AreEqual(Array.ofSeq (iseq <| seq { yield "b"; yield "c" ; yield "d" }), Array.ofSeq resultStr) + + // 1-element iseq + let resultStr2 = IConsumableSeq.tail <| (iseq <| seq { yield "a" }) + Assert.AreEqual(Array.ofSeq (IConsumableSeq.empty : iseq), Array.ofSeq resultStr2) + + //CheckThrowsArgumentNullException(fun () -> IConsumableSeq.tail null |> ignore) + CheckThrowsArgumentException(fun () -> IConsumableSeq.tail IConsumableSeq.empty |> IConsumableSeq.iter (fun _ -> failwith "Should not be reached")) + () + + [] + member this.Last() = + + let IntSeq = + iseq <| seq { for i in 0 .. 9 do + yield i } + + if IConsumableSeq.last IntSeq <> 9 then Assert.Fail() + + // string IConsumableSeq + let strSeq = iseq ["first"; "second"; "third"] + if IConsumableSeq.last strSeq <> "third" then Assert.Fail() + + // Empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + CheckThrowsArgumentException ( fun() -> IConsumableSeq.last emptySeq) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () ->IConsumableSeq.last nullSeq) + () + + [] + member this.TryLast() = + + let IntSeq = + iseq <| seq { for i in 0 .. 9 -> i } + + let intResult = IConsumableSeq.tryLast IntSeq + Assert.AreEqual(9, intResult.Value) + + // string IConsumableSeq + let strResult = IConsumableSeq.tryLast (iseq ["first"; "second"; "third"]) + Assert.AreEqual("third", strResult.Value) + + // Empty IConsumableSeq + let emptyResult = IConsumableSeq.tryLast IConsumableSeq.empty + Assert.IsTrue(emptyResult.IsNone) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () ->IConsumableSeq.tryLast nullSeq |> ignore) + () + + [] + member this.ExactlyOne() = + + let IntSeq = + iseq <| seq { for i in 7 .. 7 do + yield i } + + if IConsumableSeq.exactlyOne IntSeq <> 7 then Assert.Fail() + + // string IConsumableSeq + let strSeq = iseq ["second"] + if IConsumableSeq.exactlyOne strSeq <> "second" then Assert.Fail() + + // Empty IConsumableSeq + let emptySeq = IConsumableSeq.empty + CheckThrowsArgumentException ( fun() -> IConsumableSeq.exactlyOne emptySeq) + + // non-singleton IConsumableSeq + let emptySeq = IConsumableSeq.empty + CheckThrowsArgumentException ( fun() -> IConsumableSeq.exactlyOne (iseq [ 0 .. 1 ]) |> ignore ) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () ->IConsumableSeq.exactlyOne nullSeq) + () + + + [] + member this.Init() = + + let funcInt x = x + let init_finiteInt = IConsumableSeq.init 9 funcInt + let expectedIntSeq = iseq [ 0..8] + + VerifySeqsEqual expectedIntSeq init_finiteInt + + + // string IConsumableSeq + let funcStr x = x.ToString() + let init_finiteStr = IConsumableSeq.init 5 funcStr + let expectedStrSeq = iseq ["0";"1";"2";"3";"4"] + + VerifySeqsEqual expectedStrSeq init_finiteStr + + // null IConsumableSeq + let funcNull x = null + let init_finiteNull = IConsumableSeq.init 3 funcNull + let expectedNullSeq = iseq [ null;null;null] + + VerifySeqsEqual expectedNullSeq init_finiteNull + () + + [] + member this.InitInfinite() = + + let funcInt x = x + let init_infiniteInt = IConsumableSeq.initInfinite funcInt + let resultint = IConsumableSeq.find (fun x -> x =100) init_infiniteInt + + Assert.AreEqual(100,resultint) + + + // string IConsumableSeq + let funcStr x = x.ToString() + let init_infiniteStr = IConsumableSeq.initInfinite funcStr + let resultstr = IConsumableSeq.find (fun x -> x = "100") init_infiniteStr + + Assert.AreEqual("100",resultstr) + + + [] + member this.IsEmpty() = + + //iseq int + let seqint = iseq [1;2;3] + let is_emptyInt = IConsumableSeq.isEmpty seqint + + Assert.IsFalse(is_emptyInt) + + //iseq str + let seqStr = iseq["first";"second"] + let is_emptyStr = IConsumableSeq.isEmpty seqStr + + Assert.IsFalse(is_emptyInt) + + //iseq empty + let seqEmpty = IConsumableSeq.empty + let is_emptyEmpty = IConsumableSeq.isEmpty seqEmpty + Assert.IsTrue(is_emptyEmpty) + + ////iseq null + //let seqnull:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.isEmpty seqnull |> ignore) + () + + [] + member this.Iter() = + //iseq int + let seqint = iseq [ 1..3] + let cacheint = ref 0 + + let funcint x = cacheint := !cacheint + x + IConsumableSeq.iter funcint seqint + Assert.AreEqual(6,!cacheint) + + //iseq str + let seqStr = iseq ["first";"second"] + let cachestr =ref "" + let funcstr x = cachestr := !cachestr+x + IConsumableSeq.iter funcstr seqStr + + Assert.AreEqual("firstsecond",!cachestr) + + // empty array + let emptyseq = IConsumableSeq.empty + let resultEpt = ref 0 + IConsumableSeq.iter (fun x -> Assert.Fail()) emptyseq + + //// null seqay + //let nullseq:iseq<'a> = null + + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.iter funcint nullseq |> ignore) + () + + [] + member this.Iter2() = + + //iseq int + let seqint = iseq [ 1..3] + let cacheint = ref 0 + + let funcint x y = cacheint := !cacheint + x+y + IConsumableSeq.iter2 funcint seqint seqint + Assert.AreEqual(12,!cacheint) + + //iseq str + let seqStr = iseq ["first";"second"] + let cachestr =ref "" + let funcstr x y = cachestr := !cachestr+x+y + IConsumableSeq.iter2 funcstr seqStr seqStr + + Assert.AreEqual("firstfirstsecondsecond",!cachestr) + + // empty array + let emptyseq = IConsumableSeq.empty + let resultEpt = ref 0 + IConsumableSeq.iter2 (fun x y-> Assert.Fail()) emptyseq emptyseq + + //// null seqay + //let nullseq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.iter2 funcint nullseq nullseq |> ignore) + + () + + [] + member this.Iteri() = + + // iseq int + let seqint = iseq [ 1..10] + let cacheint = ref 0 + + let funcint x y = cacheint := !cacheint + x+y + IConsumableSeq.iteri funcint seqint + Assert.AreEqual(100,!cacheint) + + // iseq str + let seqStr = iseq ["first";"second"] + let cachestr =ref 0 + let funcstr (x:int) (y:string) = cachestr := !cachestr+ x + y.Length + IConsumableSeq.iteri funcstr seqStr + + Assert.AreEqual(12,!cachestr) + + // empty array + let emptyseq = IConsumableSeq.empty + let resultEpt = ref 0 + IConsumableSeq.iteri funcint emptyseq + Assert.AreEqual(0,!resultEpt) + + //// null seqay + //let nullseq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.iteri funcint nullseq |> ignore) + () + + [] + member this.Iteri2() = + + //iseq int + let seqint = iseq [ 1..3] + let cacheint = ref 0 + + let funcint x y z = cacheint := !cacheint + x + y + z + IConsumableSeq.iteri2 funcint seqint seqint + Assert.AreEqual(15,!cacheint) + + //iseq str + let seqStr = iseq ["first";"second"] + let cachestr = ref 0 + let funcstr (x:int) (y:string) (z:string) = cachestr := !cachestr + x + y.Length + z.Length + IConsumableSeq.iteri2 funcstr seqStr seqStr + + Assert.AreEqual(23,!cachestr) + + // empty iseq + let emptyseq = IConsumableSeq.empty + let resultEpt = ref 0 + IConsumableSeq.iteri2 (fun x y z -> Assert.Fail()) emptyseq emptyseq + + //// null iseq + //let nullseq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.iteri2 funcint nullseq nullseq |> ignore) + + // len1 <> len2 + let shorterSeq = iseq <| seq { 1..3 } + let longerSeq = iseq <| seq { 2..2..100 } + + let testSeqLengths seq1 seq2 = + let cache = ref 0 + let f x y z = cache := !cache + x + y + z + IConsumableSeq.iteri2 f seq1 seq2 + !cache + + Assert.AreEqual(21, testSeqLengths shorterSeq longerSeq) + Assert.AreEqual(21, testSeqLengths longerSeq shorterSeq) + + () + + [] + member this.Length() = + + // integer iseq + let resultInt = IConsumableSeq.length (iseq {1..8}) + if resultInt <> 8 then Assert.Fail() + + // string IConsumableSeq + let resultStr = IConsumableSeq.length (iseq ["Lists"; "are"; "commonly" ; "list" ]) + if resultStr <> 4 then Assert.Fail() + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.length IConsumableSeq.empty + if resultEpt <> 0 then Assert.Fail() + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.length nullSeq |> ignore) + + () + + [] + member this.Map() = + + // integer IConsumableSeq + let funcInt x = + match x with + | _ when x % 2 = 0 -> 10*x + | _ -> x + + let resultInt = IConsumableSeq.map funcInt (iseq { 1..10 }) + let expectedint = iseq [1;20;3;40;5;60;7;80;9;100] + + VerifySeqsEqual expectedint resultInt + + // string IConsumableSeq + let funcStr (x:string) = x.ToLower() + let resultStr = IConsumableSeq.map funcStr (iseq ["Lists"; "Are"; "Commonly" ; "List" ]) + let expectedSeq = iseq ["lists"; "are"; "commonly" ; "list"] + + VerifySeqsEqual expectedSeq resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.map funcInt IConsumableSeq.empty + VerifySeqsEqual IConsumableSeq.empty resultEpt + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.map funcStr nullSeq |> ignore) + + () + + [] + member this.Map2() = + // integer IConsumableSeq + let funcInt x y = x+y + let resultInt = IConsumableSeq.map2 funcInt (iseq { 1..10 }) (iseq {2..2..20}) + let expectedint = iseq [3;6;9;12;15;18;21;24;27;30] + + VerifySeqsEqual expectedint resultInt + + // string IConsumableSeq + let funcStr (x:int) (y:string) = x+y.Length + let resultStr = IConsumableSeq.map2 funcStr (iseq[3;6;9;11]) (iseq ["Lists"; "Are"; "Commonly" ; "List" ]) + let expectedSeq = iseq [8;9;17;15] + + VerifySeqsEqual expectedSeq resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.map2 funcInt IConsumableSeq.empty IConsumableSeq.empty + VerifySeqsEqual IConsumableSeq.empty resultEpt + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //let validSeq = iseq [1] + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.map2 funcInt nullSeq validSeq |> ignore) + + () + + [] + member this.Map3() = + // Integer iseq + let funcInt a b c = (a + b) * c + let resultInt = IConsumableSeq.map3 funcInt (iseq { 1..8 }) (iseq { 2..9 }) (iseq { 3..10 }) + let expectedInt = iseq [9; 20; 35; 54; 77; 104; 135; 170] + VerifySeqsEqual expectedInt resultInt + + // First iseq is shorter + VerifySeqsEqual (iseq [9; 20]) (IConsumableSeq.map3 funcInt (iseq { 1..2 }) (iseq { 2..9 }) (iseq { 3..10 })) + // Second iseq is shorter + VerifySeqsEqual (iseq [9; 20; 35]) (IConsumableSeq.map3 funcInt (iseq { 1..8 }) (iseq { 2..4 }) (iseq { 3..10 })) + // Third iseq is shorter + VerifySeqsEqual (iseq [9; 20; 35; 54]) (IConsumableSeq.map3 funcInt (iseq { 1..8 }) (iseq { 2..6 }) (iseq { 3..6 })) + + // String iseq + let funcStr a b c = a + b + c + let resultStr = IConsumableSeq.map3 funcStr (iseq ["A";"B";"C";"D"]) (iseq ["a";"b";"c";"d"]) (iseq ["1";"2";"3";"4"]) + let expectedStr = iseq ["Aa1";"Bb2";"Cc3";"Dd4"] + VerifySeqsEqual expectedStr resultStr + + // Empty iseq + let resultEmpty = IConsumableSeq.map3 funcStr IConsumableSeq.empty IConsumableSeq.empty IConsumableSeq.empty + VerifySeqsEqual IConsumableSeq.empty resultEmpty + + //// Null iseq + //let nullSeq = null : iseq<_> + //let nonNullSeq = iseq [1] + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.map3 funcInt nullSeq nonNullSeq nullSeq |> ignore) + + () + + [] + member this.MapFold() = + // integer IConsumableSeq + let funcInt acc x = if x % 2 = 0 then 10*x, acc + 1 else x, acc + let resultInt,resultIntAcc = IConsumableSeq.mapFold funcInt 100 <| (iseq <| seq { 1..10 }) + VerifySeqsEqual (iseq [ 1;20;3;40;5;60;7;80;9;100 ]) resultInt + Assert.AreEqual(105, resultIntAcc) + + // string IConsumableSeq + let funcStr acc (x:string) = match x.Length with 0 -> "empty", acc | _ -> x.ToLower(), sprintf "%s%s" acc x + let resultStr,resultStrAcc = IConsumableSeq.mapFold funcStr "" <| iseq [ "";"BB";"C";"" ] + VerifySeqsEqual (iseq [ "empty";"bb";"c";"empty" ]) resultStr + Assert.AreEqual("BBC", resultStrAcc) + + // empty IConsumableSeq + let resultEpt,resultEptAcc = IConsumableSeq.mapFold funcInt 100 IConsumableSeq.empty + VerifySeqsEqual IConsumableSeq.empty resultEpt + Assert.AreEqual(100, resultEptAcc) + + //// null IConsumableSeq + //let nullArr = null:iseq + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.mapFold funcStr "" nullArr |> ignore) + + () + + [] + member this.MapFoldBack() = + // integer IConsumableSeq + let funcInt x acc = if acc < 105 then 10*x, acc + 2 else x, acc + let resultInt,resultIntAcc = IConsumableSeq.mapFoldBack funcInt (iseq <| seq { 1..10 }) 100 + VerifySeqsEqual (iseq [ 1;2;3;4;5;6;7;80;90;100 ]) resultInt + Assert.AreEqual(106, resultIntAcc) + + // string IConsumableSeq + let funcStr (x:string) acc = match x.Length with 0 -> "empty", acc | _ -> x.ToLower(), sprintf "%s%s" acc x + let resultStr,resultStrAcc = IConsumableSeq.mapFoldBack funcStr (iseq [ "";"BB";"C";"" ]) "" + VerifySeqsEqual (iseq [ "empty";"bb";"c";"empty" ]) resultStr + Assert.AreEqual("CBB", resultStrAcc) + + // empty IConsumableSeq + let resultEpt,resultEptAcc = IConsumableSeq.mapFoldBack funcInt IConsumableSeq.empty 100 + VerifySeqsEqual IConsumableSeq.empty resultEpt + Assert.AreEqual(100, resultEptAcc) + + //// null IConsumableSeq + //let nullArr = null:iseq + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.mapFoldBack funcStr nullArr "" |> ignore) + + () + + member private this.MapWithSideEffectsTester (map : (int -> int) -> iseq -> iseq) expectExceptions = + let i = ref 0 + let f x = i := !i + 1; x*x + let e = ((iseq [1;2]) |> map f).GetEnumerator() + + if expectExceptions then + CheckThrowsInvalidOperationExn (fun _ -> e.Current|>ignore) + Assert.AreEqual(0, !i) + if not (e.MoveNext()) then Assert.Fail() + Assert.AreEqual(1, !i) + let _ = e.Current + Assert.AreEqual(1, !i) + let _ = e.Current + Assert.AreEqual(1, !i) + + if not (e.MoveNext()) then Assert.Fail() + Assert.AreEqual(2, !i) + let _ = e.Current + Assert.AreEqual(2, !i) + let _ = e.Current + Assert.AreEqual(2, !i) + + if e.MoveNext() then Assert.Fail() + Assert.AreEqual(2, !i) + if expectExceptions then + CheckThrowsInvalidOperationExn (fun _ -> e.Current |> ignore) + Assert.AreEqual(2, !i) + + + i := 0 + let e = ((iseq []) |> map f).GetEnumerator() + if e.MoveNext() then Assert.Fail() + Assert.AreEqual(0,!i) + if e.MoveNext() then Assert.Fail() + Assert.AreEqual(0,!i) + + + member private this.MapWithExceptionTester (map : (int -> int) -> iseq -> iseq) = + let raiser x = if x > 0 then raise(NotSupportedException()) else x + let e = (map raiser (iseq [0; 1])).GetEnumerator() + Assert.IsTrue(e.MoveNext()) // should not throw + Assert.AreEqual(0, e.Current) + CheckThrowsNotSupportedException(fun _ -> e.MoveNext() |> ignore) + Assert.AreEqual(0, e.Current) // should not throw + + [] + member this.MapWithSideEffects () = + this.MapWithSideEffectsTester IConsumableSeq.map true + + [] + member this.MapWithException () = + this.MapWithExceptionTester IConsumableSeq.map + + + [] + member this.SingletonCollectWithSideEffects () = + this.MapWithSideEffectsTester (fun f-> IConsumableSeq.collect (f >> IConsumableSeq.singleton)) true + + [] + member this.SingletonCollectWithException () = + this.MapWithExceptionTester (fun f-> IConsumableSeq.collect (f >> IConsumableSeq.singleton)) + +#if !FX_NO_LINQ + [] + member this.SystemLinqSelectWithSideEffects () = + this.MapWithSideEffectsTester (fun f s -> iseq <| System.Linq.Enumerable.Select(s, Func<_,_>(f))) false + + [] + member this.SystemLinqSelectWithException () = + this.MapWithExceptionTester (fun f s -> iseq <| System.Linq.Enumerable.Select(s, Func<_,_>(f))) +#endif + + [] + member this.MapiWithSideEffects () = + let i = ref 0 + let f _ x = i := !i + 1; x*x + let e = ((iseq [1;2]) |> IConsumableSeq.mapi f).GetEnumerator() + + CheckThrowsInvalidOperationExn (fun _ -> e.Current|>ignore) + Assert.AreEqual(0, !i) + if not (e.MoveNext()) then Assert.Fail() + Assert.AreEqual(1, !i) + let _ = e.Current + Assert.AreEqual(1, !i) + let _ = e.Current + Assert.AreEqual(1, !i) + + if not (e.MoveNext()) then Assert.Fail() + Assert.AreEqual(2, !i) + let _ = e.Current + Assert.AreEqual(2, !i) + let _ = e.Current + Assert.AreEqual(2, !i) + + if e.MoveNext() then Assert.Fail() + Assert.AreEqual(2, !i) + CheckThrowsInvalidOperationExn (fun _ -> e.Current|>ignore) + Assert.AreEqual(2, !i) + + i := 0 + let e = ((iseq []) |> IConsumableSeq.mapi f).GetEnumerator() + if e.MoveNext() then Assert.Fail() + Assert.AreEqual(0,!i) + if e.MoveNext() then Assert.Fail() + Assert.AreEqual(0,!i) + + [] + member this.Map2WithSideEffects () = + let i = ref 0 + let f x y = i := !i + 1; x*x + let e = (IConsumableSeq.map2 f (iseq [1;2]) (iseq [1;2])).GetEnumerator() + + CheckThrowsInvalidOperationExn (fun _ -> e.Current|>ignore) + Assert.AreEqual(0, !i) + if not (e.MoveNext()) then Assert.Fail() + Assert.AreEqual(1, !i) + let _ = e.Current + Assert.AreEqual(1, !i) + let _ = e.Current + Assert.AreEqual(1, !i) + + if not (e.MoveNext()) then Assert.Fail() + Assert.AreEqual(2, !i) + let _ = e.Current + Assert.AreEqual(2, !i) + let _ = e.Current + Assert.AreEqual(2, !i) + + if e.MoveNext() then Assert.Fail() + Assert.AreEqual(2,!i) + CheckThrowsInvalidOperationExn (fun _ -> e.Current|>ignore) + Assert.AreEqual(2, !i) + + i := 0 + let e = (IConsumableSeq.map2 f (iseq []) (iseq [])).GetEnumerator() + if e.MoveNext() then Assert.Fail() + Assert.AreEqual(0,!i) + if e.MoveNext() then Assert.Fail() + Assert.AreEqual(0,!i) + + [] + member this.Mapi2WithSideEffects () = + let i = ref 0 + let f _ x y = i := !i + 1; x*x + let e = (IConsumableSeq.mapi2 f (iseq [1;2]) (iseq [1;2])).GetEnumerator() + + CheckThrowsInvalidOperationExn (fun _ -> e.Current|>ignore) + Assert.AreEqual(0, !i) + if not (e.MoveNext()) then Assert.Fail() + Assert.AreEqual(1, !i) + let _ = e.Current + Assert.AreEqual(1, !i) + let _ = e.Current + Assert.AreEqual(1, !i) + + if not (e.MoveNext()) then Assert.Fail() + Assert.AreEqual(2, !i) + let _ = e.Current + Assert.AreEqual(2, !i) + let _ = e.Current + Assert.AreEqual(2, !i) + + if e.MoveNext() then Assert.Fail() + Assert.AreEqual(2,!i) + CheckThrowsInvalidOperationExn (fun _ -> e.Current|>ignore) + Assert.AreEqual(2, !i) + + i := 0 + let e = (IConsumableSeq.mapi2 f (iseq []) (iseq [])).GetEnumerator() + if e.MoveNext() then Assert.Fail() + Assert.AreEqual(0,!i) + if e.MoveNext() then Assert.Fail() + Assert.AreEqual(0,!i) + + [] + member this.Collect() = + // integer IConsumableSeq + let funcInt x = iseq [x+1] + let resultInt = IConsumableSeq.collect funcInt (iseq { 1..10 }) + + let expectedint = iseq <| seq {2..11} + + VerifySeqsEqual expectedint resultInt + +//#if !FX_NO_CHAR_PARSE +// // string IConsumableSeq +// let funcStr (y:string) = y+"ist" + +// let resultStr = IConsumableSeq.collect funcStr (iseq ["L"]) + + +// let expectedSeq = iseq ['L';'i';'s';'t'] + +// VerifySeqsEqual expectedSeq resultStr +//#endif + // empty IConsumableSeq + let resultEpt = IConsumableSeq.collect funcInt IConsumableSeq.empty + VerifySeqsEqual IConsumableSeq.empty resultEpt + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.collect funcInt nullSeq |> ignore) + + () + + [] + member this.Mapi() = + + // integer IConsumableSeq + let funcInt x y = x+y + let resultInt = IConsumableSeq.mapi funcInt (iseq { 10..2..20 } ) + let expectedint = iseq [10;13;16;19;22;25] + + VerifySeqsEqual expectedint resultInt + + // string IConsumableSeq + let funcStr (x:int) (y:string) =x+y.Length + + let resultStr = IConsumableSeq.mapi funcStr (iseq ["Lists"; "Are"; "Commonly" ; "List" ]) + let expectedStr = iseq [5;4;10;7] + + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.mapi funcInt IConsumableSeq.empty + VerifySeqsEqual IConsumableSeq.empty resultEpt + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.mapi funcInt nullSeq |> ignore) + + () + + [] + member this.Mapi2() = + // integer IConsumableSeq + let funcInt x y z = x+y+z + let resultInt = IConsumableSeq.mapi2 funcInt (iseq { 1..10 }) (iseq {2..2..20}) + let expectedint = iseq [3;7;11;15;19;23;27;31;35;39] + + VerifySeqsEqual expectedint resultInt + + // string IConsumableSeq + let funcStr (x:int) (y:int) (z:string) = x+y+z.Length + let resultStr = IConsumableSeq.mapi2 funcStr (iseq[3;6;9;11]) (iseq ["Lists"; "Are"; "Commonly" ; "List" ]) + let expectedSeq = iseq [8;10;19;18] + + VerifySeqsEqual expectedSeq resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.mapi2 funcInt IConsumableSeq.empty IConsumableSeq.empty + VerifySeqsEqual IConsumableSeq.empty resultEpt + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //let validSeq = iseq [1] + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.mapi2 funcInt nullSeq validSeq |> ignore) + + // len1 <> len2 + let shorterSeq = iseq <| seq { 1..10 } + let longerSeq = iseq <| seq { 2..20 } + + let testSeqLengths seq1 seq2 = + let f x y z = x + y + z + IConsumableSeq.mapi2 f seq1 seq2 + + VerifySeqsEqual (iseq [3;6;9;12;15;18;21;24;27;30]) (testSeqLengths shorterSeq longerSeq) + VerifySeqsEqual (iseq [3;6;9;12;15;18;21;24;27;30]) (testSeqLengths longerSeq shorterSeq) + + [] + member this.Indexed() = + + // integer IConsumableSeq + let resultInt = IConsumableSeq.indexed (iseq { 10..2..20 }) + let expectedint = iseq [(0,10);(1,12);(2,14);(3,16);(4,18);(5,20)] + + VerifySeqsEqual expectedint resultInt + + // string IConsumableSeq + let resultStr = IConsumableSeq.indexed (iseq ["Lists"; "Are"; "Commonly"; "List" ]) + let expectedStr = iseq [(0,"Lists");(1,"Are");(2,"Commonly");(3,"List")] + + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.indexed IConsumableSeq.empty + VerifySeqsEqual IConsumableSeq.empty resultEpt + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.indexed nullSeq |> ignore) + + () + + [] + member this.Max() = + // integer IConsumableSeq + let resultInt = IConsumableSeq.max (iseq { 10..20 } ) + + Assert.AreEqual(20,resultInt) + + // string IConsumableSeq + + let resultStr = IConsumableSeq.max (iseq ["Lists"; "Are"; "MaxString" ; "List" ]) + Assert.AreEqual("MaxString",resultStr) + + // empty IConsumableSeq + CheckThrowsArgumentException(fun () -> IConsumableSeq.max ( IConsumableSeq.empty : iseq) |> ignore) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.max nullSeq |> ignore) + + () + + [] + member this.MaxBy() = + + // integer IConsumableSeq + let funcInt x = x % 8 + let resultInt = IConsumableSeq.maxBy funcInt (iseq { 2..2..20 } ) + Assert.AreEqual(6,resultInt) + + // string IConsumableSeq + let funcStr (x:string) =x.Length + let resultStr = IConsumableSeq.maxBy funcStr (iseq ["Lists"; "Are"; "Commonly" ; "List" ]) + Assert.AreEqual("Commonly",resultStr) + + // empty IConsumableSeq + CheckThrowsArgumentException (fun () -> IConsumableSeq.maxBy funcInt (IConsumableSeq.empty : iseq) |> ignore) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () ->IConsumableSeq.maxBy funcInt nullSeq |> ignore) + + () + + [] + member this.MinBy() = + + // integer IConsumableSeq + let funcInt x = x % 8 + let resultInt = IConsumableSeq.minBy funcInt (iseq { 2..2..20 } ) + Assert.AreEqual(8,resultInt) + + // string IConsumableSeq + let funcStr (x:string) =x.Length + let resultStr = IConsumableSeq.minBy funcStr (iseq ["Lists"; "Are"; "Commonly" ; "List" ]) + Assert.AreEqual("Are",resultStr) + + // empty IConsumableSeq + CheckThrowsArgumentException (fun () -> IConsumableSeq.minBy funcInt (IConsumableSeq.empty : iseq) |> ignore) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () ->IConsumableSeq.minBy funcInt nullSeq |> ignore) + + () + + + [] + member this.Min() = + + // integer IConsumableSeq + let resultInt = IConsumableSeq.min (iseq { 10..20 } ) + Assert.AreEqual(10,resultInt) + + // string IConsumableSeq + let resultStr = IConsumableSeq.min (iseq ["Lists"; "Are"; "minString" ; "List" ]) + Assert.AreEqual("Are",resultStr) + + // empty IConsumableSeq + CheckThrowsArgumentException (fun () -> IConsumableSeq.min (IConsumableSeq.empty : iseq) |> ignore) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.min nullSeq |> ignore) + + () + + [] + member this.Item() = + // integer IConsumableSeq + let resultInt = IConsumableSeq.item 3 (iseq { 10..20 }) + Assert.AreEqual(13, resultInt) + + // string IConsumableSeq + let resultStr = IConsumableSeq.item 2 (iseq ["Lists"; "Are"; "Cool" ; "List" ]) + Assert.AreEqual("Cool", resultStr) + + // empty IConsumableSeq + CheckThrowsArgumentException(fun () -> IConsumableSeq.item 0 (IConsumableSeq.empty : iseq) |> ignore) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () ->IConsumableSeq.item 3 nullSeq |> ignore) + + // Negative index + for i = -1 downto -10 do + CheckThrowsArgumentException (fun () -> IConsumableSeq.item i (iseq { 10 .. 20 }) |> ignore) + + // Out of range + for i = 11 to 20 do + CheckThrowsArgumentException (fun () -> IConsumableSeq.item i (iseq { 10 .. 20 }) |> ignore) + + [] + member this.``item should fail with correct number of missing elements``() = + try + IConsumableSeq.item 0 (iseq (Array.zeroCreate 0)) |> ignore + failwith "error expected" + with + | exn when exn.Message.Contains("seq was short by 1 element") -> () + + try + IConsumableSeq.item 2 (iseq (Array.zeroCreate 0)) |> ignore + failwith "error expected" + with + | exn when exn.Message.Contains("seq was short by 3 elements") -> () + + [] + member this.Of_Array() = + // integer IConsumableSeq + let resultInt = IConsumableSeq.ofArray [|1..10|] + let expectedInt = {1..10} + + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + let resultStr = IConsumableSeq.ofArray [|"Lists"; "Are"; "ofArrayString" ; "List" |] + let expectedStr = iseq ["Lists"; "Are"; "ofArrayString" ; "List" ] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.ofArray [| |] + VerifySeqsEqual resultEpt IConsumableSeq.empty + + () + + [] + member this.Of_List() = + // integer IConsumableSeq + let resultInt = IConsumableSeq.ofList [1..10] + let expectedInt = {1..10} + + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + + let resultStr =IConsumableSeq.ofList ["Lists"; "Are"; "ofListString" ; "List" ] + let expectedStr = iseq ["Lists"; "Are"; "ofListString" ; "List" ] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.ofList [] + VerifySeqsEqual resultEpt IConsumableSeq.empty + () + + + [] + member this.Pairwise() = + // integer IConsumableSeq + let resultInt = IConsumableSeq.pairwise (iseq {1..3}) + + let expectedInt = iseq [1,2;2,3] + + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + let resultStr =IConsumableSeq.pairwise (iseq ["str1"; "str2";"str3" ]) + let expectedStr = iseq ["str1","str2";"str2","str3"] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.pairwise (iseq [] ) + VerifySeqsEqual resultEpt IConsumableSeq.empty + + () + + [] + member this.Reduce() = + + // integer IConsumableSeq + let resultInt = IConsumableSeq.reduce (fun x y -> x/y) (iseq [5*4*3*2; 4;3;2;1]) + Assert.AreEqual(5,resultInt) + + // string IConsumableSeq + let resultStr = IConsumableSeq.reduce (fun (x:string) (y:string) -> x.Remove(0,y.Length)) (iseq ["ABCDE";"A"; "B"; "C" ; "D" ]) + Assert.AreEqual("E",resultStr) + + // empty IConsumableSeq + CheckThrowsArgumentException (fun () -> IConsumableSeq.reduce (fun x y -> x/y) IConsumableSeq.empty |> ignore) + + //// null IConsumableSeq + //let nullSeq : iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.reduce (fun (x:string) (y:string) -> x.Remove(0,y.Length)) nullSeq |> ignore) + () + + [] + member this.ReduceBack() = + // int IConsumableSeq + let funcInt x y = x - y + let IntSeq = iseq <| seq { 1..4 } + let reduceInt = IConsumableSeq.reduceBack funcInt IntSeq + Assert.AreEqual((1-(2-(3-4))), reduceInt) + + // string IConsumableSeq + let funcStr (x:string) (y:string) = y.Remove(0,x.Length) + let strSeq = iseq [ "A"; "B"; "C"; "D" ; "ABCDE" ] + let reduceStr = IConsumableSeq.reduceBack funcStr strSeq + Assert.AreEqual("E", reduceStr) + + // string IConsumableSeq + let funcStr2 elem acc = sprintf "%s%s" elem acc + let strSeq2 = iseq [ "A" ] + let reduceStr2 = IConsumableSeq.reduceBack funcStr2 strSeq2 + Assert.AreEqual("A", reduceStr2) + + // Empty IConsumableSeq + CheckThrowsArgumentException (fun () -> IConsumableSeq.reduceBack funcInt IConsumableSeq.empty |> ignore) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.reduceBack funcInt nullSeq |> ignore) + + () + + [] + member this.Rev() = + // integer IConsumableSeq + let resultInt = IConsumableSeq.rev (iseq [5;4;3;2;1]) + VerifySeqsEqual (iseq[1;2;3;4;5]) resultInt + + // string IConsumableSeq + let resultStr = IConsumableSeq.rev (iseq ["A"; "B"; "C" ; "D" ]) + VerifySeqsEqual (iseq["D";"C";"B";"A"]) resultStr + + // empty IConsumableSeq + VerifySeqsEqual IConsumableSeq.empty (IConsumableSeq.rev IConsumableSeq.empty) + + //// null IConsumableSeq + //let nullSeq : iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.rev nullSeq |> ignore) + () + + [] + member this.Scan() = + // integer IConsumableSeq + let funcInt x y = x+y + let resultInt = IConsumableSeq.scan funcInt 9 (iseq {1..10}) + let expectedInt = iseq [9;10;12;15;19;24;30;37;45;54;64] + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + let funcStr x y = x+y + let resultStr =IConsumableSeq.scan funcStr "x" (iseq ["str1"; "str2";"str3" ]) + + let expectedStr = iseq ["x";"xstr1"; "xstr1str2";"xstr1str2str3"] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.scan funcInt 5 IConsumableSeq.empty + + VerifySeqsEqual resultEpt (iseq [ 5]) + + //// null IConsumableSeq + //let seqNull:iseq<'a> = null + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.scan funcInt 5 seqNull |> ignore) + () + + [] + member this.ScanBack() = + // integer IConsumableSeq + let funcInt x y = x+y + let resultInt = IConsumableSeq.scanBack funcInt (iseq { 1..10 }) 9 + let expectedInt = iseq [64;63;61;58;54;49;43;36;28;19;9] + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + let funcStr x y = x+y + let resultStr = IConsumableSeq.scanBack funcStr (iseq ["A";"B";"C";"D"]) "X" + let expectedStr = iseq ["ABCDX";"BCDX";"CDX";"DX";"X"] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.scanBack funcInt IConsumableSeq.empty 5 + let expectedEpt = iseq [5] + VerifySeqsEqual expectedEpt resultEpt + + //// null IConsumableSeq + //let seqNull:iseq<'a> = null + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.scanBack funcInt seqNull 5 |> ignore) + + // exception cases + let funcEx x (s:'State) = raise <| new System.FormatException() : 'State + // calling scanBack with funcEx does not throw + let resultEx = IConsumableSeq.scanBack funcEx (iseq <| seq {1..10}) 0 + // reading from resultEx throws + CheckThrowsFormatException(fun() -> IConsumableSeq.head resultEx |> ignore) + + // Result consumes entire input sequence as soon as it is accesses an element + let i = ref 0 + let funcState x s = (i := !i + x); x+s + let resultState = IConsumableSeq.scanBack funcState (iseq <| seq {1..3}) 0 + Assert.AreEqual(0, !i) + use e = resultState.GetEnumerator() + Assert.AreEqual(6, !i) + + () + + [] + member this.Singleton() = + // integer IConsumableSeq + let resultInt = IConsumableSeq.singleton 1 + + let expectedInt = iseq [1] + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + let resultStr =IConsumableSeq.singleton "str1" + let expectedStr = iseq ["str1"] + VerifySeqsEqual expectedStr resultStr + + // null IConsumableSeq + let resultNull = IConsumableSeq.singleton null + let expectedNull = iseq [null] + VerifySeqsEqual expectedNull resultNull + () + + + [] + member this.Skip() = + + // integer IConsumableSeq + let resultInt = IConsumableSeq.skip 2 (iseq [1;2;3;4]) + let expectedInt = iseq [3;4] + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + let resultStr =IConsumableSeq.skip 2 (iseq ["str1";"str2";"str3";"str4"]) + let expectedStr = iseq ["str3";"str4"] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.skip 0 IConsumableSeq.empty + VerifySeqsEqual resultEpt IConsumableSeq.empty + + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.skip 1 null |> ignore) + () + + [] + member this.Skip_While() = + + // integer IConsumableSeq + let funcInt x = (x < 3) + let resultInt = IConsumableSeq.skipWhile funcInt (iseq [1;2;3;4;5;6]) + let expectedInt = iseq [3;4;5;6] + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + let funcStr (x:string) = x.Contains(".") + let resultStr =IConsumableSeq.skipWhile funcStr (iseq [".";"asdfasdf.asdfasdf";"";"";"";"";"";"";"";"";""]) + let expectedStr = iseq ["";"";"";"";"";"";"";"";""] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.skipWhile funcInt IConsumableSeq.empty + VerifySeqsEqual resultEpt IConsumableSeq.empty + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.skipWhile funcInt null |> ignore) + () + + [] + member this.Sort() = + + // integer IConsumableSeq + let resultInt = IConsumableSeq.sort (iseq [1;3;2;4;6;5;7]) + let expectedInt = {1..7} + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + + let resultStr =IConsumableSeq.sort (iseq ["str1";"str3";"str2";"str4"]) + let expectedStr = iseq ["str1";"str2";"str3";"str4"] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.sort IConsumableSeq.empty + VerifySeqsEqual resultEpt IConsumableSeq.empty + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.sort null |> ignore) + () + + [] + member this.SortBy() = + + // integer IConsumableSeq + let funcInt x = Math.Abs(x-5) + let resultInt = IConsumableSeq.sortBy funcInt (iseq [1;2;4;5;7]) + let expectedInt = iseq [5;4;7;2;1] + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + let funcStr (x:string) = x.IndexOf("key") + let resultStr =IConsumableSeq.sortBy funcStr (iseq ["st(key)r";"str(key)";"s(key)tr";"(key)str"]) + + let expectedStr = iseq ["(key)str";"s(key)tr";"st(key)r";"str(key)"] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.sortBy funcInt IConsumableSeq.empty + VerifySeqsEqual resultEpt IConsumableSeq.empty + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.sortBy funcInt null |> ignore) + () + + [] + member this.SortDescending() = + + // integer IConsumableSeq + let resultInt = IConsumableSeq.sortDescending (iseq [1;3;2;Int32.MaxValue;4;6;Int32.MinValue;5;7;0]) + let expectedInt = iseq <| seq { + yield Int32.MaxValue; + yield! iseq{ 7..-1..0 } + yield Int32.MinValue + } + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + + let resultStr = IConsumableSeq.sortDescending (iseq ["str1";null;"str3";"";"Str1";"str2";"str4"]) + let expectedStr = iseq ["str4";"str3";"str2";"str1";"Str1";"";null] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.sortDescending IConsumableSeq.empty + VerifySeqsEqual resultEpt IConsumableSeq.empty + + // tuple IConsumableSeq + let tupSeq = (iseq[(2,"a");(1,"d");(1,"b");(1,"a");(2,"x");(2,"b");(1,"x")]) + let resultTup = IConsumableSeq.sortDescending tupSeq + let expectedTup = (iseq[(2,"x");(2,"b");(2,"a");(1,"x");(1,"d");(1,"b");(1,"a")]) + VerifySeqsEqual expectedTup resultTup + + // float IConsumableSeq + let minFloat,maxFloat,epsilon = System.Double.MinValue,System.Double.MaxValue,System.Double.Epsilon + let floatSeq = iseq [0.0; 0.5; 2.0; 1.5; 1.0; minFloat;maxFloat;epsilon;-epsilon] + let resultFloat = IConsumableSeq.sortDescending floatSeq + let expectedFloat = iseq [maxFloat; 2.0; 1.5; 1.0; 0.5; epsilon; 0.0; -epsilon; minFloat; ] + VerifySeqsEqual expectedFloat resultFloat + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.sort null |> ignore) + () + + [] + member this.SortByDescending() = + + // integer IConsumableSeq + let funcInt x = Math.Abs(x-5) + let resultInt = IConsumableSeq.sortByDescending funcInt (iseq [1;2;4;5;7]) + let expectedInt = iseq [1;2;7;4;5] + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + let funcStr (x:string) = x.IndexOf("key") + let resultStr =IConsumableSeq.sortByDescending funcStr (iseq ["st(key)r";"str(key)";"s(key)tr";"(key)str"]) + + let expectedStr = iseq ["str(key)";"st(key)r";"s(key)tr";"(key)str"] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.sortByDescending funcInt IConsumableSeq.empty + VerifySeqsEqual resultEpt IConsumableSeq.empty + + // tuple IConsumableSeq + let tupSeq = (iseq[(2,"a");(1,"d");(1,"b");(1,"a");(2,"x");(2,"b");(1,"x")]) + let resultTup = IConsumableSeq.sortByDescending snd tupSeq + let expectedTup = (iseq[(2,"x");(1,"x");(1,"d");(1,"b");(2,"b");(2,"a");(1,"a")]) + VerifySeqsEqual expectedTup resultTup + + // float IConsumableSeq + let minFloat,maxFloat,epsilon = System.Double.MinValue,System.Double.MaxValue,System.Double.Epsilon + let floatSeq = iseq [0.0; 0.5; 2.0; 1.5; 1.0; minFloat;maxFloat;epsilon;-epsilon] + let resultFloat = IConsumableSeq.sortByDescending id floatSeq + let expectedFloat = iseq [maxFloat; 2.0; 1.5; 1.0; 0.5; epsilon; 0.0; -epsilon; minFloat; ] + VerifySeqsEqual expectedFloat resultFloat + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.sortByDescending funcInt null |> ignore) + () + + member this.SortWith() = + + // integer IConsumableSeq + let intComparer a b = compare (a%3) (b%3) + let resultInt = IConsumableSeq.sortWith intComparer (iseq <| seq {0..10}) + let expectedInt = iseq [0;3;6;9;1;4;7;10;2;5;8] + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + let resultStr = IConsumableSeq.sortWith compare (iseq ["str1";"str3";"str2";"str4"]) + let expectedStr = iseq ["str1";"str2";"str3";"str4"] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.sortWith intComparer IConsumableSeq.empty + VerifySeqsEqual resultEpt IConsumableSeq.empty + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.sortWith intComparer null |> ignore) + + () + + [] + member this.Sum() = + + // integer IConsumableSeq + let resultInt = IConsumableSeq.sum (iseq [1..10]) + Assert.AreEqual(55,resultInt) + + // float32 IConsumableSeq + let floatSeq = (iseq [ 1.2f;3.5f;6.7f ]) + let resultFloat = IConsumableSeq.sum floatSeq + if resultFloat <> 11.4f then Assert.Fail() + + // double IConsumableSeq + let doubleSeq = (iseq [ 1.0;8.0 ]) + let resultDouble = IConsumableSeq.sum doubleSeq + if resultDouble <> 9.0 then Assert.Fail() + + // decimal IConsumableSeq + let decimalSeq = (iseq [ 0M;19M;19.03M ]) + let resultDecimal = IConsumableSeq.sum decimalSeq + if resultDecimal <> 38.03M then Assert.Fail() + + + // empty float32 IConsumableSeq + let emptyFloatSeq = IConsumableSeq.empty + let resultEptFloat = IConsumableSeq.sum emptyFloatSeq + if resultEptFloat <> 0.0f then Assert.Fail() + + // empty double IConsumableSeq + let emptyDoubleSeq = IConsumableSeq.empty + let resultDouEmp = IConsumableSeq.sum emptyDoubleSeq + if resultDouEmp <> 0.0 then Assert.Fail() + + // empty decimal IConsumableSeq + let emptyDecimalSeq = IConsumableSeq.empty + let resultDecEmp = IConsumableSeq.sum emptyDecimalSeq + if resultDecEmp <> 0M then Assert.Fail() + + () + + [] + member this.SumBy() = + + // integer IConsumableSeq + let resultInt = IConsumableSeq.sumBy int (iseq [1..10]) + Assert.AreEqual(55,resultInt) + + // float32 IConsumableSeq + let floatSeq = (iseq [ 1.2f;3.5f;6.7f ]) + let resultFloat = IConsumableSeq.sumBy float32 floatSeq + if resultFloat <> 11.4f then Assert.Fail() + + // double IConsumableSeq + let doubleSeq = (iseq [ 1.0;8.0 ]) + let resultDouble = IConsumableSeq.sumBy double doubleSeq + if resultDouble <> 9.0 then Assert.Fail() + + // decimal IConsumableSeq + let decimalSeq = (iseq [ 0M;19M;19.03M ]) + let resultDecimal = IConsumableSeq.sumBy decimal decimalSeq + if resultDecimal <> 38.03M then Assert.Fail() + + // empty float32 IConsumableSeq + let emptyFloatSeq = IConsumableSeq.empty + let resultEptFloat = IConsumableSeq.sumBy float32 emptyFloatSeq + if resultEptFloat <> 0.0f then Assert.Fail() + + // empty double IConsumableSeq + let emptyDoubleSeq = IConsumableSeq.empty + let resultDouEmp = IConsumableSeq.sumBy double emptyDoubleSeq + if resultDouEmp <> 0.0 then Assert.Fail() + + // empty decimal IConsumableSeq + let emptyDecimalSeq = IConsumableSeq.empty + let resultDecEmp = IConsumableSeq.sumBy decimal emptyDecimalSeq + if resultDecEmp <> 0M then Assert.Fail() + + () + + [] + member this.Take() = + // integer IConsumableSeq + + let resultInt = IConsumableSeq.take 3 (iseq [1;2;4;5;7]) + + let expectedInt = iseq [1;2;4] + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + + let resultStr =IConsumableSeq.take 2(iseq ["str1";"str2";"str3";"str4"]) + + let expectedStr = iseq ["str1";"str2"] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.take 0 IConsumableSeq.empty + + VerifySeqsEqual resultEpt IConsumableSeq.empty + + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.take 1 null |> ignore) + () + + [] + member this.takeWhile() = + // integer IConsumableSeq + let funcInt x = (x < 6) + let resultInt = IConsumableSeq.takeWhile funcInt (iseq [1;2;4;5;6;7]) + + let expectedInt = iseq [1;2;4;5] + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + let funcStr (x:string) = (x.Length < 4) + let resultStr =IConsumableSeq.takeWhile funcStr (iseq ["a"; "ab"; "abc"; "abcd"; "abcde"]) + + let expectedStr = iseq ["a"; "ab"; "abc"] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.takeWhile funcInt IConsumableSeq.empty + VerifySeqsEqual resultEpt IConsumableSeq.empty + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.takeWhile funcInt null |> ignore) + () + + [] + member this.ToArray() = + // integer IConsumableSeq + let resultInt = IConsumableSeq.toArray(iseq [1;2;4;5;7]) + + let expectedInt = [|1;2;4;5;7|] + Assert.AreEqual(expectedInt,resultInt) + + // string IConsumableSeq + let resultStr =IConsumableSeq.toArray (iseq ["str1";"str2";"str3"]) + + let expectedStr = [|"str1";"str2";"str3"|] + Assert.AreEqual(expectedStr,resultStr) + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.toArray IConsumableSeq.empty + Assert.AreEqual([||],resultEpt) + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.toArray null |> ignore) + () + + [] + member this.ToArrayFromICollection() = + let inputCollection = ResizeArray(iseq [1;2;4;5;7]) + let resultInt = IConsumableSeq.toArray((iseq inputCollection)) + let expectedInt = [|1;2;4;5;7|] + Assert.AreEqual(expectedInt,resultInt) + + [] + member this.ToArrayEmptyInput() = + let resultInt = IConsumableSeq.toArray(IConsumableSeq.empty) + let expectedInt = Array.empty + Assert.AreEqual(expectedInt,resultInt) + + [] + member this.ToArrayFromArray() = + let resultInt = IConsumableSeq.toArray((iseq [|1;2;4;5;7|])) + let expectedInt = [|1;2;4;5;7|] + Assert.AreEqual(expectedInt,resultInt) + + [] + member this.ToArrayFromList() = + let resultInt = IConsumableSeq.toArray((iseq [1;2;4;5;7])) + let expectedInt = [|1;2;4;5;7|] + Assert.AreEqual(expectedInt,resultInt) + + [] + member this.ToList() = + // integer IConsumableSeq + let resultInt = IConsumableSeq.toList (iseq [1;2;4;5;7]) + let expectedInt = [1;2;4;5;7] + Assert.AreEqual(expectedInt,resultInt) + + // string IConsumableSeq + let resultStr =IConsumableSeq.toList (iseq ["str1";"str2";"str3"]) + let expectedStr = ["str1";"str2";"str3"] + Assert.AreEqual(expectedStr,resultStr) + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.toList IConsumableSeq.empty + Assert.AreEqual([],resultEpt) + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.toList null |> ignore) + () + + [] + member this.Truncate() = + // integer IConsumableSeq + let resultInt = IConsumableSeq.truncate 3 (iseq [1;2;4;5;7]) + let expectedInt = [1;2;4] + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + let resultStr =IConsumableSeq.truncate 2 (iseq ["str1";"str2";"str3"]) + let expectedStr = ["str1";"str2"] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.truncate 0 IConsumableSeq.empty + VerifySeqsEqual IConsumableSeq.empty resultEpt + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.truncate 1 null |> ignore) + + // negative count + VerifySeqsEqual IConsumableSeq.empty <| IConsumableSeq.truncate -1 (iseq [1;2;4;5;7]) + VerifySeqsEqual IConsumableSeq.empty <| IConsumableSeq.truncate System.Int32.MinValue (iseq [1;2;4;5;7]) + + () + + [] + member this.tryFind() = + // integer IConsumableSeq + let resultInt = IConsumableSeq.tryFind (fun x -> (x%2=0)) (iseq [1;2;4;5;7]) + Assert.AreEqual(Some(2), resultInt) + + // integer IConsumableSeq - None + let resultInt = IConsumableSeq.tryFind (fun x -> (x%2=0)) (iseq [1;3;5;7]) + Assert.AreEqual(None, resultInt) + + // string IConsumableSeq + let resultStr = IConsumableSeq.tryFind (fun (x:string) -> x.Contains("2")) (iseq ["str1";"str2";"str3"]) + Assert.AreEqual(Some("str2"),resultStr) + + // string IConsumableSeq - None + let resultStr = IConsumableSeq.tryFind (fun (x:string) -> x.Contains("2")) (iseq ["str1";"str4";"str3"]) + Assert.AreEqual(None,resultStr) + + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.tryFind (fun x -> (x%2=0)) IConsumableSeq.empty + Assert.AreEqual(None,resultEpt) + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.tryFind (fun x -> (x%2=0)) null |> ignore) + () + + [] + member this.TryFindBack() = + // integer IConsumableSeq + let resultInt = IConsumableSeq.tryFindBack (fun x -> (x%2=0)) (iseq [1;2;4;5;7]) + Assert.AreEqual(Some 4, resultInt) + + // integer IConsumableSeq - None + let resultInt = IConsumableSeq.tryFindBack (fun x -> (x%2=0)) (iseq [1;3;5;7]) + Assert.AreEqual(None, resultInt) + + // string IConsumableSeq + let resultStr = IConsumableSeq.tryFindBack (fun (x:string) -> x.Contains("2")) (iseq ["str1";"str2";"str2x";"str3"]) + Assert.AreEqual(Some "str2x", resultStr) + + // string IConsumableSeq - None + let resultStr = IConsumableSeq.tryFindBack (fun (x:string) -> x.Contains("2")) (iseq ["str1";"str4";"str3"]) + Assert.AreEqual(None, resultStr) + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.tryFindBack (fun x -> (x%2=0)) IConsumableSeq.empty + Assert.AreEqual(None, resultEpt) + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.tryFindBack (fun x -> (x%2=0)) null |> ignore) + () + + [] + member this.TryFindIndex() = + + // integer IConsumableSeq + let resultInt = IConsumableSeq.tryFindIndex (fun x -> (x % 5 = 0)) (iseq [8; 9; 10]) + Assert.AreEqual(Some(2), resultInt) + + // integer IConsumableSeq - None + let resultInt = IConsumableSeq.tryFindIndex (fun x -> (x % 5 = 0)) (iseq [9;3;11]) + Assert.AreEqual(None, resultInt) + + // string IConsumableSeq + let resultStr = IConsumableSeq.tryFindIndex (fun (x:string) -> x.Contains("2")) (iseq ["str1"; "str2"; "str3"]) + Assert.AreEqual(Some(1),resultStr) + + // string IConsumableSeq - None + let resultStr = IConsumableSeq.tryFindIndex (fun (x:string) -> x.Contains("2")) (iseq ["str1"; "str4"; "str3"]) + Assert.AreEqual(None,resultStr) + + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.tryFindIndex (fun x -> (x%2=0)) IConsumableSeq.empty + Assert.AreEqual(None, resultEpt) + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.tryFindIndex (fun x -> (x % 2 = 0)) null |> ignore) + () + + [] + member this.TryFindIndexBack() = + + // integer IConsumableSeq + let resultInt = IConsumableSeq.tryFindIndexBack (fun x -> (x % 5 = 0)) (iseq [5; 9; 10; 12]) + Assert.AreEqual(Some(2), resultInt) + + // integer IConsumableSeq - None + let resultInt = IConsumableSeq.tryFindIndexBack (fun x -> (x % 5 = 0)) (iseq [9;3;11]) + Assert.AreEqual(None, resultInt) + + // string IConsumableSeq + let resultStr = IConsumableSeq.tryFindIndexBack (fun (x:string) -> x.Contains("2")) (iseq ["str1"; "str2"; "str2x"; "str3"]) + Assert.AreEqual(Some(2), resultStr) + + // string IConsumableSeq - None + let resultStr = IConsumableSeq.tryFindIndexBack (fun (x:string) -> x.Contains("2")) (iseq ["str1"; "str4"; "str3"]) + Assert.AreEqual(None, resultStr) + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.tryFindIndexBack (fun x -> (x%2=0)) IConsumableSeq.empty + Assert.AreEqual(None, resultEpt) + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.tryFindIndexBack (fun x -> (x % 2 = 0)) null |> ignore) + () + + [] + member this.Unfold() = + // integer IConsumableSeq + + let resultInt = IConsumableSeq.unfold (fun x -> if x = 1 then Some(7,2) else None) 1 + + VerifySeqsEqual (iseq [7]) resultInt + + // string IConsumableSeq + let resultStr =IConsumableSeq.unfold (fun (x:string) -> if x.Contains("unfold") then Some("a","b") else None) "unfold" + VerifySeqsEqual (iseq ["a"]) resultStr + () + + + [] + member this.Windowed() = + + let testWindowed config = + try + config.InputSeq + |> IConsumableSeq.windowed config.WindowSize + |> VerifySeqsEqual config.ExpectedSeq + with + | _ when Option.isNone config.Exception -> Assert.Fail() + | e when e.GetType() = (Option.get config.Exception) -> () + | _ -> Assert.Fail() + + { + InputSeq = iseq [1..10] + WindowSize = 1 + ExpectedSeq = iseq <| seq { for i in 1..10 do yield [| i |] } + Exception = None + } |> testWindowed + { + InputSeq = iseq [1..10] + WindowSize = 5 + ExpectedSeq = iseq <| seq { for i in 1..6 do yield [| i; i+1; i+2; i+3; i+4 |] } + Exception = None + } |> testWindowed + { + InputSeq = iseq [1..10] + WindowSize = 10 + ExpectedSeq = iseq <| seq { yield [| 1 .. 10 |] } + Exception = None + } |> testWindowed + { + InputSeq = iseq [1..10] + WindowSize = 25 + ExpectedSeq = IConsumableSeq.empty + Exception = None + } |> testWindowed + { + InputSeq = iseq ["str1";"str2";"str3";"str4"] + WindowSize = 2 + ExpectedSeq = iseq [ [|"str1";"str2"|];[|"str2";"str3"|];[|"str3";"str4"|]] + Exception = None + } |> testWindowed + { + InputSeq = IConsumableSeq.empty + WindowSize = 2 + ExpectedSeq = IConsumableSeq.empty + Exception = None + } |> testWindowed + //{ + // InputSeq = null + // WindowSize = 2 + // ExpectedSeq = IConsumableSeq.empty + // Exception = Some typeof + //} |> testWindowed + { + InputSeq = iseq [1..10] + WindowSize = 0 + ExpectedSeq = IConsumableSeq.empty + Exception = Some typeof + } |> testWindowed + + () + + [] + member this.Zip() = + + // integer IConsumableSeq + let resultInt = IConsumableSeq.zip (iseq [1..7]) (iseq [11..17]) + let expectedInt = + iseq <| seq { for i in 1..7 do + yield i, i+10 } + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + let resultStr =IConsumableSeq.zip (iseq ["str3";"str4"]) (iseq ["str1";"str2"]) + let expectedStr = iseq ["str3","str1";"str4","str2"] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.zip IConsumableSeq.empty IConsumableSeq.empty + VerifySeqsEqual IConsumableSeq.empty resultEpt + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.zip null null |> ignore) + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.zip null (iseq [1..7]) |> ignore) + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.zip (iseq [1..7]) null |> ignore) + () + + [] + member this.Zip3() = + // integer IConsumableSeq + let resultInt = IConsumableSeq.zip3 (iseq [1..7]) (iseq [11..17]) (iseq [21..27]) + let expectedInt = + iseq <| seq { for i in 1..7 do + yield i, (i + 10), (i + 20) } + VerifySeqsEqual expectedInt resultInt + + // string IConsumableSeq + let resultStr =IConsumableSeq.zip3 (iseq ["str1";"str2"]) (iseq ["str11";"str12"]) (iseq ["str21";"str22"]) + let expectedStr = iseq ["str1","str11","str21";"str2","str12","str22" ] + VerifySeqsEqual expectedStr resultStr + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.zip3 IConsumableSeq.empty IConsumableSeq.empty IConsumableSeq.empty + VerifySeqsEqual IConsumableSeq.empty resultEpt + + //// null IConsumableSeq + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.zip3 null null null |> ignore) + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.zip3 null (iseq [1..7]) (iseq [1..7]) |> ignore) + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.zip3 (iseq [1..7]) null (iseq [1..7]) |> ignore) + //CheckThrowsArgumentNullException(fun() -> IConsumableSeq.zip3 (iseq [1..7]) (iseq [1..7]) null |> ignore) + () + + [] + member this.tryPick() = + // integer IConsumableSeq + let resultInt = IConsumableSeq.tryPick (fun x-> if x = 1 then Some("got") else None) (iseq [1..5]) + + Assert.AreEqual(Some("got"),resultInt) + + // string IConsumableSeq + let resultStr = IConsumableSeq.tryPick (fun x-> if x = "Are" then Some("got") else None) (iseq ["Lists"; "Are"]) + Assert.AreEqual(Some("got"),resultStr) + + // empty IConsumableSeq + let resultEpt = IConsumableSeq.tryPick (fun x-> if x = 1 then Some("got") else None) IConsumableSeq.empty + Assert.IsNull(resultEpt) + + //// null IConsumableSeq + //let nullSeq : iseq<'a> = null + //let funcNull x = Some(1) + + //CheckThrowsArgumentNullException(fun () -> IConsumableSeq.tryPick funcNull nullSeq |> ignore) + + () + + [] + member this.tryItem() = + // integer IConsumableSeq + let resultInt = IConsumableSeq.tryItem 3 (iseq { 10..20 }) + Assert.AreEqual(Some(13), resultInt) + + // string IConsumableSeq + let resultStr = IConsumableSeq.tryItem 2 (iseq ["Lists"; "Are"; "Cool"; "List" ]) + Assert.AreEqual(Some("Cool"), resultStr) + + // empty IConsumableSeq + let resultEmpty = IConsumableSeq.tryItem 0 IConsumableSeq.empty + Assert.AreEqual(None, resultEmpty) + + //// null IConsumableSeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> IConsumableSeq.tryItem 3 nullSeq |> ignore) + + // Negative index + let resultNegativeIndex = IConsumableSeq.tryItem -1 (iseq { 10..20 }) + Assert.AreEqual(None, resultNegativeIndex) + + // Index greater than length + let resultIndexGreater = IConsumableSeq.tryItem 31 (iseq { 10..20 }) + Assert.AreEqual(None, resultIndexGreater) + +#endif \ No newline at end of file diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/IConsumableSeqProperties.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/IConsumableSeqProperties.fs new file mode 100644 index 00000000000..a792f456218 --- /dev/null +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/IConsumableSeqProperties.fs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +module FSharp.Core.UnitTests.FSharp_Core.Microsoft_FSharp_Collections.IConsumableSeqProperties + +open System +open System.Collections.Generic +open NUnit.Framework +open FsCheck +open Utils + +#if IConsumableSeqIsPublic + +let sortByStable<'a when 'a : comparison> (xs : 'a []) = + let indexed = xs|> IConsumableSeq.ofSeq |> IConsumableSeq.indexed + let sorted = indexed |> IConsumableSeq.sortBy snd + isStable sorted + +[] +let ``IConsumableSeq.sortBy is stable`` () = + Check.QuickThrowOnFailure sortByStable + Check.QuickThrowOnFailure sortByStable + +let sortWithStable<'a when 'a : comparison> (xs : 'a []) = + let indexed = xs |> IConsumableSeq.ofSeq |> IConsumableSeq.indexed |> Seq.toList + let sorted = indexed |> IConsumableSeq.ofSeq |> IConsumableSeq.sortWith (fun x y -> compare (snd x) (snd y)) + isStable sorted + +[] +let ``IConsumableSeq.sortWithStable is stable`` () = + Check.QuickThrowOnFailure sortWithStable + Check.QuickThrowOnFailure sortWithStable + +let distinctByStable<'a when 'a : comparison> (xs : 'a []) = + let indexed = xs|> IConsumableSeq.ofSeq |> IConsumableSeq.indexed + let sorted = indexed |> IConsumableSeq.distinctBy snd + isStable sorted + +[] +let ``IConsumableSeq.distinctBy is stable`` () = + Check.QuickThrowOnFailure distinctByStable + Check.QuickThrowOnFailure distinctByStable + +#endif \ No newline at end of file diff --git a/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs b/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs index c9738c1b8ba..1ee84dc4fd1 100644 --- a/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs +++ b/tests/FSharp.Core.UnitTests/SurfaceArea.coreclr.fs @@ -294,6 +294,193 @@ Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityC Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] Structural[T]() Microsoft.FSharp.Collections.HashIdentity: System.String ToString() Microsoft.FSharp.Collections.HashIdentity: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Int32 get_HaltedIdx() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: TResult get_Result() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void OnDispose() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void set_Result(TResult) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Int32 get_HaltedIdx() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: TResult get_Result() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Void set_Result(TResult) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Void .ctor(Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity, TState) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Void OnDispose() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: Void .ctor(Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity, TState) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Value`1[a]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Value`1[a]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Value`1[a]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Value`1[a]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Value`1[a]: Void .ctor(a) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Value`1[a]: a _1 +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: Void .ctor(a, b) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: a _1 +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: b _2 +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: Void .ctor(a, b, c) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: a _1 +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: b _2 +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: c _3 +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Value`1[a] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean Contains[T](T, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean Exists2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean ForAll2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean IsEmpty[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule: Int32 Length[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.FSharpList`1[T] ToList[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.IConsumableSeqModule+Core +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[System.Int32,a]] Indexed[a](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[a]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[T1,T2]] AllPairs[T1,T2](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T2]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[T1,T2]] Zip[T1,T2](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T2]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[TKey,Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]]] GroupByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[TKey,Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]]] GroupByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[TKey,System.Int32]] CountByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[TKey,System.Int32]] CountByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`3[T1,T2,T3]] Zip3[T1,T2,T3](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T2], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T3]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult] Collect[T,TCollection,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TCollection], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult] Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TState] ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], TState) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TState] Scan[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T[]] ChunkBySize[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T[]] SplitInto[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T[]] Windowed[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Append[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Cache[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Cast[T](System.Collections.IEnumerable) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Concat[TCollection,T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TCollection]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Delay[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] DistinctBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Distinct[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Empty[T]() +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Except[T](System.Collections.Generic.IEnumerable`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Filter[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] InitializeInfinite[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Initialize[T](Int32, Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] OfArray[T](T[]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] OfList[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] OfResizeArrayUnchecked[T](System.Collections.Generic.List`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] OfSeq[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Permute[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Replicate[T](Int32, T) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Reverse[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Singleton[T](T) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] SkipWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Skip[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] SortByDescending[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] SortDescending[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Sort[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Tail[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Take[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Truncate[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Unfold[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[V] Map2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[V] MapIndexed2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[W] Map3[T,TResult,V,W](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[V,W]]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[V]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[b] Choose[a,b](Microsoft.FSharp.Core.FSharpFunc`2[a,Microsoft.FSharp.Core.FSharpOption`1[b]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[a]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[b] MapIndexed[a,b](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[a,b]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[a]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[TResult] TryPick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFind[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryHead[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryItem[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule: System.Tuple`2[Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult],TState] MapFoldBack[T,TState,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,System.Tuple`2[TResult,TState]]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], TState) +Microsoft.FSharp.Collections.IConsumableSeqModule: System.Tuple`2[Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult],TState] MapFold[T,TState,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Tuple`2[TResult,TState]]], TState, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule: T Average[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T ExactlyOne[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T FindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Find[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Head[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Item[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Last[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Max[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Min[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T ReduceBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Sum[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: TResult Pick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: TState Fold2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TState]]], TState, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T2]) +Microsoft.FSharp.Collections.IConsumableSeqModule: TState FoldBack2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T2], TState) +Microsoft.FSharp.Collections.IConsumableSeqModule: TState FoldBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], TState) +Microsoft.FSharp.Collections.IConsumableSeqModule: TState Fold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T[] ToArray[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Void Iterate2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Void IterateIndexed2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.Unit]]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Void IterateIndexed[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Void Iterate[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) Microsoft.FSharp.Collections.ListModule: Boolean Contains[T](T, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ListModule: Boolean Exists2[T1,T2](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,System.Boolean]], Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2]) @@ -427,6 +614,55 @@ Microsoft.FSharp.Collections.MapModule: TResult Pick[TKey,T,TResult](Microsoft.F Microsoft.FSharp.Collections.MapModule: TState FoldBack[TKey,T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TKey,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], Microsoft.FSharp.Collections.FSharpMap`2[TKey,T], TState) Microsoft.FSharp.Collections.MapModule: TState Fold[TKey,T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[TKey,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]]], TState, Microsoft.FSharp.Collections.FSharpMap`2[TKey,T]) Microsoft.FSharp.Collections.MapModule: Void Iterate[TKey,T](Microsoft.FSharp.Core.FSharpFunc`2[TKey,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Collections.FSharpMap`2[TKey,T]) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Void .ctor() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.Core+NoValue: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Core+NoValue: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Core+NoValue: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Core+NoValue: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Core: Microsoft.FSharp.Collections.SeqComposition.Core+NoValue +Microsoft.FSharp.Collections.SeqComposition.Core: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Core: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Int32 HaltedIdx +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Int32 get_HaltedIdx() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: TResult Result +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: TResult get_Result() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Void .ctor(TResult) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Void set_Result(TResult) +Microsoft.FSharp.Collections.SeqComposition.ISeqConsumer: Void ListenForStopFurtherProcessing(System.Action`1[System.Int32]) +Microsoft.FSharp.Collections.SeqComposition.ISeqConsumer: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult] Transform[TResult](Microsoft.FSharp.Collections.SeqComposition.ISeqTransform`2[T,TResult]) +Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]: TResult Fold[TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]]) +Microsoft.FSharp.Collections.SeqComposition.ISeqTransform`2[T,TResult]: Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,V] Compose[V](Microsoft.FSharp.Collections.SeqComposition.ISeqConsumer, Int32, Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[TResult,V]) Microsoft.FSharp.Collections.SeqModule: Boolean Contains[T](T, System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Boolean Equals(System.Object) Microsoft.FSharp.Collections.SeqModule: Boolean Exists2[T1,T2](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,System.Boolean]], System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2]) @@ -886,7 +1122,10 @@ Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Boolean Equal Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Boolean get_CheckClose() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Int32 GenerateNext(System.Collections.Generic.IEnumerable`1[T] ByRef) Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Int32 GetHashCode() +Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Int32 Length() +Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Append(Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.Collections.Generic.IEnumerator`1[T] GetFreshEnumerator() +Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.Collections.Generic.IEnumerable`1[T] GetRaw() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.String ToString() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.Type GetType() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: T LastGenerated diff --git a/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs b/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs index 27527ff429a..e64bd957ce8 100644 --- a/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs +++ b/tests/FSharp.Core.UnitTests/SurfaceArea.net40.fs @@ -281,6 +281,68 @@ Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityC Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] Structural[T]() Microsoft.FSharp.Collections.HashIdentity: System.String ToString() Microsoft.FSharp.Collections.HashIdentity: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Int32 get_HaltedIdx() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: TResult get_Result() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void OnDispose() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void set_Result(TResult) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Int32 get_HaltedIdx() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: TResult get_Result() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Void set_Result(TResult) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: Void .ctor(a, b) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: a _1 +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: b _2 +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean Contains[T](T, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.IConsumableSeqModule+Core +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] OfSeq[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] SortByDescending[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] SortDescending[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule: T Average[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Max[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Min[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Sum[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) Microsoft.FSharp.Collections.ListModule: Boolean Contains[T](T, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ListModule: Boolean Exists2[T1,T2](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,System.Boolean]], Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2]) @@ -414,6 +476,55 @@ Microsoft.FSharp.Collections.MapModule: TResult Pick[TKey,T,TResult](Microsoft.F Microsoft.FSharp.Collections.MapModule: TState FoldBack[TKey,T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TKey,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], Microsoft.FSharp.Collections.FSharpMap`2[TKey,T], TState) Microsoft.FSharp.Collections.MapModule: TState Fold[TKey,T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[TKey,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]]], TState, Microsoft.FSharp.Collections.FSharpMap`2[TKey,T]) Microsoft.FSharp.Collections.MapModule: Void Iterate[TKey,T](Microsoft.FSharp.Core.FSharpFunc`2[TKey,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Collections.FSharpMap`2[TKey,T]) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Void .ctor() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.Core+NoValue: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Core+NoValue: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Core+NoValue: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Core+NoValue: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Core: Microsoft.FSharp.Collections.SeqComposition.Core+NoValue +Microsoft.FSharp.Collections.SeqComposition.Core: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Core: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Int32 HaltedIdx +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Int32 get_HaltedIdx() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: TResult Result +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: TResult get_Result() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Void .ctor(TResult) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]: Void set_Result(TResult) +Microsoft.FSharp.Collections.SeqComposition.ISeqConsumer: Void ListenForStopFurtherProcessing(System.Action`1[System.Int32]) +Microsoft.FSharp.Collections.SeqComposition.ISeqConsumer: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult] Transform[TResult](Microsoft.FSharp.Collections.SeqComposition.ISeqTransform`2[T,TResult]) +Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]: TResult Fold[TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2[T,TResult]]) +Microsoft.FSharp.Collections.SeqComposition.ISeqTransform`2[T,TResult]: Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,V] Compose[V](Microsoft.FSharp.Collections.SeqComposition.ISeqConsumer, Int32, Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[TResult,V]) Microsoft.FSharp.Collections.SeqModule: Boolean Contains[T](T, System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Boolean Equals(System.Object) Microsoft.FSharp.Collections.SeqModule: Boolean Exists2[T1,T2](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,System.Boolean]], System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2]) @@ -920,7 +1031,10 @@ Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Boolean Equal Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Boolean get_CheckClose() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Int32 GenerateNext(System.Collections.Generic.IEnumerable`1[T] ByRef) Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Int32 GetHashCode() +Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Int32 Length() +Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Append(Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.Collections.Generic.IEnumerator`1[T] GetFreshEnumerator() +Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.Collections.Generic.IEnumerable`1[T] GetRaw() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.String ToString() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.Type GetType() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: T LastGenerated diff --git a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl index 5f4e677efc6..8df7fccda60 100644 --- a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl +++ b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl @@ -39,9 +39,9 @@ value simpleLibraryCall7 at line 61 does not make a critical tailcall value simpleLibraryCall8 at line 62 does not make a critical tailcall value simpleLibraryCall9 at line 63 does not make a critical tailcall value simpleLibraryCall10 at line 65 does not make a critical tailcall -value simpleLibraryCall11 at line 66 does not make a critical tailcall -value simpleLibraryCall12 at line 67 does not make a critical tailcall -value simpleLibraryCall13 at line 68 does not make a critical tailcall +value simpleLibraryCall11 at line 66 may make a critical tailcall +value simpleLibraryCall12 at line 67 may make a critical tailcall +value simpleLibraryCall13 at line 68 may make a critical tailcall value simpleLibraryUse14 at line 69 does not make a critical tailcall value simpleLibraryUse15 at line 70 does not make a critical tailcall value simpleLibraryUse16 at line 71 does not make a critical tailcall diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Aggregates01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Aggregates01.il.bsl index 2b6e9243808..06526385baa 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Aggregates01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Aggregates01.il.bsl @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 4:4:3:0 } .assembly extern Utils { @@ -38,20 +38,20 @@ } .mresource public FSharpSignatureData.Linq101Aggregates01 { - // Offset: 0x00000000 Length: 0x000005F2 + // Offset: 0x00000000 Length: 0x00000614 } .mresource public FSharpOptimizationData.Linq101Aggregates01 { - // Offset: 0x000005F8 Length: 0x00000211 + // Offset: 0x00000618 Length: 0x00000211 } .module Linq101Aggregates01.exe -// MVID: {5A1F62A6-D281-4783-A745-0383A6621F5A} +// MVID: {5AF1FE1B-D281-4783-A745-03831BFEF15A} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01280000 +// Image base: 0x03330000 // =============== CLASS MEMBERS DECLARATION =================== @@ -116,7 +116,7 @@ // Code size 191 (0xbf) .maxstack 6 .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 100001,100001 : 0,0 'C:\\visualfsharp\\tests\\fsharpqa\\Source\\CodeGen\\EmittedIL\\QueryExpressionStepping\\Linq101Aggregates01.fs' + .line 100001,100001 : 0,0 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\CodeGen\\EmittedIL\\QueryExpressionStepping\\Linq101Aggregates01.fs' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/uniqueFactors@12::pc IL_0006: ldc.i4.1 @@ -804,6 +804,89 @@ } // end of class 'numSum@22-1' + .class auto autochar serializable sealed nested assembly beforefieldinit specialname 'numSum@22-3' + extends class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2 + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 projection + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public specialname rtspecialname + instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 projection) cil managed + { + // Code size 17 (0x11) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'numSum@22-3'::projection + IL_0007: ldarg.0 + IL_0008: ldc.i4.0 + IL_0009: callvirt instance void class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2::.ctor(!1) + IL_000e: ldarg.0 + IL_000f: pop + IL_0010: ret + } // end of method 'numSum@22-3'::.ctor + + .method public hidebysig virtual instance bool + ProcessNext(int32 'value') cil managed + { + // Code size 28 (0x1c) + .maxstack 8 + .line 100001,100001 : 0,0 '' + IL_0000: ldarg.0 + IL_0001: ldarg.0 + IL_0002: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2::get_Result() + IL_0007: ldarg.0 + IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'numSum@22-3'::projection + IL_000d: ldarg.1 + IL_000e: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0013: add.ovf + IL_0014: callvirt instance void class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2::set_Result(!1) + IL_0019: nop + .line 22,22 : 9,16 '' + IL_001a: ldc.i4.0 + IL_001b: ret + } // end of method 'numSum@22-3'::ProcessNext + + } // end of class 'numSum@22-3' + + .class auto ansi serializable sealed nested assembly beforefieldinit 'numSum@22-2' + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> + { + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 projection + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method assembly specialname rtspecialname + instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 projection) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 14 (0xe) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'numSum@22-2'::projection + IL_000d: ret + } // end of method 'numSum@22-2'::.ctor + + .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2 + Invoke(int32 _arg1) cil managed + { + // Code size 12 (0xc) + .maxstack 8 + .line 22,22 : 9,16 '' + IL_0000: ldarg.0 + IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'numSum@22-2'::projection + IL_0006: newobj instance void Linq101Aggregates01/'numSum@22-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) + IL_000b: ret + } // end of method 'numSum@22-2'::Invoke + + } // end of class 'numSum@22-2' + .class auto autochar serializable sealed nested assembly beforefieldinit specialname totalChars@30 extends class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1 { @@ -1190,6 +1273,89 @@ } // end of class 'totalChars@31-1' + .class auto autochar serializable sealed nested assembly beforefieldinit specialname 'totalChars@31-3' + extends class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2 + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 projection + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public specialname rtspecialname + instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 projection) cil managed + { + // Code size 17 (0x11) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'totalChars@31-3'::projection + IL_0007: ldarg.0 + IL_0008: ldc.i4.0 + IL_0009: callvirt instance void class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2::.ctor(!1) + IL_000e: ldarg.0 + IL_000f: pop + IL_0010: ret + } // end of method 'totalChars@31-3'::.ctor + + .method public hidebysig virtual instance bool + ProcessNext(string 'value') cil managed + { + // Code size 28 (0x1c) + .maxstack 8 + .line 100001,100001 : 0,0 '' + IL_0000: ldarg.0 + IL_0001: ldarg.0 + IL_0002: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2::get_Result() + IL_0007: ldarg.0 + IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'totalChars@31-3'::projection + IL_000d: ldarg.1 + IL_000e: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0013: add.ovf + IL_0014: callvirt instance void class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2::set_Result(!1) + IL_0019: nop + .line 31,31 : 9,25 '' + IL_001a: ldc.i4.0 + IL_001b: ret + } // end of method 'totalChars@31-3'::ProcessNext + + } // end of class 'totalChars@31-3' + + .class auto ansi serializable sealed nested assembly beforefieldinit 'totalChars@31-2' + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> + { + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 projection + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method assembly specialname rtspecialname + instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 projection) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 14 (0xe) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'totalChars@31-2'::projection + IL_000d: ret + } // end of method 'totalChars@31-2'::.ctor + + .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2 + Invoke(int32 _arg1) cil managed + { + // Code size 12 (0xc) + .maxstack 8 + .line 31,31 : 9,25 '' + IL_0000: ldarg.0 + IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'totalChars@31-2'::projection + IL_0006: newobj instance void Linq101Aggregates01/'totalChars@31-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) + IL_000b: ret + } // end of method 'totalChars@31-2'::Invoke + + } // end of class 'totalChars@31-2' + .class auto ansi serializable sealed nested assembly beforefieldinit categories@39 extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> { @@ -1684,6 +1850,89 @@ } // end of class 'sum@43-1' + .class auto autochar serializable sealed nested assembly beforefieldinit specialname 'sum@43-3' + extends class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2 + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 projection + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public specialname rtspecialname + instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 projection) cil managed + { + // Code size 17 (0x11) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'sum@43-3'::projection + IL_0007: ldarg.0 + IL_0008: ldc.i4.0 + IL_0009: callvirt instance void class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2::.ctor(!1) + IL_000e: ldarg.0 + IL_000f: pop + IL_0010: ret + } // end of method 'sum@43-3'::.ctor + + .method public hidebysig virtual instance bool + ProcessNext(class [Utils]Utils/Product 'value') cil managed + { + // Code size 28 (0x1c) + .maxstack 8 + .line 100001,100001 : 0,0 '' + IL_0000: ldarg.0 + IL_0001: ldarg.0 + IL_0002: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2::get_Result() + IL_0007: ldarg.0 + IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'sum@43-3'::projection + IL_000d: ldarg.1 + IL_000e: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0013: add.ovf + IL_0014: callvirt instance void class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2::set_Result(!1) + IL_0019: nop + .line 43,43 : 13,33 '' + IL_001a: ldc.i4.0 + IL_001b: ret + } // end of method 'sum@43-3'::ProcessNext + + } // end of class 'sum@43-3' + + .class auto ansi serializable sealed nested assembly beforefieldinit 'sum@43-2' + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> + { + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 projection + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method assembly specialname rtspecialname + instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 projection) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 14 (0xe) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'sum@43-2'::projection + IL_000d: ret + } // end of method 'sum@43-2'::.ctor + + .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.SeqConsumer`2 + Invoke(int32 _arg1) cil managed + { + // Code size 12 (0xc) + .maxstack 8 + .line 43,43 : 13,33 '' + IL_0000: ldarg.0 + IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'sum@43-2'::projection + IL_0006: newobj instance void Linq101Aggregates01/'sum@43-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) + IL_000b: ret + } // end of method 'sum@43-2'::Invoke + + } // end of class 'sum@43-2' + .class auto ansi serializable sealed nested assembly beforefieldinit 'categories@40-3' extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,int32>,object>> { @@ -1709,7 +1958,7 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,int32>,object> Invoke(class [System.Core]System.Linq.IGrouping`2 _arg2) cil managed { - // Code size 147 (0x93) + // Code size 108 (0x6c) .maxstack 10 .locals init ([0] class [System.Core]System.Linq.IGrouping`2 g, [1] int32 sum, @@ -1717,11 +1966,7 @@ [3] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_3, [4] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 V_4, [5] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_5, - [6] class [mscorlib]System.Collections.Generic.IEnumerable`1 V_6, - [7] class [mscorlib]System.Collections.Generic.IEnumerator`1 V_7, - [8] int32 V_8, - [9] int32 V_9, - [10] class [mscorlib]System.IDisposable V_10) + [6] class [mscorlib]System.Collections.Generic.IEnumerable`1 V_6) .line 40,40 : 38,39 '' IL_0000: ldarg.1 IL_0001: stloc.0 @@ -1749,69 +1994,34 @@ IL_0025: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() IL_002a: stloc.s V_6 IL_002c: ldloc.s V_6 - IL_002e: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() - IL_0033: stloc.s V_7 - .try - { - IL_0035: ldc.i4.0 - IL_0036: stloc.s V_9 - IL_0038: ldloc.s V_7 - IL_003a: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() - IL_003f: brfalse.s IL_0057 - - .line 43,43 : 13,33 '' - IL_0041: ldloc.s V_9 - IL_0043: ldloc.s V_5 - IL_0045: ldloc.s V_7 - IL_0047: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() - IL_004c: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_0051: add.ovf - IL_0052: stloc.s V_9 - .line 100001,100001 : 0,0 '' - IL_0054: nop - IL_0055: br.s IL_0038 - - IL_0057: ldloc.s V_9 - IL_0059: stloc.s V_8 - IL_005b: leave.s IL_007b - - } // end .try - finally - { - IL_005d: ldloc.s V_7 - IL_005f: isinst [mscorlib]System.IDisposable - IL_0064: stloc.s V_10 - IL_0066: ldloc.s V_10 - IL_0068: brfalse.s IL_006c + IL_002e: box class [mscorlib]System.Collections.Generic.IEnumerable`1 + IL_0033: brfalse.s IL_0037 - IL_006a: br.s IL_006e + IL_0035: br.s IL_0042 - IL_006c: br.s IL_0078 + .line 100001,100001 : 0,0 '' + IL_0037: ldstr "source" + IL_003c: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string) + IL_0041: throw - .line 100001,100001 : 0,0 '' - IL_006e: ldloc.s V_10 - IL_0070: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_0075: ldnull - IL_0076: pop - IL_0077: endfinally - .line 100001,100001 : 0,0 '' - IL_0078: ldnull - IL_0079: pop - IL_007a: endfinally - .line 100001,100001 : 0,0 '' - } // end handler - IL_007b: ldloc.s V_8 - IL_007d: stloc.1 + .line 100001,100001 : 0,0 '' + IL_0042: nop + IL_0043: ldloc.s V_6 + IL_0045: call class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1 [FSharp.Core]Microsoft.FSharp.Collections.IConsumableSeqModule::OfSeq(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_004a: ldloc.s V_5 + IL_004c: newobj instance void Linq101Aggregates01/'sum@43-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) + IL_0051: callvirt instance !!0 class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1::Consume(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0056: stloc.1 .line 45,45 : 9,28 '' - IL_007e: ldarg.0 - IL_007f: ldfld class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder Linq101Aggregates01/'categories@40-3'::builder@ - IL_0084: ldloc.0 - IL_0085: ldloc.1 - IL_0086: newobj instance void class [mscorlib]System.Tuple`2,int32>::.ctor(!0, + IL_0057: ldarg.0 + IL_0058: ldfld class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder Linq101Aggregates01/'categories@40-3'::builder@ + IL_005d: ldloc.0 + IL_005e: ldloc.1 + IL_005f: newobj instance void class [mscorlib]System.Tuple`2,int32>::.ctor(!0, !1) - IL_008b: tail. - IL_008d: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Yield,int32>,object>(!!0) - IL_0092: ret + IL_0064: tail. + IL_0066: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Yield,int32>,object>(!!0) + IL_006b: ret } // end of method 'categories@40-3'::Invoke } // end of class 'categories@40-3' @@ -7816,7 +8026,7 @@ .method public static void main@() cil managed { .entrypoint - // Code size 1797 (0x705) + // Code size 1719 (0x6b7) .maxstack 13 .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 factorsOf300, [1] int32 uniqueFactors, @@ -7844,49 +8054,41 @@ [23] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 V_23, [24] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_24, [25] class [mscorlib]System.Collections.Generic.IEnumerable`1 V_25, - [26] class [mscorlib]System.Collections.Generic.IEnumerator`1 V_26, - [27] int32 V_27, - [28] int32 V_28, - [29] class [mscorlib]System.IDisposable V_29, - [30] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_30, + [26] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_26, + [27] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_27, + [28] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 V_28, + [29] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_29, + [30] class [mscorlib]System.Collections.Generic.IEnumerable`1 V_30, [31] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_31, - [32] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 V_32, - [33] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_33, - [34] class [mscorlib]System.Collections.Generic.IEnumerable`1 V_34, - [35] class [mscorlib]System.Collections.Generic.IEnumerator`1 V_35, - [36] int32 V_36, - [37] int32 V_37, - [38] class [mscorlib]System.IDisposable V_38, - [39] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_39, - [40] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_40, - [41] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_41, - [42] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_42, - [43] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_43, - [44] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_44, - [45] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_45, - [46] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 V_46, - [47] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_47, - [48] class [mscorlib]System.Collections.Generic.IEnumerable`1 V_48, - [49] class [mscorlib]System.Collections.Generic.IEnumerator`1 V_49, - [50] float64 V_50, - [51] float64 V_51, - [52] int32 V_52, - [53] float64 V_53, - [54] int32 V_54, - [55] class [mscorlib]System.IDisposable V_55, - [56] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_56, - [57] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_57, - [58] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable> V_58, - [59] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64> V_59, - [60] class [mscorlib]System.Collections.Generic.IEnumerable`1> V_60, - [61] class [mscorlib]System.Collections.Generic.IEnumerator`1> V_61, - [62] float64 V_62, - [63] float64 V_63, - [64] int32 V_64, - [65] float64 V_65, - [66] int32 V_66, - [67] class [mscorlib]System.IDisposable V_67, - [68] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_68) + [32] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_32, + [33] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_33, + [34] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_34, + [35] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_35, + [36] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_36, + [37] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_37, + [38] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 V_38, + [39] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_39, + [40] class [mscorlib]System.Collections.Generic.IEnumerable`1 V_40, + [41] class [mscorlib]System.Collections.Generic.IEnumerator`1 V_41, + [42] float64 V_42, + [43] float64 V_43, + [44] int32 V_44, + [45] float64 V_45, + [46] int32 V_46, + [47] class [mscorlib]System.IDisposable V_47, + [48] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_48, + [49] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_49, + [50] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable> V_50, + [51] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64> V_51, + [52] class [mscorlib]System.Collections.Generic.IEnumerable`1> V_52, + [53] class [mscorlib]System.Collections.Generic.IEnumerator`1> V_53, + [54] float64 V_54, + [55] float64 V_55, + [56] int32 V_56, + [57] float64 V_57, + [58] int32 V_58, + [59] class [mscorlib]System.IDisposable V_59, + [60] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_60) .line 8,8 : 1,31 '' IL_0000: ldc.i4.2 IL_0001: ldc.i4.2 @@ -7985,682 +8187,612 @@ IL_00c6: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() IL_00cb: stloc.s V_25 IL_00cd: ldloc.s V_25 - IL_00cf: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() - IL_00d4: stloc.s V_26 - .try - { - IL_00d6: ldc.i4.0 - IL_00d7: stloc.s V_28 - IL_00d9: ldloc.s V_26 - IL_00db: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() - IL_00e0: brfalse.s IL_00f8 - - .line 22,22 : 9,16 '' - IL_00e2: ldloc.s V_28 - IL_00e4: ldloc.s V_24 - IL_00e6: ldloc.s V_26 - IL_00e8: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() - IL_00ed: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_00f2: add.ovf - IL_00f3: stloc.s V_28 - .line 100001,100001 : 0,0 '' - IL_00f5: nop - IL_00f6: br.s IL_00d9 - - IL_00f8: ldloc.s V_28 - IL_00fa: stloc.s V_27 - IL_00fc: leave.s IL_011c - - } // end .try - finally - { - IL_00fe: ldloc.s V_26 - IL_0100: isinst [mscorlib]System.IDisposable - IL_0105: stloc.s V_29 - IL_0107: ldloc.s V_29 - IL_0109: brfalse.s IL_010d + IL_00cf: box class [mscorlib]System.Collections.Generic.IEnumerable`1 + IL_00d4: brfalse.s IL_00d8 - IL_010b: br.s IL_010f + IL_00d6: br.s IL_00e3 - IL_010d: br.s IL_0119 + .line 100001,100001 : 0,0 '' + IL_00d8: ldstr "source" + IL_00dd: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string) + IL_00e2: throw - .line 100001,100001 : 0,0 '' - IL_010f: ldloc.s V_29 - IL_0111: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_0116: ldnull - IL_0117: pop - IL_0118: endfinally - .line 100001,100001 : 0,0 '' - IL_0119: ldnull - IL_011a: pop - IL_011b: endfinally - .line 100001,100001 : 0,0 '' - } // end handler - IL_011c: ldloc.s V_27 - IL_011e: dup - IL_011f: stsfld int32 ''.$Linq101Aggregates01::numSum@19 - IL_0124: stloc.3 + .line 100001,100001 : 0,0 '' + IL_00e3: nop + IL_00e4: ldloc.s V_25 + IL_00e6: call class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1 [FSharp.Core]Microsoft.FSharp.Collections.IConsumableSeqModule::OfSeq(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_00eb: ldloc.s V_24 + IL_00ed: newobj instance void Linq101Aggregates01/'numSum@22-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) + IL_00f2: callvirt instance !!0 class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1::Consume(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_00f7: dup + IL_00f8: stsfld int32 ''.$Linq101Aggregates01::numSum@19 + IL_00fd: stloc.3 .line 26,26 : 1,45 '' - IL_0125: ldstr "cherry" - IL_012a: ldstr "apple" - IL_012f: ldstr "blueberry" - IL_0134: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() - IL_0139: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_00fe: ldstr "cherry" + IL_0103: ldstr "apple" + IL_0108: ldstr "blueberry" + IL_010d: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_0112: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_013e: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_0117: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_0143: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_011c: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_0148: dup - IL_0149: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::words@26 - IL_014e: stloc.s words - IL_0150: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_0155: stloc.s V_30 - IL_0157: ldloc.s V_30 - IL_0159: stloc.s V_31 - IL_015b: ldnull - IL_015c: ldnull - IL_015d: ldnull - IL_015e: ldc.i4.0 - IL_015f: ldnull - IL_0160: newobj instance void Linq101Aggregates01/totalChars@30::.ctor(string, + IL_0121: dup + IL_0122: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::words@26 + IL_0127: stloc.s words + IL_0129: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_012e: stloc.s V_26 + IL_0130: ldloc.s V_26 + IL_0132: stloc.s V_27 + IL_0134: ldnull + IL_0135: ldnull + IL_0136: ldnull + IL_0137: ldc.i4.0 + IL_0138: ldnull + IL_0139: newobj instance void Linq101Aggregates01/totalChars@30::.ctor(string, string, class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, string) - IL_0165: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_016a: stloc.s V_32 - IL_016c: newobj instance void Linq101Aggregates01/'totalChars@31-1'::.ctor() - IL_0171: stloc.s V_33 - IL_0173: ldloc.s V_32 - IL_0175: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() - IL_017a: stloc.s V_34 - IL_017c: ldloc.s V_34 - IL_017e: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() - IL_0183: stloc.s V_35 - .try - { - IL_0185: ldc.i4.0 - IL_0186: stloc.s V_37 - IL_0188: ldloc.s V_35 - IL_018a: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() - IL_018f: brfalse.s IL_01a7 - - .line 31,31 : 9,25 '' - IL_0191: ldloc.s V_37 - IL_0193: ldloc.s V_33 - IL_0195: ldloc.s V_35 - IL_0197: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() - IL_019c: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_01a1: add.ovf - IL_01a2: stloc.s V_37 - .line 100001,100001 : 0,0 '' - IL_01a4: nop - IL_01a5: br.s IL_0188 - - IL_01a7: ldloc.s V_37 - IL_01a9: stloc.s V_36 - IL_01ab: leave.s IL_01cb + IL_013e: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0143: stloc.s V_28 + IL_0145: newobj instance void Linq101Aggregates01/'totalChars@31-1'::.ctor() + IL_014a: stloc.s V_29 + IL_014c: ldloc.s V_28 + IL_014e: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() + IL_0153: stloc.s V_30 + IL_0155: ldloc.s V_30 + IL_0157: box class [mscorlib]System.Collections.Generic.IEnumerable`1 + IL_015c: brfalse.s IL_0160 + + IL_015e: br.s IL_016b - } // end .try - finally - { - IL_01ad: ldloc.s V_35 - IL_01af: isinst [mscorlib]System.IDisposable - IL_01b4: stloc.s V_38 - IL_01b6: ldloc.s V_38 - IL_01b8: brfalse.s IL_01bc - - IL_01ba: br.s IL_01be - - IL_01bc: br.s IL_01c8 + .line 100001,100001 : 0,0 '' + IL_0160: ldstr "source" + IL_0165: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string) + IL_016a: throw - .line 100001,100001 : 0,0 '' - IL_01be: ldloc.s V_38 - IL_01c0: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_01c5: ldnull - IL_01c6: pop - IL_01c7: endfinally - .line 100001,100001 : 0,0 '' - IL_01c8: ldnull - IL_01c9: pop - IL_01ca: endfinally - .line 100001,100001 : 0,0 '' - } // end handler - IL_01cb: ldloc.s V_36 - IL_01cd: dup - IL_01ce: stsfld int32 ''.$Linq101Aggregates01::totalChars@28 - IL_01d3: stloc.s totalChars + .line 100001,100001 : 0,0 '' + IL_016b: nop + IL_016c: ldloc.s V_30 + IL_016e: call class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1 [FSharp.Core]Microsoft.FSharp.Collections.IConsumableSeqModule::OfSeq(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0173: ldloc.s V_29 + IL_0175: newobj instance void Linq101Aggregates01/'totalChars@31-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) + IL_017a: callvirt instance !!0 class [FSharp.Core]Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1::Consume(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_017f: dup + IL_0180: stsfld int32 ''.$Linq101Aggregates01::totalChars@28 + IL_0185: stloc.s totalChars .line 35,35 : 1,32 '' - IL_01d5: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [Utils]Utils::getProductList() - IL_01da: dup - IL_01db: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::products@35 - IL_01e0: stloc.s products + IL_0187: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [Utils]Utils::getProductList() + IL_018c: dup + IL_018d: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::products@35 + IL_0192: stloc.s products .line 37,46 : 1,21 '' - IL_01e2: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_01e7: stloc.s V_39 - IL_01e9: ldloc.s V_39 - IL_01eb: ldloc.s V_39 - IL_01ed: ldloc.s V_39 - IL_01ef: ldloc.s V_39 - IL_01f1: ldloc.s V_39 - IL_01f3: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_01f8: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_01fd: ldloc.s V_39 - IL_01ff: newobj instance void Linq101Aggregates01/categories@39::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_0204: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0194: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_0199: stloc.s V_31 + IL_019b: ldloc.s V_31 + IL_019d: ldloc.s V_31 + IL_019f: ldloc.s V_31 + IL_01a1: ldloc.s V_31 + IL_01a3: ldloc.s V_31 + IL_01a5: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_01aa: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_01af: ldloc.s V_31 + IL_01b1: newobj instance void Linq101Aggregates01/categories@39::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_01b6: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0209: newobj instance void Linq101Aggregates01/'categories@40-1'::.ctor() - IL_020e: newobj instance void Linq101Aggregates01/'categories@40-2'::.ctor() - IL_0213: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_01bb: newobj instance void Linq101Aggregates01/'categories@40-1'::.ctor() + IL_01c0: newobj instance void Linq101Aggregates01/'categories@40-2'::.ctor() + IL_01c5: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0218: ldloc.s V_39 - IL_021a: newobj instance void Linq101Aggregates01/'categories@40-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_021f: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,int32>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_01ca: ldloc.s V_31 + IL_01cc: newobj instance void Linq101Aggregates01/'categories@40-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_01d1: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,int32>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0224: newobj instance void Linq101Aggregates01/'categories@45-4'::.ctor() - IL_0229: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,int32>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_01d6: newobj instance void Linq101Aggregates01/'categories@45-4'::.ctor() + IL_01db: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,int32>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_022e: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_0233: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0238: dup - IL_0239: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories@37 - IL_023e: stloc.s categories - IL_0240: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_0245: ldc.i4.0 - IL_0246: ldc.i4.0 - IL_0247: ldnull - IL_0248: ldc.i4.0 - IL_0249: ldc.i4.0 - IL_024a: newobj instance void Linq101Aggregates01/minNum@49::.ctor(int32, + IL_01e0: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_01e5: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_01ea: dup + IL_01eb: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories@37 + IL_01f0: stloc.s categories + IL_01f2: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_01f7: ldc.i4.0 + IL_01f8: ldc.i4.0 + IL_01f9: ldnull + IL_01fa: ldc.i4.0 + IL_01fb: ldc.i4.0 + IL_01fc: newobj instance void Linq101Aggregates01/minNum@49::.ctor(int32, int32, class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, int32) - IL_024f: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0254: newobj instance void Linq101Aggregates01/'minNum@49-1'::.ctor() - IL_0259: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MinBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0201: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0206: newobj instance void Linq101Aggregates01/'minNum@49-1'::.ctor() + IL_020b: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MinBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_025e: dup - IL_025f: stsfld int32 ''.$Linq101Aggregates01::minNum@49 - IL_0264: stloc.s minNum - IL_0266: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_026b: ldnull - IL_026c: ldnull - IL_026d: ldnull - IL_026e: ldc.i4.0 - IL_026f: ldnull - IL_0270: newobj instance void Linq101Aggregates01/shortestWord@52::.ctor(string, + IL_0210: dup + IL_0211: stsfld int32 ''.$Linq101Aggregates01::minNum@49 + IL_0216: stloc.s minNum + IL_0218: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_021d: ldnull + IL_021e: ldnull + IL_021f: ldnull + IL_0220: ldc.i4.0 + IL_0221: ldnull + IL_0222: newobj instance void Linq101Aggregates01/shortestWord@52::.ctor(string, string, class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, string) - IL_0275: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_027a: newobj instance void Linq101Aggregates01/'shortestWord@52-1'::.ctor() - IL_027f: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MinBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0227: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_022c: newobj instance void Linq101Aggregates01/'shortestWord@52-1'::.ctor() + IL_0231: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MinBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0284: dup - IL_0285: stsfld int32 ''.$Linq101Aggregates01::shortestWord@52 - IL_028a: stloc.s shortestWord + IL_0236: dup + IL_0237: stsfld int32 ''.$Linq101Aggregates01::shortestWord@52 + IL_023c: stloc.s shortestWord .line 55,61 : 1,21 '' - IL_028c: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_0291: stloc.s V_40 - IL_0293: ldloc.s V_40 - IL_0295: ldloc.s V_40 - IL_0297: ldloc.s V_40 - IL_0299: ldloc.s V_40 - IL_029b: ldloc.s V_40 - IL_029d: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_02a2: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_02a7: ldloc.s V_40 - IL_02a9: newobj instance void Linq101Aggregates01/categories2@57::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_02ae: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_023e: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_0243: stloc.s V_32 + IL_0245: ldloc.s V_32 + IL_0247: ldloc.s V_32 + IL_0249: ldloc.s V_32 + IL_024b: ldloc.s V_32 + IL_024d: ldloc.s V_32 + IL_024f: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_0254: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0259: ldloc.s V_32 + IL_025b: newobj instance void Linq101Aggregates01/categories2@57::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_0260: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_02b3: newobj instance void Linq101Aggregates01/'categories2@58-1'::.ctor() - IL_02b8: newobj instance void Linq101Aggregates01/'categories2@58-2'::.ctor() - IL_02bd: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0265: newobj instance void Linq101Aggregates01/'categories2@58-1'::.ctor() + IL_026a: newobj instance void Linq101Aggregates01/'categories2@58-2'::.ctor() + IL_026f: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_02c2: ldloc.s V_40 - IL_02c4: newobj instance void Linq101Aggregates01/'categories2@58-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_02c9: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0274: ldloc.s V_32 + IL_0276: newobj instance void Linq101Aggregates01/'categories2@58-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_027b: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_02ce: newobj instance void Linq101Aggregates01/'categories2@60-4'::.ctor() - IL_02d3: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0280: newobj instance void Linq101Aggregates01/'categories2@60-4'::.ctor() + IL_0285: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_02d8: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_02dd: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_02e2: dup - IL_02e3: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories2@55 - IL_02e8: stloc.s categories2 + IL_028a: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_028f: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0294: dup + IL_0295: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories2@55 + IL_029a: stloc.s categories2 .line 64,71 : 1,21 '' - IL_02ea: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_02ef: stloc.s V_41 - IL_02f1: ldloc.s V_41 - IL_02f3: ldloc.s V_41 - IL_02f5: ldloc.s V_41 - IL_02f7: ldloc.s V_41 - IL_02f9: ldloc.s V_41 - IL_02fb: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_0300: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0305: ldloc.s V_41 - IL_0307: newobj instance void Linq101Aggregates01/categories3@66::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_030c: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_029c: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_02a1: stloc.s V_33 + IL_02a3: ldloc.s V_33 + IL_02a5: ldloc.s V_33 + IL_02a7: ldloc.s V_33 + IL_02a9: ldloc.s V_33 + IL_02ab: ldloc.s V_33 + IL_02ad: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_02b2: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_02b7: ldloc.s V_33 + IL_02b9: newobj instance void Linq101Aggregates01/categories3@66::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_02be: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0311: newobj instance void Linq101Aggregates01/'categories3@67-1'::.ctor() - IL_0316: newobj instance void Linq101Aggregates01/'categories3@67-2'::.ctor() - IL_031b: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_02c3: newobj instance void Linq101Aggregates01/'categories3@67-1'::.ctor() + IL_02c8: newobj instance void Linq101Aggregates01/'categories3@67-2'::.ctor() + IL_02cd: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0320: ldloc.s V_41 - IL_0322: newobj instance void Linq101Aggregates01/'categories3@67-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_0327: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`3,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_02d2: ldloc.s V_33 + IL_02d4: newobj instance void Linq101Aggregates01/'categories3@67-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_02d9: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`3,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_032c: newobj instance void Linq101Aggregates01/'categories3@70-4'::.ctor() - IL_0331: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_02de: newobj instance void Linq101Aggregates01/'categories3@70-4'::.ctor() + IL_02e3: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0336: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2>,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_033b: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0340: dup - IL_0341: stsfld class [mscorlib]System.Tuple`2>[] ''.$Linq101Aggregates01::categories3@64 - IL_0346: stloc.s categories3 - IL_0348: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_034d: ldc.i4.0 - IL_034e: ldc.i4.0 - IL_034f: ldnull - IL_0350: ldc.i4.0 - IL_0351: ldc.i4.0 - IL_0352: newobj instance void Linq101Aggregates01/maxNum@74::.ctor(int32, + IL_02e8: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2>,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_02ed: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_02f2: dup + IL_02f3: stsfld class [mscorlib]System.Tuple`2>[] ''.$Linq101Aggregates01::categories3@64 + IL_02f8: stloc.s categories3 + IL_02fa: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_02ff: ldc.i4.0 + IL_0300: ldc.i4.0 + IL_0301: ldnull + IL_0302: ldc.i4.0 + IL_0303: ldc.i4.0 + IL_0304: newobj instance void Linq101Aggregates01/maxNum@74::.ctor(int32, int32, class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, int32) - IL_0357: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_035c: newobj instance void Linq101Aggregates01/'maxNum@74-1'::.ctor() - IL_0361: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MaxBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0309: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_030e: newobj instance void Linq101Aggregates01/'maxNum@74-1'::.ctor() + IL_0313: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MaxBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0366: dup - IL_0367: stsfld int32 ''.$Linq101Aggregates01::maxNum@74 - IL_036c: stloc.s maxNum - IL_036e: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_0373: ldnull - IL_0374: ldnull - IL_0375: ldnull - IL_0376: ldc.i4.0 - IL_0377: ldnull - IL_0378: newobj instance void Linq101Aggregates01/longestLength@77::.ctor(string, + IL_0318: dup + IL_0319: stsfld int32 ''.$Linq101Aggregates01::maxNum@74 + IL_031e: stloc.s maxNum + IL_0320: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_0325: ldnull + IL_0326: ldnull + IL_0327: ldnull + IL_0328: ldc.i4.0 + IL_0329: ldnull + IL_032a: newobj instance void Linq101Aggregates01/longestLength@77::.ctor(string, string, class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, string) - IL_037d: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0382: newobj instance void Linq101Aggregates01/'longestLength@77-1'::.ctor() - IL_0387: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MaxBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_032f: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0334: newobj instance void Linq101Aggregates01/'longestLength@77-1'::.ctor() + IL_0339: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MaxBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_038c: dup - IL_038d: stsfld int32 ''.$Linq101Aggregates01::longestLength@77 - IL_0392: stloc.s longestLength + IL_033e: dup + IL_033f: stsfld int32 ''.$Linq101Aggregates01::longestLength@77 + IL_0344: stloc.s longestLength .line 80,86 : 1,21 '' - IL_0394: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_0399: stloc.s V_42 - IL_039b: ldloc.s V_42 - IL_039d: ldloc.s V_42 - IL_039f: ldloc.s V_42 - IL_03a1: ldloc.s V_42 - IL_03a3: ldloc.s V_42 - IL_03a5: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_03aa: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_03af: ldloc.s V_42 - IL_03b1: newobj instance void Linq101Aggregates01/categories4@82::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_03b6: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0346: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_034b: stloc.s V_34 + IL_034d: ldloc.s V_34 + IL_034f: ldloc.s V_34 + IL_0351: ldloc.s V_34 + IL_0353: ldloc.s V_34 + IL_0355: ldloc.s V_34 + IL_0357: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_035c: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0361: ldloc.s V_34 + IL_0363: newobj instance void Linq101Aggregates01/categories4@82::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_0368: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_03bb: newobj instance void Linq101Aggregates01/'categories4@83-1'::.ctor() - IL_03c0: newobj instance void Linq101Aggregates01/'categories4@83-2'::.ctor() - IL_03c5: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_036d: newobj instance void Linq101Aggregates01/'categories4@83-1'::.ctor() + IL_0372: newobj instance void Linq101Aggregates01/'categories4@83-2'::.ctor() + IL_0377: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_03ca: ldloc.s V_42 - IL_03cc: newobj instance void Linq101Aggregates01/'categories4@83-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_03d1: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_037c: ldloc.s V_34 + IL_037e: newobj instance void Linq101Aggregates01/'categories4@83-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_0383: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_03d6: newobj instance void Linq101Aggregates01/'categories4@85-4'::.ctor() - IL_03db: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0388: newobj instance void Linq101Aggregates01/'categories4@85-4'::.ctor() + IL_038d: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_03e0: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_03e5: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_03ea: dup - IL_03eb: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories4@80 - IL_03f0: stloc.s categories4 + IL_0392: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_0397: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_039c: dup + IL_039d: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories4@80 + IL_03a2: stloc.s categories4 .line 89,96 : 1,21 '' - IL_03f2: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_03f7: stloc.s V_43 - IL_03f9: ldloc.s V_43 - IL_03fb: ldloc.s V_43 - IL_03fd: ldloc.s V_43 - IL_03ff: ldloc.s V_43 - IL_0401: ldloc.s V_43 - IL_0403: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_0408: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_040d: ldloc.s V_43 - IL_040f: newobj instance void Linq101Aggregates01/categories5@91::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_0414: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_03a4: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_03a9: stloc.s V_35 + IL_03ab: ldloc.s V_35 + IL_03ad: ldloc.s V_35 + IL_03af: ldloc.s V_35 + IL_03b1: ldloc.s V_35 + IL_03b3: ldloc.s V_35 + IL_03b5: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_03ba: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_03bf: ldloc.s V_35 + IL_03c1: newobj instance void Linq101Aggregates01/categories5@91::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_03c6: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0419: newobj instance void Linq101Aggregates01/'categories5@92-1'::.ctor() - IL_041e: newobj instance void Linq101Aggregates01/'categories5@92-2'::.ctor() - IL_0423: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_03cb: newobj instance void Linq101Aggregates01/'categories5@92-1'::.ctor() + IL_03d0: newobj instance void Linq101Aggregates01/'categories5@92-2'::.ctor() + IL_03d5: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0428: ldloc.s V_43 - IL_042a: newobj instance void Linq101Aggregates01/'categories5@92-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_042f: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`3,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_03da: ldloc.s V_35 + IL_03dc: newobj instance void Linq101Aggregates01/'categories5@92-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_03e1: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`3,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0434: newobj instance void Linq101Aggregates01/'categories5@95-4'::.ctor() - IL_0439: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_03e6: newobj instance void Linq101Aggregates01/'categories5@95-4'::.ctor() + IL_03eb: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_043e: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2>,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_0443: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0448: dup - IL_0449: stsfld class [mscorlib]System.Tuple`2>[] ''.$Linq101Aggregates01::categories5@89 - IL_044e: stloc.s categories5 + IL_03f0: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2>,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_03f5: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_03fa: dup + IL_03fb: stsfld class [mscorlib]System.Tuple`2>[] ''.$Linq101Aggregates01::categories5@89 + IL_0400: stloc.s categories5 .line 99,99 : 1,66 '' - IL_0450: ldc.r8 5. - IL_0459: ldc.r8 4. - IL_0462: ldc.r8 1. - IL_046b: ldc.r8 3. - IL_0474: ldc.r8 9. - IL_047d: ldc.r8 8. - IL_0486: ldc.r8 6. - IL_048f: ldc.r8 7. - IL_0498: ldc.r8 2. - IL_04a1: ldc.r8 0.0 - IL_04aa: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() - IL_04af: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_0402: ldc.r8 5. + IL_040b: ldc.r8 4. + IL_0414: ldc.r8 1. + IL_041d: ldc.r8 3. + IL_0426: ldc.r8 9. + IL_042f: ldc.r8 8. + IL_0438: ldc.r8 6. + IL_0441: ldc.r8 7. + IL_044a: ldc.r8 2. + IL_0453: ldc.r8 0.0 + IL_045c: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_0461: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04b4: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_0466: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04b9: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_046b: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04be: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_0470: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04c3: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_0475: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04c8: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_047a: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04cd: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_047f: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04d2: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_0484: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04d7: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_0489: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04dc: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_048e: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04e1: dup - IL_04e2: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::numbers2@99 - IL_04e7: stloc.s numbers2 - IL_04e9: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_04ee: stloc.s V_44 - IL_04f0: ldloc.s V_44 - IL_04f2: stloc.s V_45 - IL_04f4: ldc.r8 0.0 - IL_04fd: ldc.r8 0.0 - IL_0506: ldnull - IL_0507: ldc.i4.0 - IL_0508: ldc.r8 0.0 - IL_0511: newobj instance void Linq101Aggregates01/averageNum@100::.ctor(float64, + IL_0493: dup + IL_0494: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::numbers2@99 + IL_0499: stloc.s numbers2 + IL_049b: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_04a0: stloc.s V_36 + IL_04a2: ldloc.s V_36 + IL_04a4: stloc.s V_37 + IL_04a6: ldc.r8 0.0 + IL_04af: ldc.r8 0.0 + IL_04b8: ldnull + IL_04b9: ldc.i4.0 + IL_04ba: ldc.r8 0.0 + IL_04c3: newobj instance void Linq101Aggregates01/averageNum@100::.ctor(float64, float64, class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, float64) - IL_0516: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_051b: stloc.s V_46 - IL_051d: newobj instance void Linq101Aggregates01/'averageNum@100-1'::.ctor() - IL_0522: stloc.s V_47 - IL_0524: ldloc.s V_46 - IL_0526: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() - IL_052b: stloc.s V_48 - IL_052d: ldloc.s V_48 - IL_052f: box class [mscorlib]System.Collections.Generic.IEnumerable`1 - IL_0534: brfalse.s IL_0538 - - IL_0536: br.s IL_0543 + IL_04c8: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_04cd: stloc.s V_38 + IL_04cf: newobj instance void Linq101Aggregates01/'averageNum@100-1'::.ctor() + IL_04d4: stloc.s V_39 + IL_04d6: ldloc.s V_38 + IL_04d8: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() + IL_04dd: stloc.s V_40 + IL_04df: ldloc.s V_40 + IL_04e1: box class [mscorlib]System.Collections.Generic.IEnumerable`1 + IL_04e6: brfalse.s IL_04ea + + IL_04e8: br.s IL_04f5 .line 100001,100001 : 0,0 '' - IL_0538: ldstr "source" - IL_053d: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string) - IL_0542: throw + IL_04ea: ldstr "source" + IL_04ef: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string) + IL_04f4: throw .line 100001,100001 : 0,0 '' - IL_0543: nop - IL_0544: ldloc.s V_48 - IL_0546: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() - IL_054b: stloc.s V_49 + IL_04f5: nop + IL_04f6: ldloc.s V_40 + IL_04f8: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() + IL_04fd: stloc.s V_41 .try { - IL_054d: ldc.r8 0.0 - IL_0556: stloc.s V_51 - IL_0558: ldc.i4.0 - IL_0559: stloc.s V_52 - IL_055b: ldloc.s V_49 - IL_055d: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() - IL_0562: brfalse.s IL_0580 - - IL_0564: ldloc.s V_51 - IL_0566: ldloc.s V_47 - IL_0568: ldloc.s V_49 - IL_056a: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() - IL_056f: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_0574: add - IL_0575: stloc.s V_51 + IL_04ff: ldc.r8 0.0 + IL_0508: stloc.s V_43 + IL_050a: ldc.i4.0 + IL_050b: stloc.s V_44 + IL_050d: ldloc.s V_41 + IL_050f: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() + IL_0514: brfalse.s IL_0532 + + IL_0516: ldloc.s V_43 + IL_0518: ldloc.s V_39 + IL_051a: ldloc.s V_41 + IL_051c: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() + IL_0521: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0526: add + IL_0527: stloc.s V_43 .line 100,100 : 47,58 '' - IL_0577: ldloc.s V_52 - IL_0579: ldc.i4.1 - IL_057a: add - IL_057b: stloc.s V_52 + IL_0529: ldloc.s V_44 + IL_052b: ldc.i4.1 + IL_052c: add + IL_052d: stloc.s V_44 .line 100001,100001 : 0,0 '' - IL_057d: nop - IL_057e: br.s IL_055b + IL_052f: nop + IL_0530: br.s IL_050d - IL_0580: ldloc.s V_52 - IL_0582: brtrue.s IL_0586 + IL_0532: ldloc.s V_44 + IL_0534: brtrue.s IL_0538 - IL_0584: br.s IL_0588 + IL_0536: br.s IL_053a - IL_0586: br.s IL_0593 + IL_0538: br.s IL_0545 .line 100001,100001 : 0,0 '' - IL_0588: ldstr "source" - IL_058d: newobj instance void [mscorlib]System.InvalidOperationException::.ctor(string) - IL_0592: throw + IL_053a: ldstr "source" + IL_053f: newobj instance void [mscorlib]System.InvalidOperationException::.ctor(string) + IL_0544: throw .line 100001,100001 : 0,0 '' - IL_0593: nop - IL_0594: ldloc.s V_51 - IL_0596: stloc.s V_53 - IL_0598: ldloc.s V_52 - IL_059a: stloc.s V_54 - IL_059c: ldloc.s V_53 - IL_059e: ldloc.s V_54 - IL_05a0: conv.r8 - IL_05a1: div - IL_05a2: stloc.s V_50 - IL_05a4: leave.s IL_05c4 + IL_0545: nop + IL_0546: ldloc.s V_43 + IL_0548: stloc.s V_45 + IL_054a: ldloc.s V_44 + IL_054c: stloc.s V_46 + IL_054e: ldloc.s V_45 + IL_0550: ldloc.s V_46 + IL_0552: conv.r8 + IL_0553: div + IL_0554: stloc.s V_42 + IL_0556: leave.s IL_0576 } // end .try finally { - IL_05a6: ldloc.s V_49 - IL_05a8: isinst [mscorlib]System.IDisposable - IL_05ad: stloc.s V_55 - IL_05af: ldloc.s V_55 - IL_05b1: brfalse.s IL_05b5 + IL_0558: ldloc.s V_41 + IL_055a: isinst [mscorlib]System.IDisposable + IL_055f: stloc.s V_47 + IL_0561: ldloc.s V_47 + IL_0563: brfalse.s IL_0567 - IL_05b3: br.s IL_05b7 + IL_0565: br.s IL_0569 - IL_05b5: br.s IL_05c1 + IL_0567: br.s IL_0573 .line 100001,100001 : 0,0 '' - IL_05b7: ldloc.s V_55 - IL_05b9: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_05be: ldnull - IL_05bf: pop - IL_05c0: endfinally + IL_0569: ldloc.s V_47 + IL_056b: callvirt instance void [mscorlib]System.IDisposable::Dispose() + IL_0570: ldnull + IL_0571: pop + IL_0572: endfinally .line 100001,100001 : 0,0 '' - IL_05c1: ldnull - IL_05c2: pop - IL_05c3: endfinally + IL_0573: ldnull + IL_0574: pop + IL_0575: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_05c4: ldloc.s V_50 - IL_05c6: dup - IL_05c7: stsfld float64 ''.$Linq101Aggregates01::averageNum@100 - IL_05cc: stloc.s averageNum - IL_05ce: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_05d3: stloc.s V_56 - IL_05d5: ldloc.s V_56 - IL_05d7: stloc.s V_57 - IL_05d9: ldloc.s V_56 - IL_05db: ldloc.s V_56 - IL_05dd: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_words() - IL_05e2: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_05e7: ldloc.s V_56 - IL_05e9: newobj instance void Linq101Aggregates01/averageLength@105::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_05ee: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0576: ldloc.s V_42 + IL_0578: dup + IL_0579: stsfld float64 ''.$Linq101Aggregates01::averageNum@100 + IL_057e: stloc.s averageNum + IL_0580: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_0585: stloc.s V_48 + IL_0587: ldloc.s V_48 + IL_0589: stloc.s V_49 + IL_058b: ldloc.s V_48 + IL_058d: ldloc.s V_48 + IL_058f: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_words() + IL_0594: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0599: ldloc.s V_48 + IL_059b: newobj instance void Linq101Aggregates01/averageLength@105::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_05a0: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_05f3: stloc.s V_58 - IL_05f5: newobj instance void Linq101Aggregates01/'averageLength@107-1'::.ctor() - IL_05fa: stloc.s V_59 - IL_05fc: ldloc.s V_58 - IL_05fe: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_0603: stloc.s V_60 - IL_0605: ldloc.s V_60 - IL_0607: box class [mscorlib]System.Collections.Generic.IEnumerable`1> - IL_060c: brfalse.s IL_0610 - - IL_060e: br.s IL_061b + IL_05a5: stloc.s V_50 + IL_05a7: newobj instance void Linq101Aggregates01/'averageLength@107-1'::.ctor() + IL_05ac: stloc.s V_51 + IL_05ae: ldloc.s V_50 + IL_05b0: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_05b5: stloc.s V_52 + IL_05b7: ldloc.s V_52 + IL_05b9: box class [mscorlib]System.Collections.Generic.IEnumerable`1> + IL_05be: brfalse.s IL_05c2 + + IL_05c0: br.s IL_05cd .line 100001,100001 : 0,0 '' - IL_0610: ldstr "source" - IL_0615: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string) - IL_061a: throw + IL_05c2: ldstr "source" + IL_05c7: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string) + IL_05cc: throw .line 100001,100001 : 0,0 '' - IL_061b: nop - IL_061c: ldloc.s V_60 - IL_061e: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1>::GetEnumerator() - IL_0623: stloc.s V_61 + IL_05cd: nop + IL_05ce: ldloc.s V_52 + IL_05d0: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1>::GetEnumerator() + IL_05d5: stloc.s V_53 .try { - IL_0625: ldc.r8 0.0 - IL_062e: stloc.s V_63 - IL_0630: ldc.i4.0 - IL_0631: stloc.s V_64 - IL_0633: ldloc.s V_61 - IL_0635: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() - IL_063a: brfalse.s IL_0658 - - IL_063c: ldloc.s V_63 - IL_063e: ldloc.s V_59 - IL_0640: ldloc.s V_61 - IL_0642: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1>::get_Current() - IL_0647: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64>::Invoke(!0) - IL_064c: add - IL_064d: stloc.s V_63 + IL_05d7: ldc.r8 0.0 + IL_05e0: stloc.s V_55 + IL_05e2: ldc.i4.0 + IL_05e3: stloc.s V_56 + IL_05e5: ldloc.s V_53 + IL_05e7: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() + IL_05ec: brfalse.s IL_060a + + IL_05ee: ldloc.s V_55 + IL_05f0: ldloc.s V_51 + IL_05f2: ldloc.s V_53 + IL_05f4: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1>::get_Current() + IL_05f9: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64>::Invoke(!0) + IL_05fe: add + IL_05ff: stloc.s V_55 .line 107,107 : 9,21 '' - IL_064f: ldloc.s V_64 - IL_0651: ldc.i4.1 - IL_0652: add - IL_0653: stloc.s V_64 + IL_0601: ldloc.s V_56 + IL_0603: ldc.i4.1 + IL_0604: add + IL_0605: stloc.s V_56 .line 100001,100001 : 0,0 '' - IL_0655: nop - IL_0656: br.s IL_0633 + IL_0607: nop + IL_0608: br.s IL_05e5 - IL_0658: ldloc.s V_64 - IL_065a: brtrue.s IL_065e + IL_060a: ldloc.s V_56 + IL_060c: brtrue.s IL_0610 - IL_065c: br.s IL_0660 + IL_060e: br.s IL_0612 - IL_065e: br.s IL_066b + IL_0610: br.s IL_061d .line 100001,100001 : 0,0 '' - IL_0660: ldstr "source" - IL_0665: newobj instance void [mscorlib]System.InvalidOperationException::.ctor(string) - IL_066a: throw + IL_0612: ldstr "source" + IL_0617: newobj instance void [mscorlib]System.InvalidOperationException::.ctor(string) + IL_061c: throw .line 100001,100001 : 0,0 '' - IL_066b: nop - IL_066c: ldloc.s V_63 - IL_066e: stloc.s V_65 - IL_0670: ldloc.s V_64 - IL_0672: stloc.s V_66 - IL_0674: ldloc.s V_65 - IL_0676: ldloc.s V_66 - IL_0678: conv.r8 - IL_0679: div - IL_067a: stloc.s V_62 - IL_067c: leave.s IL_069c + IL_061d: nop + IL_061e: ldloc.s V_55 + IL_0620: stloc.s V_57 + IL_0622: ldloc.s V_56 + IL_0624: stloc.s V_58 + IL_0626: ldloc.s V_57 + IL_0628: ldloc.s V_58 + IL_062a: conv.r8 + IL_062b: div + IL_062c: stloc.s V_54 + IL_062e: leave.s IL_064e } // end .try finally { - IL_067e: ldloc.s V_61 - IL_0680: isinst [mscorlib]System.IDisposable - IL_0685: stloc.s V_67 - IL_0687: ldloc.s V_67 - IL_0689: brfalse.s IL_068d + IL_0630: ldloc.s V_53 + IL_0632: isinst [mscorlib]System.IDisposable + IL_0637: stloc.s V_59 + IL_0639: ldloc.s V_59 + IL_063b: brfalse.s IL_063f - IL_068b: br.s IL_068f + IL_063d: br.s IL_0641 - IL_068d: br.s IL_0699 + IL_063f: br.s IL_064b .line 100001,100001 : 0,0 '' - IL_068f: ldloc.s V_67 - IL_0691: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_0696: ldnull - IL_0697: pop - IL_0698: endfinally + IL_0641: ldloc.s V_59 + IL_0643: callvirt instance void [mscorlib]System.IDisposable::Dispose() + IL_0648: ldnull + IL_0649: pop + IL_064a: endfinally .line 100001,100001 : 0,0 '' - IL_0699: ldnull - IL_069a: pop - IL_069b: endfinally + IL_064b: ldnull + IL_064c: pop + IL_064d: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_069c: ldloc.s V_62 - IL_069e: dup - IL_069f: stsfld float64 ''.$Linq101Aggregates01::averageLength@103 - IL_06a4: stloc.s averageLength + IL_064e: ldloc.s V_54 + IL_0650: dup + IL_0651: stsfld float64 ''.$Linq101Aggregates01::averageLength@103 + IL_0656: stloc.s averageLength .line 111,117 : 1,21 '' - IL_06a6: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_06ab: stloc.s V_68 - IL_06ad: ldloc.s V_68 - IL_06af: ldloc.s V_68 - IL_06b1: ldloc.s V_68 - IL_06b3: ldloc.s V_68 - IL_06b5: ldloc.s V_68 - IL_06b7: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_06bc: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_06c1: ldloc.s V_68 - IL_06c3: newobj instance void Linq101Aggregates01/categories6@113::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_06c8: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0658: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_065d: stloc.s V_60 + IL_065f: ldloc.s V_60 + IL_0661: ldloc.s V_60 + IL_0663: ldloc.s V_60 + IL_0665: ldloc.s V_60 + IL_0667: ldloc.s V_60 + IL_0669: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_066e: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0673: ldloc.s V_60 + IL_0675: newobj instance void Linq101Aggregates01/categories6@113::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_067a: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_06cd: newobj instance void Linq101Aggregates01/'categories6@114-1'::.ctor() - IL_06d2: newobj instance void Linq101Aggregates01/'categories6@114-2'::.ctor() - IL_06d7: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_067f: newobj instance void Linq101Aggregates01/'categories6@114-1'::.ctor() + IL_0684: newobj instance void Linq101Aggregates01/'categories6@114-2'::.ctor() + IL_0689: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_06dc: ldloc.s V_68 - IL_06de: newobj instance void Linq101Aggregates01/'categories6@114-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_06e3: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_068e: ldloc.s V_60 + IL_0690: newobj instance void Linq101Aggregates01/'categories6@114-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_0695: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_06e8: newobj instance void Linq101Aggregates01/'categories6@116-4'::.ctor() - IL_06ed: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_069a: newobj instance void Linq101Aggregates01/'categories6@116-4'::.ctor() + IL_069f: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_06f2: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_06f7: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_06fc: dup - IL_06fd: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories6@111 - IL_0702: stloc.s categories6 - IL_0704: ret + IL_06a4: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_06a9: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_06ae: dup + IL_06af: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories6@111 + IL_06b4: stloc.s categories6 + IL_06b6: ret } // end of method $Linq101Aggregates01::main@ } // end of class ''.$Linq101Aggregates01 diff --git a/tests/fsharpqa/Source/Conformance/Expressions/SyntacticSugar/Slices04.fs b/tests/fsharpqa/Source/Conformance/Expressions/SyntacticSugar/Slices04.fs index 061912d8962..1aed204e3d8 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/SyntacticSugar/Slices04.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/SyntacticSugar/Slices04.fs @@ -148,18 +148,18 @@ if f.LastLB2 <> None then exit 1 if f.LastUB2 <> None then exit 1 let _ = f.[['a'; 'b'], *] -if f.LastI1 <> Seq.ofList ['a'; 'b'] then exit 1 +if Seq.toList f.LastI1 <> ['a'; 'b'] then exit 1 if f.LastLB2 <> None then exit 1 if f.LastUB2 <> None then exit 1 f.[['t'; 'g'], *] <- [['f']] -if f.LastI1 <> Seq.ofList ['t'; 'g'] then exit 1 +if Seq.toList f.LastI1 <> ['t'; 'g'] then exit 1 if f.LastLB2 <> None then exit 1 if f.LastUB2 <> None then exit 1 if f.LastV2D <> [['f']] then exit 1 let _ = f.[*, ['c'; 'd']] -if f.LastI2 <> Seq.ofList ['c'; 'd'] then exit 1 +if Seq.toList f.LastI2 <> ['c'; 'd'] then exit 1 if f.LastLB1 <> None then exit 1 if f.LastUB1 <> None then exit 1 diff --git a/tests/fsharpqa/Source/Misc/LongSourceFile01.fs b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs index 0cf4c3e3e84..a7645182481 100644 --- a/tests/fsharpqa/Source/Misc/LongSourceFile01.fs +++ b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs @@ -247,6 +247,194 @@ Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityC Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] Structural[T]() Microsoft.FSharp.Collections.HashIdentity: System.String ToString() Microsoft.FSharp.Collections.HashIdentity: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Int32 get_HaltedIdx() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: TResult get_Result() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void OnDispose() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState]: Void set_Result(TResult) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Int32 get_HaltedIdx() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: TResult get_Result() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState]: Void set_Result(TResult) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Void .ctor(Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity, TState) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState]: Void OnDispose() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: Void .ctor(Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity, TState) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Value`1[a]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Value`1[a]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Value`1[a]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Value`1[a]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Value`1[a]: Void .ctor(a) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Value`1[a]: a _1 +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: Void .ctor(a, b) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: a _1 +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b]: b _2 +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: Void .ctor(a, b, c) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: a _1 +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: b _2 +Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c]: c _3 +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithPostProcessing`3[T,TResult,TState] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqConsumerWithState`3[T,TResult,TState] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+SeqTransformActivityWithPostProcessing`3[T,TResult,TState] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Transform`3[T,TResult,TState] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Value`1[a] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`2[a,b] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: Microsoft.FSharp.Collections.IConsumableSeqModule+Core+Values`3[a,b,c] +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule+Core: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean Contains[T](T, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean Exists2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean ForAll2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Boolean IsEmpty[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Int32 GetHashCode() +Microsoft.FSharp.Collections.IConsumableSeqModule: Int32 Length[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.FSharpList`1[T] ToList[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.IConsumableSeqModule+Core +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[System.Int32,a]] Indexed[a](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[a]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[T1,T2]] AllPairs[T1,T2](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T2]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[T1,T2]] Zip[T1,T2](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T2]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[TKey,Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]]] GroupByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[TKey,Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]]] GroupByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[TKey,System.Int32]] CountByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`2[TKey,System.Int32]] CountByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[System.Tuple`3[T1,T2,T3]] Zip3[T1,T2,T3](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T2], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T3]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult] Collect[T,TCollection,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TCollection], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult] Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TState] ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], TState) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TState] Scan[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T[]] ChunkBySize[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T[]] SplitInto[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T[]] Windowed[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Append[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Cache[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Cast[T](System.Collections.IEnumerable) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Concat[TCollection,T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TCollection]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Delay[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] DistinctBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Distinct[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Empty[T]() +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Except[T](System.Collections.Generic.IEnumerable`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Filter[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] InitializeInfinite[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Initialize[T](Int32, Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] OfArray[T](T[]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] OfList[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] OfResizeArrayUnchecked[T](System.Collections.Generic.List`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] OfSeq[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Permute[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Replicate[T](Int32, T) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Reverse[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Singleton[T](T) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] SkipWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Skip[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] SortByDescending[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] SortDescending[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Sort[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Tail[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Take[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Truncate[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Unfold[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[V] Map2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[V] MapIndexed2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[W] Map3[T,TResult,V,W](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[V,W]]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[V]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[b] Choose[a,b](Microsoft.FSharp.Core.FSharpFunc`2[a,Microsoft.FSharp.Core.FSharpOption`1[b]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[a]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[b] MapIndexed[a,b](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[a,b]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[a]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[TResult] TryPick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFind[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryHead[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryItem[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: System.String ToString() +Microsoft.FSharp.Collections.IConsumableSeqModule: System.Tuple`2[Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult],TState] MapFoldBack[T,TState,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,System.Tuple`2[TResult,TState]]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], TState) +Microsoft.FSharp.Collections.IConsumableSeqModule: System.Tuple`2[Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult],TState] MapFold[T,TState,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Tuple`2[TResult,TState]]], TState, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: System.Type GetType() +Microsoft.FSharp.Collections.IConsumableSeqModule: T Average[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T ExactlyOne[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T FindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Find[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Head[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Item[T](Int32, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Last[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Max[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Min[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T ReduceBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T Sum[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: TResult Pick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: TState Fold2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TState]]], TState, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T2]) +Microsoft.FSharp.Collections.IConsumableSeqModule: TState FoldBack2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T2], TState) +Microsoft.FSharp.Collections.IConsumableSeqModule: TState FoldBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], TState) +Microsoft.FSharp.Collections.IConsumableSeqModule: TState Fold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: T[] ToArray[T](Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Void Iterate2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Void IterateIndexed2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.Unit]]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Void IterateIndexed[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.IConsumableSeqModule: Void Iterate[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) +Microsoft.FSharp.Collections.ListModule: Boolean Contains[T](T, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ListModule: Boolean Exists2[T1,T2](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,System.Boolean]], Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2]) Microsoft.FSharp.Collections.ListModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T]) @@ -342,6 +530,56 @@ Microsoft.FSharp.Collections.MapModule: TResult Pick[TKey,T,TResult](Microsoft.F Microsoft.FSharp.Collections.MapModule: TState FoldBack[TKey,T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TKey,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], Microsoft.FSharp.Collections.FSharpMap`2[TKey,T], TState) Microsoft.FSharp.Collections.MapModule: TState Fold[TKey,T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[TKey,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]]], TState, Microsoft.FSharp.Collections.FSharpMap`2[TKey,T]) Microsoft.FSharp.Collections.MapModule: Void Iterate[TKey,T](Microsoft.FSharp.Core.FSharpFunc`2[TKey,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Collections.FSharpMap`2[TKey,T]) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Void .ctor() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`1[T]: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,TResult]: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.Core+NoValue: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Core+NoValue: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Core+NoValue: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Core+NoValue: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Core: Microsoft.FSharp.Collections.SeqComposition.Core+NoValue +Microsoft.FSharp.Collections.SeqComposition.Core: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Core: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Int32 HaltedIdx +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Int32 get_HaltedIdx() +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: TResult Result +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: TResult get_Result() +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Void .ctor(TResult) +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Void set_Result(TResult) +Microsoft.FSharp.Collections.SeqComposition.ISeqConsumer: Void ListenForStopFurtherProcessing(System.Action`1[System.Int32]) +Microsoft.FSharp.Collections.SeqComposition.ISeqConsumer: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[TResult] Transform[TResult](Microsoft.FSharp.Collections.SeqComposition.ISeqTransform`2[T,TResult]) +Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]: TResult Fold[TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]]) +Microsoft.FSharp.Collections.SeqComposition.ISeqTransform`2[T,TResult]: Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[T,V] Compose[V](Microsoft.FSharp.Collections.SeqComposition.ISeqConsumer, Int32, Microsoft.FSharp.Collections.SeqComposition.SeqConsumerActivity`2[TResult,V]) +Microsoft.FSharp.Collections.SeqModule: Boolean Contains[T](T, System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Boolean Equals(System.Object) Microsoft.FSharp.Collections.SeqModule: Boolean Exists2[T1,T2](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,System.Boolean]], System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2]) Microsoft.FSharp.Collections.SeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) @@ -787,7 +1025,10 @@ Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Boolean Equal Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Boolean get_CheckClose() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Int32 GenerateNext(System.Collections.Generic.IEnumerable`1[T] ByRef) Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Int32 GetHashCode() +Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Int32 Length() +Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T] Append(Microsoft.FSharp.Collections.SeqComposition.IConsumableSeq`1[T]) Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.Collections.Generic.IEnumerator`1[T] GetFreshEnumerator() +Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.Collections.Generic.IEnumerable`1[T] GetRaw() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.String ToString() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.Type GetType() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: T LastGenerated