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
+
+ [