From 8aff77e2a349395bf260722e2530d000824143d0 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 13 Mar 2017 20:06:20 +1100 Subject: [PATCH 01/83] Added ISeq module --- .../SurfaceArea.net40.fs | 193 ++ src/fsharp/FSharp.Core/FSharp.Core.fsproj | 6 + src/fsharp/FSharp.Core/iseq.fs | 1725 +++++++++++++++++ src/fsharp/FSharp.Core/iseq.fsi | 362 ++++ 4 files changed, 2286 insertions(+) create mode 100644 src/fsharp/FSharp.Core/iseq.fs create mode 100644 src/fsharp/FSharp.Core/iseq.fsi diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs index 0fdcc27abe..dd26877111 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs @@ -280,6 +280,199 @@ 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.ISeqModule+Core+Activity: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnDispose() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+IOutOfBand: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]: ISeq`1 PushTransform[TResult](TransformFactory`2) +Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]: TResult Fold[TResult,TState](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]]) +Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Activity`2 Compose[V](IOutOfBand, Int32, Activity`2) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void .ctor(Activity, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnDispose() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void .ctor(Activity, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Void .ctor(a) +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: a _1 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: Void .ctor(a, b) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: a _1 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: b _2 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: Void .ctor(a, b, c) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: a _1 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: b _2 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: c _3 +Microsoft.FSharp.Collections.ISeqModule+Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Activity +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+IOutOfBand +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+NoValue +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c] +Microsoft.FSharp.Collections.ISeqModule+Core: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule: Boolean Contains[T](T, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule: Boolean Exists2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Append[T](ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Choose[a,b](Microsoft.FSharp.Core.FSharpFunc`2[a,Microsoft.FSharp.Core.FSharpOption`1[b]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Concat[TCollection,T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Delay[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 DistinctBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Distinct[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Empty[T]() +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Except[T](System.Collections.Generic.IEnumerable`1[T], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Filter[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 GroupByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 GroupByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Indexed[a](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 InitializeInfinite[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Initialize[T](Int32, Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map3[T,TResult,V,W](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[V,W]]], ISeq`1, ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 MapIndexed2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 MapIndexed[a,b](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[a,b]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfArray[T](T[]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfList[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfResizeArrayUnchecked[T](System.Collections.Generic.List`1[T]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfSeq[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Pairwise[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Permute[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Reverse[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], ISeq`1, TState) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Scan[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SkipWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Skip[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Sort[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Tail[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Take[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Truncate[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Unfold[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Windowed[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Zip[T1,T2](ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule: Int32 Length[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.ISeqModule+Core +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[TResult] TryPick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFind[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryHead[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryItem[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule: T Average[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T ExactlyOne[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Head[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Last[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Max[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Min[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T ReduceBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Sum[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: 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, ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: TState FoldBack2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], ISeq`1, ISeq`1, TState) +Microsoft.FSharp.Collections.ISeqModule: TState FoldBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], ISeq`1, TState) +Microsoft.FSharp.Collections.ISeqModule: TState Fold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T[] ToArray[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Void Iterate2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.Unit]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: 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]]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Void IterateIndexed[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Void Iterate[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit], ISeq`1) 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]) diff --git a/src/fsharp/FSharp.Core/FSharp.Core.fsproj b/src/fsharp/FSharp.Core/FSharp.Core.fsproj index ee0bd8f50e..1f6a7dc83e 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.fsproj +++ b/src/fsharp/FSharp.Core/FSharp.Core.fsproj @@ -100,6 +100,12 @@ Collections/seqcore.fs + + Collections/iseq.fsi + + + Collections/iseq.fs + Collections/seq.fsi diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs new file mode 100644 index 0000000000..d99e39639c --- /dev/null +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -0,0 +1,1725 @@ +// 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.Basics + + [] + module ISeq = + open IEnumerator + + module Core = + [] + type NoValue = struct end + + [] + type Value<'a> = + val mutable _1 : 'a + new (a:'a) = { _1 = a } + + [] + type Values<'a,'b> = + val mutable _1 : 'a + val mutable _2 : 'b + new (a:'a, b: 'b) = { _1 = a; _2 = b } + + [] + type Values<'a,'b,'c> = + val mutable _1 : 'a + val mutable _2 : 'b + val mutable _3 : 'c + new (a:'a, b:'b, c:'c) = { _1 = a; _2 = b; _3 = c } + + type PipeIdx = int + + type IOutOfBand = + abstract StopFurtherProcessing : PipeIdx -> unit + + [] + type Activity() = + abstract ChainComplete : stopTailCall:byref * PipeIdx -> unit + abstract ChainDispose : stopTailCall:byref -> unit + + [] + type Activity<'T,'U> () = + inherit Activity() + abstract ProcessNext : input:'T -> bool + + [] + type Transform<'T,'U,'State> = + inherit Activity<'T,'U> + + new (next:Activity, initState:'State) = { + inherit Activity<'T,'U> () + State = initState + Next = next + } + + val mutable State : 'State + val Next : Activity + + override this.ChainComplete (stopTailCall, terminatingIdx) = + this.Next.ChainComplete (&stopTailCall, terminatingIdx) + override this.ChainDispose stopTailCall = + this.Next.ChainDispose (&stopTailCall) + + [] + type TransformWithPostProcessing<'T,'U,'State>(next:Activity, initState:'State) = + inherit Transform<'T,'U,'State>(next, initState) + + abstract OnComplete : PipeIdx -> unit + abstract OnDispose : unit -> unit + + override this.ChainComplete (stopTailCall, terminatingIdx) = + this.OnComplete terminatingIdx + this.Next.ChainComplete (&stopTailCall, terminatingIdx) + override this.ChainDispose stopTailCall = + try this.OnDispose () + finally this.Next.ChainDispose (&stopTailCall) + + [] + type Folder<'T,'Result,'State> = + inherit Activity<'T,'T> + + val mutable Result : 'Result + val mutable State : 'State + + val mutable HaltedIdx : int + member this.StopFurtherProcessing pipeIdx = this.HaltedIdx <- pipeIdx + interface IOutOfBand with + member this.StopFurtherProcessing pipeIdx = this.StopFurtherProcessing pipeIdx + + new (initalResult,initState) = { + inherit Activity<'T,'T>() + State = initState + HaltedIdx = 0 + Result = initalResult + } + + override this.ChainComplete (_,_) = () + override this.ChainDispose _ = () + + [] + type FolderWithPostProcessing<'T,'Result,'State>(initResult,initState) = + inherit Folder<'T,'Result,'State>(initResult,initState) + + abstract OnComplete : PipeIdx -> unit + abstract OnDispose : unit -> unit + + override this.ChainComplete (stopTailCall, terminatingIdx) = + this.OnComplete terminatingIdx + override this.ChainDispose _ = + this.OnDispose () + + [] + type TransformFactory<'T,'U> () = + abstract Compose<'V> : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> + + type ISeq<'T> = + inherit IEnumerable<'T> + abstract member PushTransform<'U> : TransformFactory<'T,'U> -> ISeq<'U> + abstract member Fold<'Result,'State> : f:(PipeIdx->Folder<'T,'Result,'State>) -> 'Result + + 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 + // ineffictive ** + let inline avoid boolean = match boolean with true -> true | false -> false + + module internal Upcast = + // The f# compiler outputs unnecessary unbox.any calls in upcasts. If this functionality + // is fixed with the compiler then these functions can be removed. + let inline seq<'T,'seq when 'seq :> ISeq<'T> and 'seq : not struct> (t:'seq) : ISeq<'T> = (# "" t : ISeq<'T> #) + let inline enumerable<'T,'enumerable when 'enumerable :> IEnumerable<'T> and 'enumerable : not struct> (t:'enumerable) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) + let inline enumerator<'T,'enumerator when 'enumerator :> IEnumerator<'T> and 'enumerator : not struct> (t:'enumerator) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) + let inline enumeratorNonGeneric<'enumerator when 'enumerator :> IEnumerator and 'enumerator : not struct> (t:'enumerator) : IEnumerator = (# "" t : IEnumerator #) + let inline outOfBand<'outOfBand when 'outOfBand :> IOutOfBand and 'outOfBand : not struct> (t:'outOfBand) : IOutOfBand = (# "" t : IOutOfBand #) + + let createFold (factory:TransformFactory<_,_>) (folder:Folder<_,_,_>) pipeIdx = + factory.Compose (Upcast.outOfBand folder) pipeIdx folder + + let inline 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) } + + type ComposedFactory<'T,'U,'V> private (first:TransformFactory<'T,'U>, second:TransformFactory<'U,'V>) = + inherit TransformFactory<'T,'V>() + + override this.Compose<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = + first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) + + static member Combine (first:TransformFactory<'T,'U>) (second:TransformFactory<'U,'V>) : TransformFactory<'T,'V> = + upcast ComposedFactory(first, second) + + and IdentityFactory<'T> private () = + inherit TransformFactory<'T,'T> () + static let singleton : TransformFactory<'T,'T> = upcast (IdentityFactory<'T>()) + override __.Compose<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next + static member Instance = singleton + + and ISkipable = + // Seq.init(Infinite)? lazily uses Current. The only ISeq 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 Result<'T>() = + inherit Folder<'T,'T,NoValue>(Unchecked.defaultof<'T>,Unchecked.defaultof) + + member val SeqState = SeqProcessNextStates.NotStarted with get, set + + override this.ProcessNext (input:'T) : bool = + this.Result <- input + true + + module Fold = + type IIterate<'T> = + abstract Iterate<'U,'Result,'State> : outOfBand:Folder<'U,'Result,'State> -> consumer:Activity<'T,'U> -> unit + + [] + type enumerable<'T> (enumerable:IEnumerable<'T>) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = + use enumerator = enumerable.GetEnumerator () + let rec iterate () = + if enumerator.MoveNext () then + consumer.ProcessNext enumerator.Current |> ignore + if outOfBand.HaltedIdx = 0 then + iterate () + iterate () + + [] + type Array<'T> (array:array<'T>) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = + let array = array + let rec iterate idx = + if idx < array.Length then + consumer.ProcessNext array.[idx] |> ignore + if outOfBand.HaltedIdx = 0 then + iterate (idx+1) + iterate 0 + + [] + type resizeArray<'T> (array:ResizeArray<'T>) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = + let array = array + let rec iterate idx = + if idx < array.Count then + consumer.ProcessNext array.[idx] |> ignore + if outOfBand.HaltedIdx = 0 then + iterate (idx+1) + iterate 0 + + [] + type List<'T> (alist:list<'T>) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = + let rec iterate lst = + match lst with + | hd :: tl -> + consumer.ProcessNext hd |> ignore + if outOfBand.HaltedIdx = 0 then + iterate tl + | _ -> () + iterate alist + + [] + type unfold<'S,'T> (generator:'S->option<'T*'S>, state:'S) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = + let generator = generator + let rec iterate current = + match generator current with + | Some (item, next) -> + consumer.ProcessNext item |> ignore + if outOfBand.HaltedIdx = 0 then + iterate next + | _ -> () + iterate state + + [] + type init<'T> (f:int->'T, terminatingIdx:int) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = + let terminatingIdx = terminatingIdx + let f = f + + let firstIdx = + match box consumer with + | :? ISkipable as skipping -> + let rec skip idx = + if idx = terminatingIdx || outOfBand.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 outOfBand.HaltedIdx = 0 then + iterate (idx+1) + else + idx + else + idx + + let finalIdx = iterate firstIdx + if outOfBand.HaltedIdx = 0 && finalIdx = System.Int32.MaxValue then + raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + + let execute (createFolder:PipeIdx->Folder<'U,'Result,'State>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (executeOn:#IIterate<'T>) = + let mutable stopTailCall = () + let result = createFolder (pipeIdx+1) + let consumer = createFold transformFactory result pipeIdx + try + executeOn.Iterate result consumer + consumer.ChainComplete (&stopTailCall, result.HaltedIdx) + result.Result + finally + consumer.ChainDispose (&stopTailCall) + + let executeThin (createFolder:PipeIdx->Folder<'T,'Result,'State>) (executeOn:#IIterate<'T>) = + let mutable stopTailCall = () + let result = createFolder 1 + try + executeOn.Iterate result result + result.ChainComplete (&stopTailCall, result.HaltedIdx) + result.Result + finally + result.ChainDispose (&stopTailCall) + + module Enumerable = + type Empty<'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 Empty<'T> ()) + static member Element = element + + [] + type EnumeratorBase<'T>(result:Result<'T>, activity:Activity) = + interface IDisposable with + member __.Dispose () : unit = + let mutable stopTailCall = () + activity.ChainDispose (&stopTailCall) + + interface IEnumerator with + member this.Current : obj = box ((Upcast.enumerator this)).Current + member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)" + member __.Reset () : unit = noReset () + + interface IEnumerator<'T> with + member __.Current = + if result.SeqState = SeqProcessNextStates.InProcess then result.Result + else + match result.SeqState with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> failwith "library implementation error: all states should have been handled" + + and [] EnumerableBase<'T> () = + let derivedClassShouldImplement () = + failwith "library implementation error: derived class should implement (should be abstract)" + + abstract member Append : (ISeq<'T>) -> ISeq<'T> + + default this.Append source = Upcast.seq (AppendEnumerable [this; source]) + + interface IEnumerable with + member this.GetEnumerator () : IEnumerator = + let genericEnumerable = Upcast.enumerable this + let genericEnumerator = genericEnumerable.GetEnumerator () + Upcast.enumeratorNonGeneric genericEnumerator + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () + + interface ISeq<'T> with + member __.PushTransform _ = derivedClassShouldImplement () + member __.Fold _ = derivedClassShouldImplement () + + and Enumerator<'T,'U>(source:IEnumerator<'T>, activity:Activity<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, activity) + + let rec moveNext () = + if (result.HaltedIdx = 0) && source.MoveNext () then + if activity.ProcessNext source.Current then + true + else + moveNext () + else + result.SeqState <- SeqProcessNextStates.Finished + let mutable stopTailCall = () + activity.ChainComplete (&stopTailCall, result.HaltedIdx) + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + interface IDisposable with + member __.Dispose () = + try + source.Dispose () + finally + let mutable stopTailCall = () + activity.ChainDispose (&stopTailCall) + + and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), createFold current result pipeIdx, result)) + + interface ISeq<'U> with + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next, pipeIdx+1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + Fold.execute f current pipeIdx (Fold.enumerable enumerable) + + and EnumerableThin<'T>(enumerable:IEnumerable<'T>) = + inherit EnumerableBase<'T>() + + interface IEnumerable<'T> with + member this.GetEnumerator () = enumerable.GetEnumerator () + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new Enumerable<'T,'U>(enumerable, next, 1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + Fold.executeThin f (Fold.enumerable enumerable) + + and SeqDelayed<'T>(delayed:unit->ISeq<'T>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'T>() + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = (delayed()).GetEnumerator () + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new SeqDelayed<'U>((fun () -> (delayed()).PushTransform next), pipeIdx+1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + (delayed()).Fold f + + and ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = + let mutable state = SeqProcessNextStates.NotStarted + let main = sources.GetEnumerator () + + let mutable active = EmptyEnumerators.Element + + let rec moveNext () = + if active.MoveNext () then + true + elif main.MoveNext () then + active.Dispose () + active <- main.Current.GetEnumerator () + moveNext () + else + state <- SeqProcessNextStates.Finished + false + + interface IEnumerator<'T> with + member __.Current = + if state = SeqProcessNextStates.InProcess then active.Current + else + match state with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> failwith "library implementation error: all states should have been handled" + + interface IEnumerator with + member this.Current = box ((Upcast.enumerator this)).Current + member __.MoveNext () = + state <- SeqProcessNextStates.InProcess + moveNext () + member __.Reset () = noReset () + + interface IDisposable with + member __.Dispose () = + main.Dispose () + active.Dispose () + + and AppendEnumerable<'T> (sources:list>) = + inherit EnumerableBase<'T>() + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = + Upcast.enumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) + + override this.Append source = + Upcast.seq (AppendEnumerable (source::sources)) + + interface ISeq<'T> with + member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (Enumerable<'T,'V>(this, next, 1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + Fold.executeThin f (Fold.enumerable this) + + and ConcatEnumerable<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = + inherit EnumerableBase<'T>() + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = + Upcast.enumerator (new ConcatEnumerator<_,_> (sources)) + + interface ISeq<'T> with + member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (Enumerable<'T,'V>(this, next, 1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + Fold.executeThin f (Fold.enumerable this) + + let create enumerable current = + Upcast.seq (Enumerable (enumerable, current, 1)) + + module EmptyEnumerable = + type Enumerable<'T> () = + inherit Enumerable.EnumerableBase<'T>() + + static let singleton = Enumerable<'T>() :> ISeq<'T> + static member Instance = singleton + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = IEnumerator.Empty<'T>() + + override this.Append source = + Upcast.seq (Enumerable.EnumerableThin<'T> source) + + interface ISeq<'T> with + member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (Enumerable.Enumerable<'T,'V>(this, next, 1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + Fold.executeThin f (Fold.enumerable this) + + module Array = + type Enumerator<'T,'U>(array:array<'T>, activity:Activity<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, activity) + + let mutable idx = 0 + + let rec moveNext () = + if (result.HaltedIdx = 0) && idx < array.Length then + idx <- idx+1 + if activity.ProcessNext array.[idx-1] then + true + else + moveNext () + else + result.SeqState <- SeqProcessNextStates.Finished + let mutable stopTailCall = () + activity.ChainComplete (&stopTailCall, result.HaltedIdx) + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type Enumerable<'T,'U>(array:array<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit Enumerable.EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new Enumerator<'T,'U>(array, createFold transformFactory result pipeIdx, result)) + + interface ISeq<'U> with + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new Enumerable<'T,'V>(array, ComposedFactory.Combine transformFactory next, 1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + Fold.execute f transformFactory pipeIdx (Fold.Array array) + + module ResizeArray = + type Enumerator<'T,'U>(array:ResizeArray<'T>, activity:Activity<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, activity) + + let mutable idx = 0 + + let rec moveNext () = + if (result.HaltedIdx = 0) && idx < array.Count then + idx <- idx+1 + if activity.ProcessNext array.[idx-1] then + true + else + moveNext () + else + result.SeqState <- SeqProcessNextStates.Finished + let mutable stopTailCall = () + activity.ChainComplete (&stopTailCall, result.HaltedIdx) + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type Enumerable<'T,'U>(resizeArray:ResizeArray<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit Enumerable.EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new Enumerator<'T,'U>(resizeArray, createFold transformFactory result pipeIdx, result)) + + interface ISeq<'U> with + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new Enumerable<'T,'V>(resizeArray, ComposedFactory.Combine transformFactory next, 1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + Fold.execute f transformFactory pipeIdx (Fold.resizeArray resizeArray) + + module List = + type Enumerator<'T,'U>(alist:list<'T>, activity:Activity<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, activity) + + 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 <- SeqProcessNextStates.Finished + let mutable stopTailCall = () + activity.ChainComplete (&stopTailCall, result.HaltedIdx) + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext list + + type Enumerable<'T,'U>(alist:list<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit Enumerable.EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new Enumerator<'T,'U>(alist, createFold transformFactory result pipeIdx, result)) + + interface ISeq<'U> with + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + Fold.execute f transformFactory pipeIdx (Fold.List alist) + + let create alist current = + Upcast.seq (Enumerable(alist, current, 1)) + + module Unfold = + type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, activity:Activity<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, activity) + + let mutable current = state + + let rec moveNext () = + match result.HaltedIdx, generator current with + | 0, Some (item, nextState) -> + current <- nextState + if activity.ProcessNext item then + true + else + moveNext () + | _ -> false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit Enumerable.EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, createFold transformFactory result pipeIdx, result)) + + interface ISeq<'U> with + member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + Fold.execute f transformFactory pipeIdx (Fold.unfold (generator, state)) + + module Init = + // 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. + + let getTerminatingIdx (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 Enumerator<'T,'U>(count:Nullable, f:int->'T, activity:Activity<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, activity) + + let isSkipping = + match box activity with + | :? ISkipable as skip -> skip.CanSkip + | _ -> fun () -> false + + let terminatingIdx = + getTerminatingIdx count + + let mutable maybeSkipping = true + let mutable idx = -1 + + let rec moveNext () = + if result.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 + moveNext () + elif activity.ProcessNext (f idx) then + true + else + moveNext () + elif result.HaltedIdx = 0 && idx = System.Int32.MaxValue then + raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + else + result.SeqState <- SeqProcessNextStates.Finished + let mutable stopTailCall = () + activity.ChainComplete (&stopTailCall, result.HaltedIdx) + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type Enumerable<'T,'U>(count:Nullable, f:int->'T, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit Enumerable.EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new Enumerator<'T,'U>(count, f, createFold transformFactory result pipeIdx, result)) + + interface ISeq<'U> with + member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + + member this.Fold<'Result,'State> (createResult:PipeIdx->Folder<'U,'Result,'State>) = + let terminatingIdx = getTerminatingIdx count + Fold.execute createResult transformFactory pipeIdx (Fold.init (f, terminatingIdx)) + + 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 () = () } + + type EnumerableDecider<'T>(count:Nullable, f:int->'T, pipeIdx:PipeIdx) = + inherit Enumerable.EnumerableBase<'T>() + + 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 ISeq<'T> with + member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (Enumerable<'T,'V>(count, f, next, pipeIdx+1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + Fold.executeThin f (Fold.enumerable (Upcast.enumerable this)) + + [] + let ofResizeArrayUnchecked (source:ResizeArray<'T>) : ISeq<'T> = + Upcast.seq (ResizeArray.Enumerable (source, IdentityFactory.Instance, 1)) + + [] + let ofArray (source:array<'T>) : ISeq<'T> = + checkNonNull "source" source + Upcast.seq (Array.Enumerable (source, IdentityFactory.Instance, 1)) + + [] + let ofList (source:list<'T>) : ISeq<'T> = + Upcast.seq (List.Enumerable (source, IdentityFactory.Instance, 1)) + + [] + let ofSeq (source:seq<'T>) : ISeq<'T> = + match source with + | :? ISeq<'T> as seq -> seq + | :? array<'T> as array -> ofArray array + | :? list<'T> as list -> ofList list + | null -> nullArg "source" + | _ -> Upcast.seq (Enumerable.EnumerableThin<'T> source) + + [] + let inline average (source:ISeq<'T>) = + source.Fold (fun _ -> + upcast { new FolderWithPostProcessing<'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:ISeq<'T>) = + source.Fold (fun _ -> + upcast { new FolderWithPostProcessing<'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 empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance + + [] + let exactlyOne (source:ISeq<'T>) : 'T = + source.Fold (fun pipeIdx -> + upcast { new FolderWithPostProcessing<'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.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 fold<'T,'State> (f:'State->'T->'State) (seed:'State) (source:ISeq<'T>) : 'State = + source.Fold (fun _ -> + upcast { new Folder<'T,'State,NoValue>(seed,Unchecked.defaultof) with + override this.ProcessNext value = + this.Result <- f this.Result value + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline fold2<'T1,'T2,'State> (folder:'State->'T1->'T2->'State) (state:'State) (source1:ISeq<'T1>) (source2: ISeq<'T2>) = + source1.Fold (fun pipeIdx -> + upcast { new FolderWithPostProcessing<_,'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.StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = () + override this.OnDispose () = this.State.Dispose () }) + + [] + let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = + Upcast.seq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance, 1)) + + [] + let initInfinite<'T> (f:int->'T) : ISeq<'T> = + Upcast.seq (new Init.EnumerableDecider<'T>(Nullable (), f, 1)) + + [] + let init<'T> (count:int) (f:int->'T) : ISeq<'T> = + if count < 0 then invalidArgInputMustBeNonNegative "count" count + elif count = 0 then empty else + Upcast.seq (new Init.EnumerableDecider<'T>(Nullable count, f, 1)) + + [] + let inline iter f (source:ISeq<'T>) = + source.Fold (fun _ -> + upcast { new Folder<'T,unit,NoValue> ((),Unchecked.defaultof) with + override this.ProcessNext value = + f value + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline iter2 (f:'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = + source1.Fold (fun pipeIdx -> + upcast { new FolderWithPostProcessing<'T,unit,IEnumerator<'U>> ((),source2.GetEnumerator()) with + override this.ProcessNext value = + if this.State.MoveNext() then + f value this.State.Current + else + this.StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = () + override this.OnDispose () = this.State.Dispose () }) + + [] + let inline iteri2 (f:int->'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = + source1.Fold (fun pipeIdx -> + upcast { new FolderWithPostProcessing<'T,unit,Values>>((),Values<_,_>(-1,source2.GetEnumerator())) with + override this.ProcessNext value = + if this.State._2.MoveNext() then + f this.State._1 value this.State._2.Current + this.State._1 <- this.State._1 + 1 + Unchecked.defaultof<_> + else + this.StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> + override this.OnComplete _ = () + override this.OnDispose () = this.State._2.Dispose () }) + + [] + let tryHead (source:ISeq<'T>) = + source.Fold (fun pipeIdx -> + upcast { new Folder<'T, Option<'T>,NoValue> (None,Unchecked.defaultof) with + override this.ProcessNext value = + this.Result <- Some value + this.StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let head (source:ISeq<_>) = + match tryHead source with + | None -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + | Some x -> x + + [] + let inline iteri f (source:ISeq<'T>) = + source.Fold (fun _ -> + { new Folder<'T,unit,int> ((),0) with + override this.ProcessNext value = + f this.State value + this.State <- this.State + 1 + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline except (itemsToExclude: seq<'T>) (source:ISeq<'T>) : ISeq<'T> when 'T:equality = + source.PushTransform { new TransformFactory<'T,'T>() with + override __.Compose _ _ next = + upcast { new Transform<'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 exists f (source:ISeq<'T>) = + source.Fold (fun pipeIdx -> + upcast { new Folder<'T, bool,NoValue> (false,Unchecked.defaultof) with + override this.ProcessNext value = + if f value then + this.Result <- true + this.StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline exists2 (predicate:'T->'U->bool) (source1:ISeq<'T>) (source2: ISeq<'U>) : bool = + source1.Fold (fun pipeIdx -> + upcast { new FolderWithPostProcessing<'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.StopFurtherProcessing pipeIdx + else + this.StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = () + override this.OnDispose () = this.State.Dispose () }) + + [] + let inline contains element (source:ISeq<'T>) = + source.Fold (fun pipeIdx -> + upcast { new Folder<'T, bool,NoValue> (false,Unchecked.defaultof) with + override this.ProcessNext value = + if element = value then + this.Result <- true + this.StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline forall predicate (source:ISeq<'T>) = + source.Fold (fun pipeIdx -> + upcast { new Folder<'T, bool,NoValue> (true,Unchecked.defaultof) with + override this.ProcessNext value = + if not (predicate value) then + this.Result <- false + this.StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline forall2 predicate (source1:ISeq<'T>) (source2:ISeq<'U>) : bool = + source1.Fold (fun pipeIdx -> + upcast { new FolderWithPostProcessing<'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.StopFurtherProcessing pipeIdx + else + this.StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.OnComplete _ = () + override this.OnDispose () = this.State.Dispose () }) + + [] + let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = + source.PushTransform { new TransformFactory<'T,'T>() with + override __.Compose _ _ next = + upcast { new Transform<'T,'V,NoValue>(next,Unchecked.defaultof) with + override __.ProcessNext input = + if f input then TailCall.avoid (next.ProcessNext input) + else false } } + + [] + let inline map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = + source.PushTransform { new TransformFactory<'T,'U>() with + override __.Compose _ _ next = + upcast { new Transform<'T,'V,NoValue>(next,Unchecked.defaultof) with + override __.ProcessNext input = + TailCall.avoid (next.ProcessNext (f input)) } } + + [] + let inline mapi f (source:ISeq<_>) = + source.PushTransform { new TransformFactory<'T,'U>() with + override __.Compose _ _ next = + upcast { new Transform<'T,'V,int>(next, -1) with + override this.ProcessNext (input:'T) : bool = + this.State <- this.State + 1 + TailCall.avoid (next.ProcessNext (f this.State input)) } } + + [] + let inline map2<'T,'U,'V> (map:'T->'U->'V) (source1:ISeq<'T>) (source2:ISeq<'U>) : ISeq<'V> = + source1.PushTransform { new TransformFactory<'T,'V>() with + override __.Compose outOfBand pipeIdx (next:Activity<'V,'W>) = + upcast { new TransformWithPostProcessing<'T,'W, IEnumerator<'U>>(next, (source2.GetEnumerator ())) with + override this.ProcessNext input = + if this.State.MoveNext () then + TailCall.avoid (next.ProcessNext (map input this.State.Current)) + else + outOfBand.StopFurtherProcessing pipeIdx + false + override this.OnComplete _ = () + override this.OnDispose () = this.State.Dispose () }} + + [] + let inline mapi2<'T,'U,'V> (map:int->'T->'U->'V) (source1:ISeq<'T>) (source2:ISeq<'U>) : ISeq<'V> = + source1.PushTransform { new TransformFactory<'T,'V>() with + override __.Compose<'W> outOfBand pipeIdx next = + upcast { new TransformWithPostProcessing<'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 (map idx t u.Current)) + else + outOfBand.StopFurtherProcessing pipeIdx + false + override this.OnDispose () = this.State._2.Dispose () + override this.OnComplete _ = () }} + + [] + let inline map3<'T,'U,'V,'W>(map:'T->'U->'V->'W) (source1:ISeq<'T>) (source2:ISeq<'U>) (source3:ISeq<'V>) : ISeq<'W> = + source1.PushTransform { new TransformFactory<'T,'W>() with + override __.Compose<'X> outOfBand pipeIdx next = + upcast { new TransformWithPostProcessing<'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 (map 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 compareWith (f:'T->'T->int) (source1:ISeq<'T>) (source2:ISeq<'T>) : int = + source1.Fold (fun pipeIdx -> + upcast { new FolderWithPostProcessing<'T,int,IEnumerator<'T>>(0,source2.GetEnumerator()) with + override this.ProcessNext value = + if not (this.State.MoveNext()) then + this.Result <- 1 + this.StopFurtherProcessing pipeIdx + else + let c = f value this.State.Current + if c <> 0 then + this.Result <- c + this.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 choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = + source.PushTransform { new TransformFactory<'T,'U>() with + override __.Compose _ _ next = + upcast { new Transform<'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 distinct (source:ISeq<'T>) : ISeq<'T> when 'T:equality = + source.PushTransform { new TransformFactory<'T,'T>() with + override __.Compose _ _ next = + upcast { new Transform<'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 distinctBy (keyf:'T->'Key) (source:ISeq<'T>) :ISeq<'T> when 'Key:equality = + source.PushTransform { new TransformFactory<'T,'T>() with + override __.Compose _ _ next = + upcast { new Transform<'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:ISeq<'T>) : 'T when 'T:comparison = + source.Fold (fun _ -> + upcast { new FolderWithPostProcessing<'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:ISeq<'T>) : 'T when 'U:comparison = + source.Fold (fun _ -> + upcast { new FolderWithPostProcessing<'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:ISeq<'T>) : 'T when 'T:comparison = + source.Fold (fun _ -> + upcast { new FolderWithPostProcessing<'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:ISeq<'T>) : 'T = + source.Fold (fun _ -> + upcast { new FolderWithPostProcessing<'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 pairwise (source:ISeq<'T>) : ISeq<'T*'T> = + source.PushTransform { new TransformFactory<'T,'T * 'T>() with + override __.Compose _ _ next = + upcast { new Transform<'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 reduce (f:'T->'T->'T) (source: ISeq<'T>) : 'T = + source.Fold (fun _ -> + upcast { new FolderWithPostProcessing<'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 inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = + source.PushTransform { new TransformFactory<'T,'State>() with + override __.Compose _ _ next = + upcast { new Transform<'T,'V,'State>(next, initialState) with + override this.ProcessNext (input:'T) : bool = + this.State <- folder this.State input + TailCall.avoid (next.ProcessNext this.State) } } + + [] + let skip (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = + source.PushTransform { new TransformFactory<'T,'T>() with + override __.Compose _ _ next = + let mutable this = Unchecked.defaultof> + let skipper = + { new TransformWithPostProcessing<'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 + upcast this } + + [] + let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = + source.PushTransform { new TransformFactory<'T,'T>() with + override __.Compose _ _ next = + upcast { new Transform<'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:ISeq<'T>) = + source.Fold (fun _ -> + upcast { new Folder<'T,'T,NoValue> (LanguagePrimitives.GenericZero,Unchecked.defaultof) 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:ISeq<'T>) = + source.Fold (fun _ -> + upcast { new Folder<'T,'U,NoValue> (LanguagePrimitives.GenericZero<'U>,Unchecked.defaultof) with + override this.ProcessNext value = + this.Result <- Checked.(+) this.Result (f value) + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let take (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = + source.PushTransform { new TransformFactory<'T,'T>() with + member __.Compose outOfBand pipelineIdx next = + upcast { new TransformWithPostProcessing<'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 takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = + source.PushTransform { new TransformFactory<'T,'T>() with + member __.Compose outOfBand pipeIdx next = + upcast { new Transform<'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 tail (source:ISeq<'T>) : ISeq<'T> = + source.PushTransform { new TransformFactory<'T,'T>() with + member __.Compose _ _ next = + upcast { new TransformWithPostProcessing<'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 truncate (truncateCount:int) (source:ISeq<'T>) : ISeq<'T> = + source.PushTransform { new TransformFactory<'T,'T>() with + member __.Compose outOfBand pipeIdx next = + upcast { new Transform<'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 indexed source = + mapi (fun i x -> i,x) source + + [] + let tryItem index (source:ISeq<'T>) = + if index < 0 then None else + source |> skip index |> tryHead + + [] + let inline tryPick f (source:ISeq<'T>) = + source.Fold (fun pipeIdx -> + upcast { new Folder<'T, Option<'U>,NoValue> (None,Unchecked.defaultof) with + override this.ProcessNext value = + match f value with + | (Some _) as some -> + this.Result <- some + this.StopFurtherProcessing pipeIdx + | None -> () + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline tryFind f (source:ISeq<'T>) = + source.Fold (fun pipeIdx -> + upcast { new Folder<'T, Option<'T>,NoValue> (None,Unchecked.defaultof) with + override this.ProcessNext value = + if f value then + this.Result <- Some value + this.StopFurtherProcessing pipeIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let inline tryFindIndex (predicate:'T->bool) (source:ISeq<'T>) : int option = + source.Fold (fun pipeIdx -> + { new Folder<'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.StopFurtherProcessing pipeIdx + else + this.State <- this.State + 1 + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let tryLast (source:ISeq<'T>) : 'T option = + source.Fold (fun _ -> + upcast { new FolderWithPostProcessing<'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 last (source:ISeq<_>) = + match tryLast source with + | None -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + | Some x -> x + + [] + let windowed (windowSize:int) (source:ISeq<'T>) : ISeq<'T[]> = + if windowSize <= 0 then + invalidArgFmt "windowSize" "{0}\nwindowSize = {1}" [|SR.GetString SR.inputMustBePositive; windowSize|] + + source.PushTransform { new TransformFactory<'T,'T[]>() with + member __.Compose outOfBand pipeIdx next = + upcast { + new Transform<'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 concat (sources:ISeq<#ISeq<'T>>) : ISeq<'T> = + Upcast.seq (Enumerable.ConcatEnumerable sources) + + [] + let append (source1:ISeq<'T>) (source2: ISeq<'T>) : ISeq<'T> = + match source1 with + | :? Enumerable.EnumerableBase<'T> as s -> s.Append source2 + | _ -> Upcast.seq (new Enumerable.AppendEnumerable<_>([source2; source1])) + + [] + let delay (delayed:unit->ISeq<'T>) = + Upcast.seq (Enumerable.SeqDelayed (delayed, 1)) + + module internal GroupBy = + let inline private impl (comparer:IEqualityComparer<'SafeKey>) (keyf:'T->'SafeKey) (getKey:'SafeKey->'Key) (source:ISeq<'T>) = + source.Fold (fun _ -> + upcast { new FolderWithPostProcessing<'T,ISeq<'Key*ISeq<'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 (keyf:'T->'Key) (source:ISeq<'T>) = + delay (fun () -> impl HashIdentity.Structural<'Key> keyf id source) + + let inline byRef (keyf:'T->'Key) (source:ISeq<'T>) = + delay (fun () -> impl (valueComparer<'Key> ()) (keyf >> Value) (fun v -> v._1) source) + + [] + let inline groupByVal<'T,'Key when 'Key : equality and 'Key : struct> (keyf:'T->'Key) (source:ISeq<'T>) = + GroupBy.byVal keyf source + + [] + let inline groupByRef<'T,'Key when 'Key : equality and 'Key : not struct> (keyf:'T->'Key) (source:ISeq<'T>) = + GroupBy.byRef keyf source + + module CountBy = + let inline private impl (comparer:IEqualityComparer<'SafeKey>) (keyf:'T->'SafeKey) (getKey:'SafeKey->'Key) (source:ISeq<'T>) = + source.Fold (fun _ -> + upcast { new FolderWithPostProcessing<'T,ISeq<'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 (keyf:'T->'Key) (source:ISeq<'T>) = + delay (fun () -> impl HashIdentity.Structural<'Key> keyf id source) + + let inline byRef (keyf:'T->'Key) (source:ISeq<'T>) = + delay (fun () -> impl (valueComparer<'Key> ()) (keyf >> Value) (fun v -> v._1) source) + + [] + let inline countByVal<'T,'Key when 'Key : equality and 'Key : struct> (projection:'T -> 'Key) (source:ISeq<'T>) = + CountBy.byVal projection source + + [] + let inline countByRef<'T,'Key when 'Key : equality and 'Key : not struct> (projection:'T -> 'Key) (source:ISeq<'T>) = + CountBy.byRef projection source + + [] + let length (source:ISeq<'T>) = + source.Fold (fun _ -> + upcast { new Folder<'T,int,NoValue>(0,Unchecked.defaultof<_>) with + override this.ProcessNext v = + this.Result <- this.Result + 1 + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + let toArray (source:ISeq<'T>) = + source.Fold (fun _ -> + upcast { new FolderWithPostProcessing<'T,array<'T>,_>(Unchecked.defaultof<_>,ResizeArray ()) with + override this.ProcessNext v = + this.State.Add v + Unchecked.defaultof<_> (* return value unused in Fold context *) + override this.OnComplete _ = + this.Result <- this.State.ToArray () + override this.OnDispose () = () }) + + [] + let sortBy keyf source = + delay (fun () -> + let array = source |> toArray + Array.stableSortInPlaceBy keyf array + ofArray array) + + [] + let sort source = + delay (fun () -> + let array = source |> toArray + Array.stableSortInPlace array + ofArray array) + + [] + let sortWith f source = + delay (fun () -> + let array = source |> toArray + Array.stableSortInPlaceWith f array + ofArray array) + + [] + let rev source = + delay (fun () -> + let array = source |> toArray + Array.Reverse array + ofArray array) + + [] + let permute f (source:ISeq<_>) = + delay (fun () -> + source + |> toArray + |> Array.permute f + |> ofArray) + + [] + let scanBack<'T,'State> f (source:ISeq<'T>) (acc:'State) : ISeq<'State> = + delay (fun () -> + let array = source |> toArray + Array.scanSubRight f array 0 (array.Length - 1) acc + |> ofArray) + + let inline foldArraySubRight f (arr: 'T[]) start fin acc = + let mutable state = acc + for i = fin downto start do + state <- f arr.[i] state + state + + [] + let inline foldBack<'T,'State> f (source: ISeq<'T>) (x:'State) = + let arr = toArray source + let len = arr.Length + foldArraySubRight f arr 0 (len - 1) x + + [] + let zip source1 source2 = + map2 (fun x y -> x,y) source1 source2 + + [] + let inline foldBack2<'T1,'T2,'State> f (source1:ISeq<'T1>) (source2:ISeq<'T2>) (x:'State) = + let zipped = zip source1 source2 + foldBack ((<||) f) zipped x + + [] + let inline reduceBack f (source:ISeq<'T>) = + let arr = toArray source + match arr.Length with + | 0 -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + | len -> foldArraySubRight f arr 0 (len - 2) arr.[len - 1] diff --git a/src/fsharp/FSharp.Core/iseq.fsi b/src/fsharp/FSharp.Core/iseq.fsi new file mode 100644 index 0000000000..8f030782f1 --- /dev/null +++ b/src/fsharp/FSharp.Core/iseq.fsi @@ -0,0 +1,362 @@ +// 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 + + [] + module ISeq = + module Core = + [] + type NoValue = struct end + + /// Values is a mutable struct. It can be embedded within the folder type + /// if two values are required for the calculation. + [] + type 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 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 + + /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the + /// source of the chain. + type PipeIdx = int + + type IOutOfBand = + abstract StopFurtherProcessing : PipeIdx -> unit + + /// Activity 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 Activity = + /// 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 ChainComplete : stopTailCall:byref*PipeIdx -> unit + /// OnDispose is used to cleanup the stream. It is always called at the last operation + /// after the enumeration has completed. + abstract ChainDispose : stopTailCall:byref -> unit + + /// Activity is the base class of all elements within the pipeline + [] + type Activity<'T,'U> = + inherit Activity + new : unit -> Activity<'T,'U> + abstract member ProcessNext : input:'T -> bool + + [] + type Transform<'T,'U,'State> = + inherit Activity<'T,'U> + new : next:Activity * 'State -> Transform<'T,'U,'State> + val mutable State : 'State + val private Next : Activity + + [] + type TransformWithPostProcessing<'T,'U,'State> = + inherit Transform<'T,'U,'State> + new : next:Activity * 'State -> TransformWithPostProcessing<'T,'U,'State> + abstract OnComplete : PipeIdx -> unit + abstract OnDispose : unit -> unit + + /// Folder 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 Folder<'T,'Result,'State> = + inherit Activity<'T,'T> + new : 'Result*'State -> Folder<'T,'Result,'State> + interface IOutOfBand + val mutable State : 'State + val mutable Result : 'Result + val mutable HaltedIdx : int + member StopFurtherProcessing : PipeIdx -> unit + + [] + type FolderWithPostProcessing<'T,'Result,'State> = + inherit Folder<'T,'Result,'State> + new : 'Result*'State -> FolderWithPostProcessing<'T,'Result,'State> + abstract OnDispose : unit -> unit + abstract OnComplete : PipeIdx -> unit + + [] + type TransformFactory<'T,'U> = + new : unit -> TransformFactory<'T,'U> + abstract member Compose : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> + + type ISeq<'T> = + inherit System.Collections.Generic.IEnumerable<'T> + abstract member PushTransform : TransformFactory<'T,'U> -> ISeq<'U> + abstract member Fold<'Result,'State> : f:(PipeIdx->Folder<'T,'Result,'State>) -> 'Result + + open Core + + [] + val ofResizeArrayUnchecked : ResizeArray<'T> -> ISeq<'T> + + [] + val ofList : list<'T> -> ISeq<'T> + + [] + val ofArray : array<'T> -> ISeq<'T> + + [] + val ofSeq : seq<'T> -> ISeq<'T> + + [] + val inline average : source: ISeq< ^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:ISeq< 'T > -> ^U + when ^U:(static member Zero : ^U) + and ^U:(static member (+) : ^U * ^U -> ^U) + and ^U:(static member DivideByInt : ^U * int -> ^U) + + [] + val empty<'T> : ISeq<'T> + + [] + val exactlyOne : ISeq<'T> -> 'T + + [] + val inline fold<'T,'State> : f:('State->'T->'State) -> seed:'State -> source:ISeq<'T> -> 'State + + [] + val inline fold2<'T1,'T2,'State> : folder:('State->'T1->'T2->'State) -> state:'State -> source1: ISeq<'T1> -> source2: ISeq<'T2> -> 'State + + [] + val unfold : generator:('State -> option<'T*'State>) -> state:'State -> ISeq<'T> + + [] + val initInfinite : f:(int -> 'T) -> ISeq<'T> + + [] + val init : count:int -> f:(int -> 'T) -> ISeq<'T> + + [] + val inline iter : f:('T -> unit) -> source:ISeq<'T> -> unit + + [] + val inline iter2 : f:('T->'U->unit) -> source1 : ISeq<'T> -> source2 : ISeq<'U> -> unit + + [] + val inline iteri2 : f:(int->'T->'U->unit) -> source1:ISeq<'T> -> source2:ISeq<'U> -> unit + + [] + val tryHead : ISeq<'T> -> option<'T> + + [] + val head: source:ISeq<'T> -> 'T + + [] + val inline iteri : f:(int -> 'T -> unit) -> source:ISeq<'T> -> unit + + [] + val inline except : itemsToExclude:seq<'T> -> source:ISeq<'T> -> ISeq<'T> when 'T:equality + + [] + val inline exists : f:('T -> bool) -> source:ISeq<'T> -> bool + + [] + val inline exists2 : predicate:('T->'U->bool) -> source1:ISeq<'T> -> source2:ISeq<'U> -> bool + + [] + val inline contains : element:'T -> source:ISeq<'T> -> bool when 'T : equality + + [] + val inline forall : f:('T -> bool) -> source:ISeq<'T> -> bool + + [] + val inline forall2 : predicate:('T->'U->bool) -> source1:ISeq<'T> -> source2:ISeq<'U> -> bool + + [] + val inline filter : f:('T -> bool) -> source:ISeq<'T> -> ISeq<'T> + + [] + val inline map : f:('T -> 'U) -> source:ISeq<'T> -> ISeq<'U> + + [] + val inline mapi : f:(int->'a->'b) -> source: ISeq<'a> -> ISeq<'b> + + [] + val inline map2<'T,'U,'V> : map:('T->'U->'V) -> source1:ISeq<'T> -> source2:ISeq<'U> -> ISeq<'V> + + [] + val inline mapi2<'T,'U,'V> : map:(int -> 'T->'U->'V) -> source1:ISeq<'T> -> source2:ISeq<'U> -> ISeq<'V> + + [] + val inline map3<'T,'U,'V,'W> : map:('T->'U->'V->'W) -> source1:ISeq<'T> -> source2:ISeq<'U> -> source3:ISeq<'V> -> ISeq<'W> + + [] + val inline compareWith : f:('T->'T->int) -> source1 :ISeq<'T> -> source2:ISeq<'T> -> int + + [] + val inline choose : f:('a->option<'b>) -> source: ISeq<'a> -> ISeq<'b> + + [] + val inline distinct : source:ISeq<'T> -> ISeq<'T> when 'T:equality + + [] + val inline distinctBy : keyf:('T->'Key) -> source:ISeq<'T> -> ISeq<'T> when 'Key:equality + + [] + val inline max : source:ISeq<'T> -> 'T when 'T:comparison + + [] + val inline maxBy : f:('T->'U) -> source:ISeq<'T> -> 'T when 'U:comparison + + [] + val inline min : source:ISeq<'T> -> 'T when 'T:comparison + + [] + val inline minBy : f:('T->'U) -> source:ISeq<'T> -> 'T when 'U:comparison + + [] + val pairwise : source:ISeq<'T> -> ISeq<'T * 'T> + + [] + val inline reduce : f:('T->'T->'T) -> source:ISeq<'T> -> 'T + + [] + val inline scan : folder:('State->'T->'State) -> initialState:'State -> source:ISeq<'T> -> ISeq<'State> + + [] + val skip : skipCount:int -> source:ISeq<'T> -> ISeq<'T> + + [] + val inline skipWhile : predicate:('T->bool) -> source:ISeq<'T> -> ISeq<'T> + + [] + val inline sum : source:ISeq<'T> -> 'T + when 'T:(static member Zero : ^T) + and 'T:(static member (+) : ^T * ^T -> ^T) + + [] + val inline sumBy : f :('T -> ^U) -> source:ISeq<'T> -> ^U + when ^U:(static member Zero : ^U) + and ^U:(static member (+) : ^U * ^U -> ^U) + + [] + val take : takeCount:int -> source:ISeq<'T> -> ISeq<'T> + + [] + val inline takeWhile : predicate:('T->bool) -> source:ISeq<'T> -> ISeq<'T> + + [] + val tail : source:ISeq<'T> -> ISeq<'T> + + [] + val truncate : truncateCount:int -> source:ISeq<'T> -> ISeq<'T> + + [] + val indexed : source: ISeq<'a> -> ISeq + + [] + val tryItem : index:int -> source:ISeq<'T> -> option<'T> + + [] + val inline tryPick : f:('T -> option<'U>) -> source:ISeq<'T> -> option<'U> + + [] + val inline tryFind : f:('T -> bool) -> source:ISeq<'T> -> option<'T> + + [] + val inline tryFindIndex: predicate:('T->bool) -> source:ISeq<'T> -> option + + [] + val last: source:ISeq<'T> -> 'T + + [] + val tryLast : source:ISeq<'T> -> option<'T> + + [] + val windowed : windowSize:int -> source:ISeq<'T> -> ISeq> + + [] + val concat : sources:ISeq<'Collection> -> ISeq<'T> when 'Collection :> ISeq<'T> + + [] + val append: source1:ISeq<'T> -> source2:ISeq<'T> -> ISeq<'T> + + [] + val delay : (unit -> ISeq<'T>) -> ISeq<'T> + + [] + val inline groupByVal : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * ISeq<'T>> when 'Key : equality and 'Key : struct + + [] + val inline groupByRef : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * ISeq<'T>> when 'Key : equality and 'Key : not struct + + [] + val inline countByVal : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * int> when 'Key : equality and 'Key : struct + + [] + val inline countByRef : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * int> when 'Key : equality and 'Key : not struct + + [] + val length: source:ISeq<'T> -> int + + [] + val toArray: source:ISeq<'T> -> array<'T> + + [] + val sortBy : projection:('T->'Key) -> source:ISeq<'T> -> ISeq<'T> when 'Key : comparison + + [] + val sort : source:ISeq<'T> -> ISeq<'T> when 'T : comparison + + [] + val sortWith : comparer:('T->'T->int) -> source:ISeq<'T> -> ISeq<'T> + + [] + val rev: source:ISeq<'T> -> ISeq<'T> + + [] + val permute: indexMap:(int->int) -> source:ISeq<'T> -> ISeq<'T> + + [] + val scanBack<'T,'State> : folder:('T->'State->'State) -> source:ISeq<'T> -> state:'State -> ISeq<'State> + + [] + val zip: source1:ISeq<'T1> -> source2:ISeq<'T2> -> ISeq<'T1 * 'T2> + + [] + val inline reduceBack: reduction:('T->'T->'T) -> source:ISeq<'T> -> 'T + + [] + val inline foldBack<'T,'State> : folder:('T->'State->'State) -> source:ISeq<'T> -> state:'State -> 'State + + [] + val inline foldBack2<'T1,'T2,'State> : folder:('T1->'T2->'State->'State) -> source1:ISeq<'T1> -> source2:ISeq<'T2> -> state:'State -> 'State + + module internal GroupBy = + val inline byVal : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * ISeq<'T>> when 'Key : equality + val inline byRef : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * ISeq<'T>> when 'Key : equality + + module internal CountBy = + val inline byVal : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * int> when 'Key : equality + val inline byRef : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * int> when 'Key : equality From f22c20c044e0c0e452239db88aafa01e25ec6843 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 14 Mar 2017 19:21:52 +1100 Subject: [PATCH 02/83] Updated remaining SurfaceArea files --- .../SurfaceArea.coreclr.fs | 193 +++++++++++++++++ .../fsharpqa/Source/Misc/LongSourceFile01.fs | 194 ++++++++++++++++++ 2 files changed, 387 insertions(+) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs index cd7c9087a5..64bb5ea2ef 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs @@ -293,6 +293,199 @@ 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.ISeqModule+Core+Activity: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnDispose() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+IOutOfBand: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]: ISeq`1 PushTransform[TResult](TransformFactory`2) +Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]: TResult Fold[TResult,TState](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]]) +Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Activity`2 Compose[V](IOutOfBand, Int32, Activity`2) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void .ctor(Activity, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnDispose() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void .ctor(Activity, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Void .ctor(a) +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: a _1 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: Void .ctor(a, b) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: a _1 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: b _2 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: Void .ctor(a, b, c) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: a _1 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: b _2 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: c _3 +Microsoft.FSharp.Collections.ISeqModule+Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Activity +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+IOutOfBand +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+NoValue +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c] +Microsoft.FSharp.Collections.ISeqModule+Core: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule: Boolean Contains[T](T, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule: Boolean Exists2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Append[T](ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Choose[a,b](Microsoft.FSharp.Core.FSharpFunc`2[a,Microsoft.FSharp.Core.FSharpOption`1[b]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Concat[TCollection,T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Delay[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 DistinctBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Distinct[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Empty[T]() +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Except[T](System.Collections.Generic.IEnumerable`1[T], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Filter[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 GroupByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 GroupByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Indexed[a](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 InitializeInfinite[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Initialize[T](Int32, Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map3[T,TResult,V,W](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[V,W]]], ISeq`1, ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 MapIndexed2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 MapIndexed[a,b](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[a,b]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfArray[T](T[]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfList[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfResizeArrayUnchecked[T](System.Collections.Generic.List`1[T]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfSeq[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Pairwise[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Permute[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Reverse[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], ISeq`1, TState) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Scan[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SkipWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Skip[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Sort[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Tail[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Take[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Truncate[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Unfold[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Windowed[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Zip[T1,T2](ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule: Int32 Length[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.ISeqModule+Core +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[TResult] TryPick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFind[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryHead[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryItem[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule: T Average[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T ExactlyOne[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Head[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Last[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Max[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Min[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T ReduceBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Sum[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: 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, ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: TState FoldBack2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], ISeq`1, ISeq`1, TState) +Microsoft.FSharp.Collections.ISeqModule: TState FoldBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], ISeq`1, TState) +Microsoft.FSharp.Collections.ISeqModule: TState Fold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T[] ToArray[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Void Iterate2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.Unit]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: 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]]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Void IterateIndexed[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Void Iterate[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit], ISeq`1) 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]) diff --git a/tests/fsharpqa/Source/Misc/LongSourceFile01.fs b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs index 970a5f77ff..5cffea8000 100644 --- a/tests/fsharpqa/Source/Misc/LongSourceFile01.fs +++ b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs @@ -247,6 +247,200 @@ 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.ISeqModule+Core+Activity: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnDispose() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+IOutOfBand: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]: ISeq`1 PushTransform[TResult](TransformFactory`2) +Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]: TResult Fold[TResult,TState](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]]) +Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Activity`2 Compose[V](IOutOfBand, Int32, Activity`2) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void .ctor(Activity, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnDispose() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void .ctor(Activity, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Void .ctor(a) +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: a _1 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: Void .ctor(a, b) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: a _1 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: b _2 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: Void .ctor(a, b, c) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: a _1 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: b _2 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: c _3 +Microsoft.FSharp.Collections.ISeqModule+Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Activity +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+IOutOfBand +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+NoValue +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c] +Microsoft.FSharp.Collections.ISeqModule+Core: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule: Boolean Contains[T](T, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule: Boolean Exists2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Append[T](ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Choose[a,b](Microsoft.FSharp.Core.FSharpFunc`2[a,Microsoft.FSharp.Core.FSharpOption`1[b]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Concat[TCollection,T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Delay[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 DistinctBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Distinct[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Empty[T]() +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Except[T](System.Collections.Generic.IEnumerable`1[T], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Filter[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 GroupByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 GroupByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Indexed[a](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 InitializeInfinite[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Initialize[T](Int32, Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map3[T,TResult,V,W](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[V,W]]], ISeq`1, ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 MapIndexed2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 MapIndexed[a,b](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[a,b]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfArray[T](T[]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfList[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfResizeArrayUnchecked[T](System.Collections.Generic.List`1[T]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfSeq[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Pairwise[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Permute[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Reverse[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], ISeq`1, TState) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Scan[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SkipWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Skip[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Sort[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Tail[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Take[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Truncate[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Unfold[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Windowed[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Zip[T1,T2](ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule: Int32 Length[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.ISeqModule+Core +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[TResult] TryPick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFind[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryHead[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryItem[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule: T Average[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T ExactlyOne[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Head[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Last[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Max[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Min[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T ReduceBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Sum[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: 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, ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: TState FoldBack2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], ISeq`1, ISeq`1, TState) +Microsoft.FSharp.Collections.ISeqModule: TState FoldBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], ISeq`1, TState) +Microsoft.FSharp.Collections.ISeqModule: TState Fold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T[] ToArray[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Void Iterate2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.Unit]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: 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]]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Void IterateIndexed[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Void Iterate[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit], ISeq`1) +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]) From 594a3fac96183996977f301b4e73d8edde6247c4 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 15 Mar 2017 20:38:33 +1100 Subject: [PATCH 03/83] Copied Seq tests and converted to ISeq Due to missing functionality, this process will probably be done again some time, but this is just a rough sketch to get some tests up and running --- .../FSharp.Core.Unittests.fsproj | 5 + .../ISeqModule.fs | 1165 +++++++++++ .../ISeqModule2.fs | 1839 +++++++++++++++++ .../ISeqProperties.fs | 39 + 4 files changed, 3048 insertions(+) create mode 100644 src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs create mode 100644 src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule2.fs create mode 100644 src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqProperties.fs diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core.Unittests.fsproj b/src/fsharp/FSharp.Core.Unittests/FSharp.Core.Unittests.fsproj index f851d9ca39..ecc6aec03b 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core.Unittests.fsproj +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core.Unittests.fsproj @@ -93,6 +93,11 @@ + + + + + diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs new file mode 100644 index 0000000000..0286684808 --- /dev/null +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs @@ -0,0 +1,1165 @@ +// 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 + +// Various tests for the: +// Microsoft.FSharp.Collections.seq type + +(* +[Test Strategy] +Make sure each method works on: +* Integer ISeq (value type) +* String ISeq (reference type) +* Empty ISeq (0 elements) +* Null ISeq (null) +*) + +[] +type ISeqModule() = + + [] + member this.AllPairs() = + + // integer ISeq + let resultInt = Seq.allPairs (seq [1..7]) (seq [11..17]) + let expectedInt = + seq { for i in 1..7 do + for j in 11..17 do + yield i, j } + VerifySeqsEqual expectedInt resultInt + + // string ISeq + let resultStr = Seq.allPairs (seq ["str3";"str4"]) (seq ["str1";"str2"]) + let expectedStr = seq ["str3","str1";"str3","str2";"str4","str1";"str4","str2"] + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + VerifySeqsEqual ISeq.empty <| Seq.allPairs ISeq.empty ISeq.empty + VerifySeqsEqual ISeq.empty <| Seq.allPairs { 1..7 } ISeq.empty + VerifySeqsEqual ISeq.empty <| Seq.allPairs ISeq.empty { 1..7 } + + // null ISeq + CheckThrowsArgumentNullException(fun() -> Seq.allPairs null null |> ignore) + CheckThrowsArgumentNullException(fun() -> Seq.allPairs null (seq [1..7]) |> ignore) + CheckThrowsArgumentNullException(fun() -> Seq.allPairs (seq [1..7]) null |> ignore) + () + + [] + member this.CachedSeq_Clear() = + + let evaluatedItems : int list ref = ref [] + let cachedSeq = + ISeq.initInfinite (fun i -> evaluatedItems := i :: !evaluatedItems; i) + |> Seq.cache + |> ISeq.ofSeq + + // Verify no items have been evaluated from the ISeq yet + Assert.AreEqual(List.length !evaluatedItems, 0) + + // Force evaluation of 10 elements + ISeq.take 10 cachedSeq + |> Seq.toList + |> ignore + + // verify ref clear switch length + Assert.AreEqual(List.length !evaluatedItems, 10) + + // Force evaluation of 10 elements + ISeq.take 10 cachedSeq + |> Seq.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 + ISeq.take 10 cachedSeq + |> Seq.toList + |> ignore + + // Verify length of evaluatedItemList is 20 + Assert.AreEqual(List.length !evaluatedItems, 20) + () + + [] + member this.Append() = + + // empty ISeq + let emptySeq1 = ISeq.empty + let emptySeq2 = ISeq.empty + let appendEmptySeq = ISeq.append emptySeq1 emptySeq2 + let expectResultEmpty = ISeq.empty + + VerifySeqsEqual expectResultEmpty appendEmptySeq + + // Integer ISeq + let integerSeq1 = seq [0..4] |> ISeq.ofSeq + let integerSeq2 = seq [5..9] |> ISeq.ofSeq + + let appendIntergerSeq = ISeq.append integerSeq1 integerSeq2 + + let expectResultInteger = seq { for i in 0..9 -> i} + + VerifySeqsEqual expectResultInteger appendIntergerSeq + + + // String ISeq + let stringSeq1 = seq ["1";"2"] |> ISeq.ofSeq + let stringSeq2 = seq ["3";"4"] |> ISeq.ofSeq + + let appendStringSeq = ISeq.append stringSeq1 stringSeq2 + + let expectedResultString = seq ["1";"2";"3";"4"] + + VerifySeqsEqual expectedResultString appendStringSeq + + // null ISeq + let nullSeq1 = seq [null;null] |> ISeq.ofSeq + let nullSeq2 = seq [null;null] |> ISeq.ofSeq + + let appendNullSeq = ISeq.append nullSeq1 nullSeq2 + + let expectedResultNull = seq [ null;null;null;null] + + VerifySeqsEqual expectedResultNull appendNullSeq + + () + + [] + member this.replicate() = + // replicate should create multiple copies of the given value + Assert.IsTrue(Seq.isEmpty <| Seq.replicate 0 null) + Assert.IsTrue(Seq.isEmpty <| Seq.replicate 0 1) + Assert.AreEqual(null, ISeq.head <| (Seq.replicate 1 null |> ISeq.ofSeq)) + Assert.AreEqual(["1";"1"],Seq.replicate 2 "1" |> Seq.toList) + + CheckThrowsArgumentException (fun () -> Seq.replicate -1 null |> ignore) + + + [] + member this.Average() = + // empty ISeq + let emptySeq = ISeq.empty + + CheckThrowsArgumentException (fun () -> ISeq.average emptySeq |> ignore) + + + // double ISeq + let doubleSeq = seq [1.0;2.2;2.5;4.3] |> ISeq.ofSeq + + let averageDouble = ISeq.average doubleSeq + + Assert.IsFalse( averageDouble <> 2.5) + + // float32 ISeq + let floatSeq = seq [ 2.0f;4.4f;5.0f;8.6f] |> ISeq.ofSeq + + let averageFloat = ISeq.average floatSeq + + Assert.IsFalse( averageFloat <> 5.0f) + + // decimal ISeq + let decimalSeq = seq [ 0M;19M;19.03M] |> ISeq.ofSeq + + let averageDecimal = ISeq.average decimalSeq + + Assert.IsFalse( averageDecimal <> 12.676666666666666666666666667M ) + + // null ISeq + //let nullSeq : ISeq.Core.ISeq = null + + //CheckThrowsArgumentNullException (fun () -> ISeq.average nullSeq |> ignore) + () + + + [] + member this.AverageBy() = + // empty ISeq + let emptySeq = ISeq.empty + + CheckThrowsArgumentException (fun () -> ISeq.averageBy (fun x -> x+1.0) emptySeq |> ignore) + + // double ISeq + let doubleSeq = seq [1.0;2.2;2.5;4.3] |> ISeq.ofSeq + + let averageDouble = ISeq.averageBy (fun x -> x-2.0) doubleSeq + + Assert.IsFalse( averageDouble <> 0.5 ) + + // float32 ISeq + let floatSeq = seq [ 2.0f;4.4f;5.0f;8.6f] |> ISeq.ofSeq + + let averageFloat = ISeq.averageBy (fun x -> x*3.3f) floatSeq + + Assert.IsFalse( averageFloat <> 16.5f ) + + // decimal ISeq + let decimalSeq = seq [ 0M;19M;19.03M] |> ISeq.ofSeq + + let averageDecimal = ISeq.averageBy (fun x -> x/10.7M) decimalSeq + + Assert.IsFalse( averageDecimal <> 1.1847352024922118380062305296M ) + + //// null ISeq + //let nullSeq = null + + //CheckThrowsArgumentNullException (fun () -> ISeq.averageBy (fun (x:double)->x+4.0) nullSeq |> ignore) + () + + [] + member this.Cache() = + // empty ISeq + let emptySeq = ISeq.empty + + let cacheEmpty = Seq.cache emptySeq + + let expectedResultEmpty = ISeq.empty + + VerifySeqsEqual expectedResultEmpty cacheEmpty + + // double ISeq + let doubleSeq = seq [1.0;2.2;2.5;4.3] |> ISeq.ofSeq + + let cacheDouble = Seq.cache doubleSeq + + VerifySeqsEqual doubleSeq cacheDouble + + + // float32 ISeq + let floatSeq = seq [ 2.0f;4.4f;5.0f;8.6f] + + let cacheFloat = Seq.cache floatSeq + + VerifySeqsEqual floatSeq cacheFloat + + // decimal ISeq + let decimalSeq = seq [ 0M; 19M; 19.03M] + + let cacheDecimal = Seq.cache decimalSeq + + VerifySeqsEqual decimalSeq cacheDecimal + + // null ISeq + let nullSeq = seq [null] + + let cacheNull = Seq.cache nullSeq + + VerifySeqsEqual nullSeq cacheNull + () + + [] + member this.Case() = + + // integer ISeq + let integerArray = [|1;2|] + let integerSeq = Seq.cast integerArray + + let expectedIntegerSeq = seq [1;2] + + VerifySeqsEqual expectedIntegerSeq integerSeq + + // string ISeq + let stringArray = [|"a";"b"|] + let stringSeq = Seq.cast stringArray + + let expectedStringSeq = seq["a";"b"] + + VerifySeqsEqual expectedStringSeq stringSeq + + // empty ISeq + let emptySeq = Seq.cast ISeq.empty + let expectedEmptySeq = ISeq.empty + + VerifySeqsEqual expectedEmptySeq ISeq.empty + + // null ISeq + let nullArray = [|null;null|] + let NullSeq = Seq.cast nullArray + let expectedNullSeq = seq [null;null] + + VerifySeqsEqual expectedNullSeq NullSeq + + CheckThrowsExn(fun () -> + let strings = + integerArray + |> Seq.cast + for o in strings do ()) + + CheckThrowsExn(fun () -> + let strings = + integerArray + |> Seq.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 ISeq + let intSeq = seq [1..20] |> ISeq.ofSeq + let funcInt x = if (x%5=0) then Some x else None + let intChoosed = ISeq.choose funcInt intSeq + let expectedIntChoosed = seq { for i = 1 to 4 do yield i*5} + + + + VerifySeqsEqual expectedIntChoosed intChoosed + + // string ISeq + let stringSrc = seq ["list";"List"] |> ISeq.ofSeq + let funcString x = match x with + | "list"-> Some x + | "List" -> Some x + | _ -> None + let strChoosed = ISeq.choose funcString stringSrc + let expectedStrChoose = seq ["list";"List"] + + VerifySeqsEqual expectedStrChoose strChoosed + + // empty ISeq + let emptySeq = ISeq.empty + let emptyChoosed = ISeq.choose funcInt emptySeq + + let expectedEmptyChoose = ISeq.empty + + VerifySeqsEqual expectedEmptyChoose emptySeq + + + // null ISeq + //let nullSeq = null + + //CheckThrowsArgumentNullException (fun () -> ISeq.choose funcInt nullSeq |> ignore) + () + + [] + member this.ChunkBySize() = + + let verify expected actual = + ISeq.zip (expected |> ISeq.ofSeq) (actual |> ISeq.ofSeq) + |> ISeq.iter ((<||) VerifySeqsEqual) + + // int ISeq + verify [[1..4];[5..8]] <| Seq.chunkBySize 4 {1..8} + verify [[1..4];[5..8];[9..10]] <| Seq.chunkBySize 4 {1..10} + verify [[1]; [2]; [3]; [4]] <| Seq.chunkBySize 1 {1..4} + + Seq.chunkBySize 2 (ISeq.initInfinite id) + |> ISeq.ofSeq + |> ISeq.take 3 + |> verify [[0;1];[2;3];[4;5]] + + Seq.chunkBySize 1 (ISeq.initInfinite id) + |> ISeq.ofSeq + |> ISeq.take 5 + |> verify [[0];[1];[2];[3];[4]] + + // string ISeq + verify [["a"; "b"];["c";"d"];["e"]] <| Seq.chunkBySize 2 ["a";"b";"c";"d";"e"] + + // empty ISeq + verify ISeq.empty <| Seq.chunkBySize 3 ISeq.empty + + // null ISeq + let nullSeq:seq<_> = null + CheckThrowsArgumentNullException (fun () -> Seq.chunkBySize 3 nullSeq |> ignore) + + // invalidArg + CheckThrowsArgumentException (fun () -> Seq.chunkBySize 0 {1..10} |> ignore) + CheckThrowsArgumentException (fun () -> Seq.chunkBySize -1 {1..10} |> ignore) + + () + + [] + member this.SplitInto() = + + let verify expected actual = + ISeq.zip (expected |> ISeq.ofSeq) (actual |> ISeq.ofSeq) + |> ISeq.iter ((<||) VerifySeqsEqual) + + // int ISeq + Seq.splitInto 3 {1..10} |> verify (seq [ {1..4}; {5..7}; {8..10} ]) + Seq.splitInto 3 {1..11} |> verify (seq [ {1..4}; {5..8}; {9..11} ]) + Seq.splitInto 3 {1..12} |> verify (seq [ {1..4}; {5..8}; {9..12} ]) + + Seq.splitInto 4 {1..5} |> verify (seq [ [1..2]; [3]; [4]; [5] ]) + Seq.splitInto 20 {1..4} |> verify (seq [ [1]; [2]; [3]; [4] ]) + + // string ISeq + Seq.splitInto 3 ["a";"b";"c";"d";"e"] |> verify ([ ["a"; "b"]; ["c";"d"]; ["e"] ]) + + // empty ISeq + VerifySeqsEqual [] <| Seq.splitInto 3 [] + + // null ISeq + let nullSeq:seq<_> = null + CheckThrowsArgumentNullException (fun () -> Seq.splitInto 3 nullSeq |> ignore) + + // invalidArg + CheckThrowsArgumentException (fun () -> Seq.splitInto 0 [1..10] |> ignore) + CheckThrowsArgumentException (fun () -> Seq.splitInto -1 [1..10] |> ignore) + + () + + [] + member this.Compare() = + + // int ISeq + let intSeq1 = seq [1;3;7;9] |> ISeq.ofSeq + let intSeq2 = seq [2;4;6;8] |> ISeq.ofSeq + let funcInt x y = if (x>y) then x else 0 + let intcompared = ISeq.compareWith funcInt intSeq1 intSeq2 + + Assert.IsFalse( intcompared <> 7 ) + + // string ISeq + let stringSeq1 = seq ["a"; "b"] |> ISeq.ofSeq + let stringSeq2 = seq ["c"; "d"] |> ISeq.ofSeq + let funcString x y = match (x,y) with + | "a", "c" -> 0 + | "b", "d" -> 1 + |_ -> -1 + let strcompared = ISeq.compareWith funcString stringSeq1 stringSeq2 + Assert.IsFalse( strcompared <> 1 ) + + // empty ISeq + let emptySeq = ISeq.empty + let emptycompared = ISeq.compareWith funcInt emptySeq emptySeq + + Assert.IsFalse( emptycompared <> 0 ) + + // null ISeq + //let nullSeq = null + + //CheckThrowsArgumentNullException (fun () -> ISeq.compareWith funcInt nullSeq emptySeq |> ignore) + //CheckThrowsArgumentNullException (fun () -> ISeq.compareWith funcInt emptySeq nullSeq |> ignore) + //CheckThrowsArgumentNullException (fun () -> ISeq.compareWith funcInt nullSeq nullSeq |> ignore) + + () + + [] + member this.Concat() = + // integer ISeq + let seqInt = + seq { for i in 0..9 do + yield seq {for j in 0..9 do + yield i*10+j} |> ISeq.ofSeq } |> ISeq.ofSeq + let conIntSeq = ISeq.concat seqInt + let expectedIntSeq = seq { for i in 0..99 do yield i} + + VerifySeqsEqual expectedIntSeq conIntSeq + + // string ISeq + let strSeq = + seq { for a in 'a' .. 'b' do + for b in 'a' .. 'b' do + yield seq [a; b] |> ISeq.ofSeq }|> ISeq.ofSeq + + let conStrSeq = ISeq.concat strSeq + let expectedStrSeq = seq ['a';'a';'a';'b';'b';'a';'b';'b';] + VerifySeqsEqual expectedStrSeq conStrSeq + + // Empty ISeq + let emptySeqs = seq [seq[ ISeq.empty;ISeq.empty]|> ISeq.ofSeq;seq[ ISeq.empty;ISeq.empty]|> ISeq.ofSeq]|> ISeq.ofSeq + let conEmptySeq = ISeq.concat emptySeqs + let expectedEmptySeq =seq { for i in 1..4 do yield ISeq.empty} + + VerifySeqsEqual expectedEmptySeq conEmptySeq + + //// null ISeq + //let nullSeq = null + + //CheckThrowsArgumentNullException (fun () -> ISeq.concat nullSeq |> ignore) + + () + + [] + member this.CountBy() = + // integer ISeq + let funcIntCount_by (x:int) = x%3 + let seqInt = + seq { for i in 0..9 do + yield i} + let countIntSeq = Seq.countBy funcIntCount_by seqInt + + let expectedIntSeq = seq [0,4;1,3;2,3] + + VerifySeqsEqual expectedIntSeq countIntSeq + + // string ISeq + let funcStrCount_by (s:string) = s.IndexOf("key") + let strSeq = seq [ "key";"blank key";"key";"blank blank key"] + + let countStrSeq = Seq.countBy funcStrCount_by strSeq + let expectedStrSeq = seq [0,2;6,1;12,1] + VerifySeqsEqual expectedStrSeq countStrSeq + + // Empty ISeq + let emptySeq = ISeq.empty + let countEmptySeq = Seq.countBy funcIntCount_by emptySeq + let expectedEmptySeq =seq [] + + VerifySeqsEqual expectedEmptySeq countEmptySeq + + // null ISeq + let nullSeq = null + + CheckThrowsArgumentNullException (fun () -> Seq.countBy funcIntCount_by nullSeq |> ignore) + () + + [] + member this.Distinct() = + + // integer ISeq + let IntDistinctSeq = + seq { for i in 0..9 do + yield i % 3 } |> ISeq.ofSeq + + let DistinctIntSeq = ISeq.distinct IntDistinctSeq + + let expectedIntSeq = seq [0;1;2] + + VerifySeqsEqual expectedIntSeq DistinctIntSeq + + // string ISeq + let strDistinctSeq = seq ["elementDup"; "ele1"; "ele2"; "elementDup"] |> ISeq.ofSeq + + let DistnctStrSeq = ISeq.distinct strDistinctSeq + let expectedStrSeq = seq ["elementDup"; "ele1"; "ele2"] |> ISeq.ofSeq + VerifySeqsEqual expectedStrSeq DistnctStrSeq + + // Empty ISeq + let emptySeq = ISeq.empty + let distinctEmptySeq = ISeq.distinct emptySeq + let expectedEmptySeq = seq [] |> ISeq.ofSeq + + VerifySeqsEqual expectedEmptySeq distinctEmptySeq + + //// null ISeq + //let nullSeq = null + + //CheckThrowsArgumentNullException(fun () -> ISeq.distinct nullSeq |> ignore) + () + + [] + member this.DistinctBy () = + // integer ISeq + let funcInt x = x % 3 + let IntDistinct_bySeq = + seq { for i in 0..9 do + yield i } |> ISeq.ofSeq + + let distinct_byIntSeq = ISeq.distinctBy funcInt IntDistinct_bySeq + + let expectedIntSeq = seq [0;1;2] |> ISeq.ofSeq + + VerifySeqsEqual expectedIntSeq distinct_byIntSeq + + // string ISeq + let funcStrDistinct (s:string) = s.IndexOf("key") + let strSeq = seq [ "key"; "blank key"; "key dup"; "blank key dup"] |> ISeq.ofSeq + + let DistnctStrSeq = ISeq.distinctBy funcStrDistinct strSeq + let expectedStrSeq = seq ["key"; "blank key"] |> ISeq.ofSeq + VerifySeqsEqual expectedStrSeq DistnctStrSeq + + // Empty ISeq + let emptySeq = ISeq.empty + let distinct_byEmptySeq = ISeq.distinctBy funcInt emptySeq + let expectedEmptySeq = seq [] |> ISeq.ofSeq + + VerifySeqsEqual expectedEmptySeq distinct_byEmptySeq + + //// null ISeq + //let nullSeq = null + + //CheckThrowsArgumentNullException(fun () -> ISeq.distinctBy funcInt nullSeq |> ignore) + () + + [] + member this.Except() = + // integer ISeq + let intSeq1 = seq { yield! {1..100} + yield! {1..100} } |> ISeq.ofSeq + let intSeq2 = {1..10} |> ISeq.ofSeq + let expectedIntSeq = {11..100} |> ISeq.ofSeq + + VerifySeqsEqual expectedIntSeq <| ISeq.except intSeq2 intSeq1 + + // string ISeq + let strSeq1 = seq ["a"; "b"; "c"; "d"; "a"] |> ISeq.ofSeq + let strSeq2 = seq ["b"; "c"] |> ISeq.ofSeq + let expectedStrSeq = seq ["a"; "d"] |> ISeq.ofSeq + + VerifySeqsEqual expectedStrSeq <| ISeq.except strSeq2 strSeq1 + + // double ISeq + // Sequences with nan do not behave, due to the F# generic equality comparisons +// let floatSeq1 = seq [1.0; 1.0; System.Double.MaxValue; nan; nan] +// +// VerifySeqsEqual [1.0; System.Double.MaxValue; nan; nan] <| ISeq.except [] floatSeq1 +// VerifySeqsEqual [1.0; System.Double.MaxValue] <| ISeq.except [nan] floatSeq1 + + // empty ISeq + let emptyIntSeq = ISeq.empty + VerifySeqsEqual {1..100} <| ISeq.except emptyIntSeq intSeq1 + VerifySeqsEqual emptyIntSeq <| ISeq.except intSeq1 emptyIntSeq + VerifySeqsEqual emptyIntSeq <| ISeq.except emptyIntSeq emptyIntSeq + VerifySeqsEqual emptyIntSeq <| ISeq.except intSeq1 intSeq1 + + //// null ISeq + //let nullSeq = null + //CheckThrowsArgumentNullException(fun () -> ISeq.except nullSeq emptyIntSeq |> ignore) + //CheckThrowsArgumentNullException(fun () -> ISeq.except emptyIntSeq nullSeq |> ignore) + //CheckThrowsArgumentNullException(fun () -> ISeq.except nullSeq nullSeq |> ignore) + + () + + [] + member this.Exists() = + + // Integer ISeq + let funcInt x = (x % 2 = 0) + let IntexistsSeq = + seq { for i in 0..9 do + yield i} |> ISeq.ofSeq + + let ifExistInt = ISeq.exists funcInt IntexistsSeq + + Assert.IsTrue( ifExistInt) + + // String ISeq + let funcStr (s:string) = s.Contains("key") + let strSeq = seq ["key"; "blank key"] |> ISeq.ofSeq + + let ifExistStr = ISeq.exists funcStr strSeq + + Assert.IsTrue( ifExistStr) + + // Empty ISeq + let emptySeq = ISeq.empty + let ifExistsEmpty = ISeq.exists funcInt emptySeq + + Assert.IsFalse( ifExistsEmpty) + + + + //// null ISeq + //let nullSeq = null + + //CheckThrowsArgumentNullException (fun () -> ISeq.exists funcInt nullSeq |> ignore) + () + + [] + member this.Exists2() = + // Integer ISeq + let funcInt x y = (x+y)%3=0 + let Intexists2Seq1 = seq [1;3;7] |> ISeq.ofSeq + let Intexists2Seq2 = seq [1;6;3] |> ISeq.ofSeq + + let ifExist2Int = ISeq.exists2 funcInt Intexists2Seq1 Intexists2Seq2 + Assert.IsTrue( ifExist2Int) + + // String ISeq + let funcStr s1 s2 = ((s1 + s2) = "CombinedString") + let strSeq1 = seq [ "Combined"; "Not Combined"] |> ISeq.ofSeq + let strSeq2 = seq ["String"; "Other String"] |> ISeq.ofSeq + let ifexists2Str = ISeq.exists2 funcStr strSeq1 strSeq2 + Assert.IsTrue(ifexists2Str) + + // Empty ISeq + let emptySeq = ISeq.empty + let ifexists2Empty = ISeq.exists2 funcInt emptySeq emptySeq + Assert.IsFalse( ifexists2Empty) + + //// null ISeq + //let nullSeq = null + //CheckThrowsArgumentNullException (fun () -> ISeq.exists2 funcInt nullSeq nullSeq |> ignore) + () + + + [] + member this.Filter() = + // integer ISeq + let funcInt x = if (x % 5 = 0) then true else false + let IntSeq = + seq { for i in 1..20 do + yield i } |> ISeq.ofSeq + + let filterIntSeq = ISeq.filter funcInt IntSeq + + let expectedfilterInt = seq [ 5;10;15;20] + + VerifySeqsEqual expectedfilterInt filterIntSeq + + // string ISeq + let funcStr (s:string) = s.Contains("Expected Content") + let strSeq = seq [ "Expected Content"; "Not Expected"; "Expected Content"; "Not Expected"] |> ISeq.ofSeq + + let filterStrSeq = ISeq.filter funcStr strSeq + + let expectedfilterStr = seq ["Expected Content"; "Expected Content"] |> ISeq.ofSeq + + VerifySeqsEqual expectedfilterStr filterStrSeq + // Empty ISeq + let emptySeq = ISeq.empty + let filterEmptySeq = ISeq.filter funcInt emptySeq + + let expectedEmptySeq =seq [] + + VerifySeqsEqual expectedEmptySeq filterEmptySeq + + + + //// null ISeq + //let nullSeq = null + + //CheckThrowsArgumentNullException (fun () -> ISeq.filter funcInt nullSeq |> ignore) + () + + [] + member this.Find() = + + // integer ISeq + let funcInt x = if (x % 5 = 0) then true else false + let IntSeq = + seq { for i in 1..20 do + yield i } |> ISeq.ofSeq + + let findInt = Seq.find funcInt IntSeq + Assert.AreEqual(findInt, 5) + + // string ISeq + let funcStr (s:string) = s.Contains("Expected Content") + let strSeq = seq [ "Expected Content";"Not Expected"] |> ISeq.ofSeq + + let findStr = Seq.find funcStr strSeq + Assert.AreEqual(findStr, "Expected Content") + + // Empty ISeq + let emptySeq = ISeq.empty + + CheckThrowsKeyNotFoundException(fun () -> Seq.find funcInt emptySeq |> ignore) + + //// null ISeq + //let nullSeq = null + //CheckThrowsArgumentNullException (fun () -> Seq.find funcInt nullSeq |> ignore) + () + + [] + member this.FindBack() = + // integer ISeq + let funcInt x = x % 5 = 0 + Assert.AreEqual(20, Seq.findBack funcInt <| seq { 1..20 }) + Assert.AreEqual(15, Seq.findBack funcInt <| seq { 1..19 }) + Assert.AreEqual(5, Seq.findBack funcInt <| seq { 5..9 }) + + // string ISeq + let funcStr (s:string) = s.Contains("Expected") + let strSeq = seq [ "Not Expected"; "Expected Content"] |> ISeq.ofSeq + let findStr = Seq.findBack funcStr strSeq + Assert.AreEqual("Expected Content", findStr) + + // Empty ISeq + let emptySeq = ISeq.empty + CheckThrowsKeyNotFoundException(fun () -> Seq.findBack funcInt emptySeq |> ignore) + + // Not found + let emptySeq = ISeq.empty + CheckThrowsKeyNotFoundException(fun () -> seq { 1..20 } |> Seq.findBack (fun _ -> false) |> ignore) + + //// null ISeq + //let nullSeq = null + //CheckThrowsArgumentNullException (fun () -> Seq.findBack funcInt nullSeq |> ignore) + () + + [] + member this.FindIndex() = + + // integer ISeq + let digits = [1 .. 100] |> ISeq.ofList + let idx = digits |> Seq.findIndex (fun i -> i.ToString().Length > 1) + Assert.AreEqual(idx, 9) + + // empty ISeq + CheckThrowsKeyNotFoundException(fun () -> Seq.findIndex (fun i -> true) ISeq.empty |> ignore) + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> Seq.findIndex (fun i -> true) null |> ignore) + () + + [] + member this.Permute() = + let mapIndex i = (i + 1) % 4 + + // integer seq + let intSeq = seq { 1..4 }|> ISeq.ofSeq + let resultInt = ISeq.permute mapIndex intSeq + VerifySeqsEqual (seq [4;1;2;3]) resultInt + + // string seq + let resultStr = ISeq.permute mapIndex ([|"Lists"; "are"; "commonly"; "list" |] |> ISeq.ofSeq) + VerifySeqsEqual (seq ["list"; "Lists"; "are"; "commonly" ]) resultStr + + // empty seq + let resultEpt = ISeq.permute mapIndex ([||] |> ISeq.ofSeq) + VerifySeqsEqual ISeq.empty resultEpt + + //// null seq + //let nullSeq = null + //CheckThrowsArgumentNullException (fun () -> ISeq.permute mapIndex nullSeq |> ignore) + + // argument exceptions + CheckThrowsArgumentException (fun () -> ISeq.permute (fun _ -> 10) ([0..9]|> ISeq.ofSeq) |> ISeq.iter ignore) + CheckThrowsArgumentException (fun () -> ISeq.permute (fun _ -> 0) ([0..9]|> ISeq.ofSeq) |> ISeq.iter ignore) + () + + [] + member this.FindIndexBack() = + // integer ISeq + let digits = seq { 1..100 }|> ISeq.ofSeq + let idx = digits |> Seq.findIndexBack (fun i -> i.ToString().Length = 1) + Assert.AreEqual(idx, 8) + + // string ISeq + let funcStr (s:string) = s.Contains("Expected") + let strSeq = seq [ "Not Expected"; "Expected Content" ] |> ISeq.ofSeq + let findStr = Seq.findIndexBack funcStr strSeq + Assert.AreEqual(1, findStr) + + // empty ISeq + CheckThrowsKeyNotFoundException(fun () -> Seq.findIndexBack (fun i -> true) ISeq.empty |> ignore) + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> Seq.findIndexBack (fun i -> true) null |> ignore) + () + + [] + member this.Pick() = + + let digits = [| 1 .. 10 |] |> ISeq.ofArray + let result = Seq.pick (fun i -> if i > 5 then Some(i.ToString()) else None) digits + Assert.AreEqual(result, "6") + + // Empty seq (Bugged, 4173) + CheckThrowsKeyNotFoundException (fun () -> Seq.pick (fun i -> Some('a')) ([| |] : int[]) |> ignore) + + // Null + CheckThrowsArgumentNullException (fun () -> Seq.pick (fun i -> Some(i + 0)) null |> ignore) + () + + [] + member this.Fold() = + let funcInt x y = x+y + + let IntSeq = + seq { for i in 1..10 do + yield i} |> ISeq.ofSeq + + let foldInt = ISeq.fold funcInt 1 IntSeq + if foldInt <> 56 then Assert.Fail() + + // string ISeq + let funcStr (x:string) (y:string) = x+y + let strSeq = seq ["B"; "C"; "D" ; "E"] |> ISeq.ofSeq + let foldStr = ISeq.fold funcStr "A" strSeq + + if foldStr <> "ABCDE" then Assert.Fail() + + + // Empty ISeq + let emptySeq = ISeq.empty + let foldEmpty = ISeq.fold funcInt 1 emptySeq + if foldEmpty <> 1 then Assert.Fail() + + //// null ISeq + //let nullSeq = null + + //CheckThrowsArgumentNullException (fun () -> ISeq.fold funcInt 1 nullSeq |> ignore) + () + + + + [] + member this.Fold2() = + Assert.AreEqual([(3,5); (2,3); (1,1)],ISeq.fold2 (fun acc x y -> (x,y)::acc) [] (seq [ 1..3 ] |> ISeq.ofSeq) (seq [1..2..6] |> ISeq.ofSeq)) + + // integer List + let funcInt x y z = x + y + z + let resultInt = ISeq.fold2 funcInt 9 (seq [ 1..10 ] |> ISeq.ofSeq) (seq [1..2..20] |> ISeq.ofSeq) + Assert.AreEqual(164, resultInt) + + // string List + let funcStr x y z = x + y + z + let resultStr = ISeq.fold2 funcStr "*" (["a"; "b"; "c" ; "d" ] |> ISeq.ofSeq) (["A"; "B"; "C" ; "D" ] |> ISeq.ofSeq) + Assert.AreEqual("*aAbBcCdD", resultStr) + + // empty List + let emptyArr = [ ] |> ISeq.ofSeq + let resultEpt = ISeq.fold2 funcInt 5 emptyArr emptyArr + Assert.AreEqual(5, resultEpt) + + Assert.AreEqual(0,ISeq.fold2 funcInt 0 ISeq.empty (seq [1] |> ISeq.ofSeq)) + Assert.AreEqual(-1,ISeq.fold2 funcInt -1 (seq [1] |> ISeq.ofSeq) ISeq.empty) + + Assert.AreEqual(2,ISeq.fold2 funcInt 0 (seq [1;2] |> ISeq.ofSeq) (seq [1] |> ISeq.ofSeq)) + Assert.AreEqual(4,ISeq.fold2 funcInt 0 (seq [1] |> ISeq.ofSeq) (seq [3;6] |> ISeq.ofSeq)) + + //// null ISeq + //let nullSeq = null + + //CheckThrowsArgumentNullException (fun () -> ISeq.fold2 funcInt 0 nullSeq (seq [1] |> ISeq.ofSeq) |> ignore) + //CheckThrowsArgumentNullException (fun () -> ISeq.fold2 funcInt 0 (seq [1] |> ISeq.ofSeq) nullSeq |> ignore) + () + + [] + member this.FoldBack() = + // int ISeq + let funcInt x y = x-y + let IntSeq = seq { 1..4 } |> ISeq.ofSeq + let foldInt = ISeq.foldBack funcInt IntSeq 6 + Assert.AreEqual((1-(2-(3-(4-6)))), foldInt) + + // string ISeq + let funcStr (x:string) (y:string) = y.Remove(0,x.Length) + let strSeq = seq [ "A"; "B"; "C"; "D" ] |> ISeq.ofSeq + let foldStr = ISeq.foldBack funcStr strSeq "ABCDE" + Assert.AreEqual("E", foldStr) + + // single element + let funcStr2 elem acc = sprintf "%s%s" elem acc + let strSeq2 = seq [ "A" ] |> ISeq.ofSeq + let foldStr2 = ISeq.foldBack funcStr2 strSeq2 "X" + Assert.AreEqual("AX", foldStr2) + + // Empty ISeq + let emptySeq = ISeq.empty + let foldEmpty = ISeq.foldBack funcInt emptySeq 1 + Assert.AreEqual(1, foldEmpty) + + //// null ISeq + //let nullSeq = null + //CheckThrowsArgumentNullException (fun () -> ISeq.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 = ISeq.foldBack cons IntSeq [] + Assert.AreEqual([1;2;3;4], identityFoldr) + + () + + [] + member this.foldBack2() = + // int ISeq + let funcInt x y z = x + y + z + let intSeq = seq { 1..10 } |> ISeq.ofSeq + let resultInt = ISeq.foldBack2 funcInt intSeq (seq { 1..2..20 } |> ISeq.ofSeq) 9 + Assert.AreEqual(164, resultInt) + + // string ISeq + let funcStr = sprintf "%s%s%s" + let strSeq = seq [ "A"; "B"; "C"; "D" ] |> ISeq.ofSeq + let resultStr = ISeq.foldBack2 funcStr strSeq (seq [ "a"; "b"; "c"; "d"] |> ISeq.ofSeq) "*" + Assert.AreEqual("AaBbCcDd*", resultStr) + + // single element + let strSeqSingle = seq [ "X" ] |> ISeq.ofSeq + Assert.AreEqual("XAZ", ISeq.foldBack2 funcStr strSeqSingle strSeq "Z") + Assert.AreEqual("AXZ", ISeq.foldBack2 funcStr strSeq strSeqSingle "Z") + Assert.AreEqual("XYZ", ISeq.foldBack2 funcStr strSeqSingle (seq [ "Y" ] |> ISeq.ofSeq) "Z") + + // empty ISeq + let emptySeq = ISeq.empty + Assert.AreEqual(1, ISeq.foldBack2 funcInt emptySeq emptySeq 1) + Assert.AreEqual(1, ISeq.foldBack2 funcInt emptySeq intSeq 1) + Assert.AreEqual(1, ISeq.foldBack2 funcInt intSeq emptySeq 1) + + // infinite ISeq + let infiniteSeq = ISeq.initInfinite (fun i -> 2 * i + 1) + Assert.AreEqual(164, ISeq.foldBack2 funcInt intSeq infiniteSeq 9) + Assert.AreEqual(164, ISeq.foldBack2 funcInt infiniteSeq intSeq 9) + + //// null ISeq + //let nullSeq = null + //CheckThrowsArgumentNullException (fun () -> ISeq.foldBack2 funcInt nullSeq intSeq 1 |> ignore) + //CheckThrowsArgumentNullException (fun () -> ISeq.foldBack2 funcInt intSeq nullSeq 1 |> ignore) + //CheckThrowsArgumentNullException (fun () -> ISeq.foldBack2 funcInt nullSeq nullSeq 1 |> ignore) + + () + + [] + member this.ForAll() = + + let funcInt x = if x%2 = 0 then true else false + let IntSeq = + seq { for i in 1..10 do + yield i*2} |> ISeq.ofSeq + let for_allInt = ISeq.forall funcInt IntSeq + + if for_allInt <> true then Assert.Fail() + + + // string ISeq + let funcStr (x:string) = x.Contains("a") + let strSeq = seq ["a"; "ab"; "abc" ; "abcd"] |> ISeq.ofSeq + let for_allStr = ISeq.forall funcStr strSeq + + if for_allStr <> true then Assert.Fail() + + + // Empty ISeq + let emptySeq = ISeq.empty + let for_allEmpty = ISeq.forall funcInt emptySeq + + if for_allEmpty <> true then Assert.Fail() + + //// null ISeq + //let nullSeq = null + //CheckThrowsArgumentNullException (fun () -> ISeq.forall funcInt nullSeq |> ignore) + () + + [] + member this.ForAll2() = + + let funcInt x y = if (x+y)%2 = 0 then true else false + let IntSeq = + seq { for i in 1..10 do + yield i} |> ISeq.ofSeq + + let for_all2Int = ISeq.forall2 funcInt IntSeq IntSeq + + if for_all2Int <> true then Assert.Fail() + + // string ISeq + let funcStr (x:string) (y:string) = (x+y).Length = 5 + let strSeq1 = seq ["a"; "ab"; "abc" ; "abcd"] |> ISeq.ofSeq + let strSeq2 = seq ["abcd"; "abc"; "ab" ; "a"] |> ISeq.ofSeq + let for_all2Str = ISeq.forall2 funcStr strSeq1 strSeq2 + + if for_all2Str <> true then Assert.Fail() + + // Empty ISeq + let emptySeq = ISeq.empty + let for_all2Empty = ISeq.forall2 funcInt emptySeq emptySeq + + if for_all2Empty <> true then Assert.Fail() + + //// null ISeq + //let nullSeq = null + + //CheckThrowsArgumentNullException (fun () -> ISeq.forall2 funcInt nullSeq nullSeq |> ignore) + + [] + member this.GroupBy() = + + let funcInt x = x%5 + + let IntSeq = + seq { for i in 0 .. 9 do + yield i } |> ISeq.ofSeq + + let group_byInt = ISeq.groupByVal funcInt IntSeq |> ISeq.map (fun (i, v) -> i, Seq.toList v) + + let expectedIntSeq = + seq { for i in 0..4 do + yield i, [i; i+5] } |> ISeq.ofSeq + + VerifySeqsEqual group_byInt expectedIntSeq + + // string ISeq + let funcStr (x:string) = x.Length + let strSeq = seq ["length7"; "length 8"; "length7" ; "length 9"] |> ISeq.ofSeq + + let group_byStr = ISeq.groupByVal funcStr strSeq |> ISeq.map (fun (i, v) -> i, Seq.toList v) + let expectedStrSeq = + seq { + yield 7, ["length7"; "length7"] + yield 8, ["length 8"] + yield 9, ["length 9"] } |> ISeq.ofSeq + + VerifySeqsEqual expectedStrSeq group_byStr + + // Empty ISeq + let emptySeq = ISeq.empty + let group_byEmpty = ISeq.groupByVal funcInt emptySeq + let expectedEmptySeq = seq [] + + VerifySeqsEqual expectedEmptySeq group_byEmpty + + //// null ISeq + //let nullSeq = null + //let group_byNull = ISeq.groupByVal funcInt nullSeq + //CheckThrowsArgumentNullException (fun () -> ISeq.iter (fun _ -> ()) group_byNull) + () + + [] + member this.DisposalOfUnstartedEnumerator() = + let run = ref false + let f() = seq { + try + () + finally + run := true + } + + f().GetEnumerator().Dispose() + Assert.IsFalse(!run) + + [] + member this.WeirdLocalNames() = + + let f pc = seq { + yield pc + yield (pc+1) + yield (pc+2) + } + + let l = f 3 |> Seq.toList + Assert.AreEqual([3;4;5], l) + + let f i = seq { + let pc = i*2 + yield pc + yield (pc+1) + yield (pc+2) + } + let l = f 3 |> Seq.toList + Assert.AreEqual([6;7;8], l) + + [] + member this.Contains() = + + // Integer ISeq + let intSeq = seq { 0..9 } |> ISeq.ofSeq + + let ifContainsInt = ISeq.contains 5 intSeq + + Assert.IsTrue(ifContainsInt) + + // String ISeq + let strSeq = seq ["key"; "blank key"] |> ISeq.ofSeq + + let ifContainsStr = ISeq.contains "key" strSeq + + Assert.IsTrue(ifContainsStr) + + // Empty ISeq + let emptySeq = ISeq.empty + let ifContainsEmpty = ISeq.contains 5 emptySeq + + Assert.IsFalse(ifContainsEmpty) + + //// null ISeq + //let nullSeq = null + + //CheckThrowsArgumentNullException (fun () -> ISeq.contains 5 nullSeq |> ignore) diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule2.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule2.fs new file mode 100644 index 0000000000..36d8839f10 --- /dev/null +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule2.fs @@ -0,0 +1,1839 @@ +// 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 + +type ISeqWindowedTestInput<'t> = + { + InputSeq : seq<'t> + WindowSize : int + ExpectedSeq : seq<'t[]> + Exception : Type option + } + +[] +type ISeqModule2() = + + [] + member this.Hd() = + + let IntSeq = + seq { for i in 0 .. 9 do + yield i } |> ISeq.ofSeq + + if ISeq.head IntSeq <> 0 then Assert.Fail() + + // string ISeq + let strSeq = seq ["first"; "second"; "third"] |> ISeq.ofSeq + if ISeq.head strSeq <> "first" then Assert.Fail() + + // Empty ISeq + let emptySeq = ISeq.empty + CheckThrowsArgumentException ( fun() -> ISeq.head emptySeq) + + //// null ISeq + //let nullSeq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () ->ISeq.head nullSeq) + () + + [] + member this.TryHead() = + // int ISeq + let IntSeq = + seq { for i in 0 .. 9 -> i } |> ISeq.ofSeq + + let intResult = ISeq.tryHead IntSeq + + // string ISeq + let strResult = ISeq.tryHead (seq ["first"; "second"; "third"] |> ISeq.ofSeq) + Assert.AreEqual("first", strResult.Value) + + // Empty ISeq + let emptyResult = ISeq.tryHead ISeq.empty + Assert.AreEqual(None, emptyResult) + + //// null ISeq + //let nullSeq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () ->ISeq.head nullSeq) + () + + [] + member this.Tl() = + // integer seq + let resultInt = ISeq.tail <| (seq { 1..10 } |> ISeq.ofSeq) + Assert.AreEqual(Array.ofSeq (seq { 2..10 } |> ISeq.ofSeq), Array.ofSeq resultInt) + + // string seq + let resultStr = ISeq.tail <| (seq { yield "a"; yield "b"; yield "c"; yield "d" } |> ISeq.ofSeq) + Assert.AreEqual(Array.ofSeq (seq { yield "b"; yield "c" ; yield "d" } |> ISeq.ofSeq), Array.ofSeq resultStr) + + // 1-element seq + let resultStr2 = ISeq.tail <| (seq { yield "a" } |> ISeq.ofSeq) + Assert.AreEqual(Array.ofSeq (ISeq.empty ), Array.ofSeq resultStr2) + + //CheckThrowsArgumentNullException(fun () -> ISeq.tail null |> ignore) + CheckThrowsArgumentException(fun () -> ISeq.tail ISeq.empty |> ISeq.iter (fun _ -> failwith "Should not be reached")) + () + + [] + member this.Last() = + + let IntSeq = + seq { for i in 0 .. 9 do + yield i } |> ISeq.ofSeq + + if ISeq.last IntSeq <> 9 then Assert.Fail() + + // string ISeq + let strSeq = seq ["first"; "second"; "third"] |> ISeq.ofSeq + if ISeq.last strSeq <> "third" then Assert.Fail() + + // Empty ISeq + let emptySeq = ISeq.empty + CheckThrowsArgumentException ( fun() -> ISeq.last emptySeq) + + //// null ISeq + //let nullSeq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () ->ISeq.last nullSeq) + () + + [] + member this.TryLast() = + + let IntSeq = + seq { for i in 0 .. 9 -> i } |> ISeq.ofSeq + + let intResult = ISeq.tryLast IntSeq + Assert.AreEqual(9, intResult.Value) + + // string ISeq + let strResult = ISeq.tryLast (seq ["first"; "second"; "third"] |> ISeq.ofSeq) + Assert.AreEqual("third", strResult.Value) + + // Empty ISeq + let emptyResult = ISeq.tryLast ISeq.empty + Assert.IsTrue(emptyResult.IsNone) + + //// null ISeq + //let nullSeq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () ->ISeq.tryLast nullSeq |> ignore) + () + + [] + member this.ExactlyOne() = + + let IntSeq = + seq { for i in 7 .. 7 do + yield i } |> ISeq.ofSeq + + if ISeq.exactlyOne IntSeq <> 7 then Assert.Fail() + + // string ISeq + let strSeq = seq ["second"] |> ISeq.ofSeq + if ISeq.exactlyOne strSeq <> "second" then Assert.Fail() + + // Empty ISeq + let emptySeq = ISeq.empty + CheckThrowsArgumentException ( fun() -> ISeq.exactlyOne emptySeq) + + // non-singleton ISeq + let emptySeq = ISeq.empty + CheckThrowsArgumentException ( fun() -> ISeq.exactlyOne ([ 0 .. 1 ] |> ISeq.ofSeq) |> ignore ) + + //// null ISeq + //let nullSeq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () ->ISeq.exactlyOne nullSeq) + () + + + [] + member this.Init() = + + let funcInt x = x + let init_finiteInt = ISeq.init 9 funcInt + let expectedIntSeq = seq [ 0..8] |> ISeq.ofSeq + + VerifySeqsEqual expectedIntSeq init_finiteInt + + + // string ISeq + let funcStr x = x.ToString() + let init_finiteStr = ISeq.init 5 funcStr + let expectedStrSeq = seq ["0";"1";"2";"3";"4"] |> ISeq.ofSeq + + VerifySeqsEqual expectedStrSeq init_finiteStr + + //// null ISeq + //let funcNull x = null + //let init_finiteNull = ISeq.init 3 funcNull + //let expectedNullSeq = seq [ null;null;null] |> ISeq.ofSeq + + //VerifySeqsEqual expectedNullSeq init_finiteNull + () + + [] + member this.InitInfinite() = + + let funcInt x = x + let init_infiniteInt = ISeq.initInfinite funcInt + let resultint = Seq.find (fun x -> x =100) init_infiniteInt + + Assert.AreEqual(100,resultint) + + + // string ISeq + let funcStr x = x.ToString() + let init_infiniteStr = ISeq.initInfinite funcStr + let resultstr = Seq.find (fun x -> x = "100") init_infiniteStr + + Assert.AreEqual("100",resultstr) + + + [] + member this.IsEmpty() = + + //seq int + let seqint = seq [1;2;3] |> ISeq.ofSeq + let is_emptyInt = Seq.isEmpty seqint + + Assert.IsFalse(is_emptyInt) + + //seq str + let seqStr = seq["first";"second"] + let is_emptyStr = Seq.isEmpty seqStr + + Assert.IsFalse(is_emptyInt) + + //seq empty + let seqEmpty = ISeq.empty + let is_emptyEmpty = Seq.isEmpty seqEmpty + Assert.IsTrue(is_emptyEmpty) + + //seq null + let seqnull:seq<'a> = null + CheckThrowsArgumentNullException (fun () -> Seq.isEmpty seqnull |> ignore) + () + + [] + member this.Iter() = + //seq int + let seqint = seq [ 1..3] |> ISeq.ofSeq + let cacheint = ref 0 + + let funcint x = cacheint := !cacheint + x + ISeq.iter funcint seqint + Assert.AreEqual(6,!cacheint) + + //seq str + let seqStr = seq ["first";"second"] |> ISeq.ofSeq + let cachestr =ref "" + let funcstr x = cachestr := !cachestr+x + ISeq.iter funcstr seqStr + + Assert.AreEqual("firstsecond",!cachestr) + + // empty array + let emptyseq = ISeq.empty + let resultEpt = ref 0 + ISeq.iter (fun x -> Assert.Fail()) emptyseq + + // null seqay + //let nullseq:seq<'a> = null + + //CheckThrowsArgumentNullException (fun () -> ISeq.iter funcint nullseq |> ignore) + () + + [] + member this.Iter2() = + + //seq int + let seqint = seq [ 1..3] |> ISeq.ofSeq + let cacheint = ref 0 + + let funcint x y = cacheint := !cacheint + x+y + ISeq.iter2 funcint seqint seqint + Assert.AreEqual(12,!cacheint) + + //seq str + let seqStr = seq ["first";"second"]|> ISeq.ofSeq + let cachestr =ref "" + let funcstr x y = cachestr := !cachestr+x+y + ISeq.iter2 funcstr seqStr seqStr + + Assert.AreEqual("firstfirstsecondsecond",!cachestr) + + // empty array + let emptyseq = ISeq.empty + let resultEpt = ref 0 + ISeq.iter2 (fun x y-> Assert.Fail()) emptyseq emptyseq + + //// null seqay + //let nullseq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.iter2 funcint nullseq nullseq |> ignore) + + () + + [] + member this.Iteri() = + + // seq int + let seqint = seq [ 1..10] |> ISeq.ofSeq + let cacheint = ref 0 + + let funcint x y = cacheint := !cacheint + x+y + ISeq.iteri funcint seqint + Assert.AreEqual(100,!cacheint) + + // seq str + let seqStr = seq ["first";"second"]|> ISeq.ofSeq + let cachestr =ref 0 + let funcstr (x:int) (y:string) = cachestr := !cachestr+ x + y.Length + ISeq.iteri funcstr seqStr + + Assert.AreEqual(12,!cachestr) + + // empty array + let emptyseq = ISeq.empty + let resultEpt = ref 0 + ISeq.iteri funcint emptyseq + Assert.AreEqual(0,!resultEpt) + + //// null seqay + //let nullseq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.iteri funcint nullseq |> ignore) + () + + [] + member this.Iteri2() = + + //seq int + let seqint = seq [ 1..3] |> ISeq.ofSeq + let cacheint = ref 0 + + let funcint x y z = cacheint := !cacheint + x + y + z + ISeq.iteri2 funcint seqint seqint + Assert.AreEqual(15,!cacheint) + + //seq str + let seqStr = seq ["first";"second"]|> ISeq.ofSeq + let cachestr = ref 0 + let funcstr (x:int) (y:string) (z:string) = cachestr := !cachestr + x + y.Length + z.Length + ISeq.iteri2 funcstr seqStr seqStr + + Assert.AreEqual(23,!cachestr) + + // empty seq + let emptyseq = ISeq.empty + let resultEpt = ref 0 + ISeq.iteri2 (fun x y z -> Assert.Fail()) emptyseq emptyseq + + //// null seq + //let nullseq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.iteri2 funcint nullseq nullseq |> ignore) + + // len1 <> len2 + let shorterSeq = seq { 1..3 } |> ISeq.ofSeq + let longerSeq = seq { 2..2..100 } |> ISeq.ofSeq + + let testSeqLengths seq1 seq2 = + let cache = ref 0 + let f x y z = cache := !cache + x + y + z + ISeq.iteri2 f seq1 seq2 + !cache + + Assert.AreEqual(21, testSeqLengths shorterSeq longerSeq) + Assert.AreEqual(21, testSeqLengths longerSeq shorterSeq) + + () + + [] + member this.Length() = + + // integer seq + let resultInt = ISeq.length ({1..8}|> ISeq.ofSeq) + if resultInt <> 8 then Assert.Fail() + + // string ISeq + let resultStr = ISeq.length (seq ["Lists"; "are"; "commonly" ; "list" ]|> ISeq.ofSeq) + if resultStr <> 4 then Assert.Fail() + + // empty ISeq + let resultEpt = ISeq.length ISeq.empty + if resultEpt <> 0 then Assert.Fail() + + //// null ISeq + //let nullSeq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.length nullSeq |> ignore) + + () + + [] + member this.Map() = + + // integer ISeq + let funcInt x = + match x with + | _ when x % 2 = 0 -> 10*x + | _ -> x + + let resultInt = ISeq.map funcInt ({ 1..10 }|> ISeq.ofSeq) + let expectedint = seq [1;20;3;40;5;60;7;80;9;100] + + VerifySeqsEqual expectedint resultInt + + // string ISeq + let funcStr (x:string) = x.ToLower() + let resultStr = ISeq.map funcStr (seq ["Lists"; "Are"; "Commonly" ; "List" ] |> ISeq.ofSeq) + let expectedSeq = seq ["lists"; "are"; "commonly" ; "list"] |> ISeq.ofSeq + + VerifySeqsEqual expectedSeq resultStr + + // empty ISeq + let resultEpt = ISeq.map funcInt ISeq.empty + VerifySeqsEqual ISeq.empty resultEpt + + //// null ISeq + //let nullSeq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.map funcStr nullSeq |> ignore) + + () + + [] + member this.Map2() = + // integer ISeq + let funcInt x y = x+y + let resultInt = ISeq.map2 funcInt ({ 1..10 }|> ISeq.ofSeq) ( {2..2..20} |> ISeq.ofSeq) + let expectedint = seq [3;6;9;12;15;18;21;24;27;30]|> ISeq.ofSeq + + VerifySeqsEqual expectedint resultInt + + // string ISeq + let funcStr (x:int) (y:string) = x+y.Length + let resultStr = ISeq.map2 funcStr (seq[3;6;9;11] |> ISeq.ofSeq) (seq ["Lists"; "Are"; "Commonly" ; "List" ] |> ISeq.ofSeq) + let expectedSeq = seq [8;9;17;15] + + VerifySeqsEqual expectedSeq resultStr + + // empty ISeq + let resultEpt = ISeq.map2 funcInt ISeq.empty ISeq.empty + VerifySeqsEqual ISeq.empty resultEpt + + //// null ISeq + //let nullSeq:seq<'a> = null + //let validSeq = seq [1] + //CheckThrowsArgumentNullException (fun () -> ISeq.map2 funcInt nullSeq validSeq |> ignore) + + () + + [] + member this.Map3() = + // Integer seq + let funcInt a b c = (a + b) * c + let resultInt = ISeq.map3 funcInt ({ 1..8 }|> ISeq.ofSeq)( { 2..9 }|> ISeq.ofSeq)( { 3..10 }|> ISeq.ofSeq) + let expectedInt = seq [9; 20; 35; 54; 77; 104; 135; 170] + VerifySeqsEqual expectedInt resultInt + + // First seq is shorter + VerifySeqsEqual (seq [9; 20]) (ISeq.map3 funcInt ({ 1..2 }|> ISeq.ofSeq)( { 2..9 }|> ISeq.ofSeq)( { 3..10 }|> ISeq.ofSeq)) + // Second seq is shorter + VerifySeqsEqual (seq [9; 20; 35]) (ISeq.map3 funcInt ({ 1..8 }|> ISeq.ofSeq)( { 2..4 }|> ISeq.ofSeq)( { 3..10 }|> ISeq.ofSeq)) + // Third seq is shorter + VerifySeqsEqual (seq [9; 20; 35; 54]) (ISeq.map3 funcInt ({ 1..8 }|> ISeq.ofSeq) ( { 2..6 }|> ISeq.ofSeq)( { 3..6 }|> ISeq.ofSeq)) + + // String seq + let funcStr a b c = a + b + c + let resultStr = ISeq.map3 funcStr (["A";"B";"C";"D"]|> ISeq.ofSeq) ( ["a";"b";"c";"d"]|> ISeq.ofSeq)( ["1";"2";"3";"4"]|> ISeq.ofSeq) + let expectedStr = seq ["Aa1";"Bb2";"Cc3";"Dd4"]|> ISeq.ofSeq + VerifySeqsEqual expectedStr resultStr + + // Empty seq + let resultEmpty = ISeq.map3 funcStr ISeq.empty ISeq.empty ISeq.empty + VerifySeqsEqual ISeq.empty resultEmpty + + //// Null seq + //let nullSeq = null : seq<_> + //let nonNullSeq = seq [1] + //CheckThrowsArgumentNullException (fun () -> ISeq.map3 funcInt nullSeq nonNullSeq nullSeq |> ignore) + + () + + [] + member this.MapFold() = + // integer ISeq + let funcInt acc x = if x % 2 = 0 then 10*x, acc + 1 else x, acc + let resultInt,resultIntAcc = Seq.mapFold funcInt 100 <| seq { 1..10 } + VerifySeqsEqual (seq [ 1;20;3;40;5;60;7;80;9;100 ]) resultInt + Assert.AreEqual(105, resultIntAcc) + + // string ISeq + let funcStr acc (x:string) = match x.Length with 0 -> "empty", acc | _ -> x.ToLower(), sprintf "%s%s" acc x + let resultStr,resultStrAcc = Seq.mapFold funcStr "" <| seq [ "";"BB";"C";"" ] + VerifySeqsEqual (seq [ "empty";"bb";"c";"empty" ]) resultStr + Assert.AreEqual("BBC", resultStrAcc) + + // empty ISeq + let resultEpt,resultEptAcc = Seq.mapFold funcInt 100 ISeq.empty + VerifySeqsEqual ISeq.empty resultEpt + Assert.AreEqual(100, resultEptAcc) + + //// null ISeq + //let nullArr = null:seq + //CheckThrowsArgumentNullException (fun () -> Seq.mapFold funcStr "" nullArr |> ignore) + + () + + [] + member this.MapFoldBack() = + // integer ISeq + let funcInt x acc = if acc < 105 then 10*x, acc + 2 else x, acc + let resultInt,resultIntAcc = Seq.mapFoldBack funcInt (seq { 1..10 }) 100 + VerifySeqsEqual (seq [ 1;2;3;4;5;6;7;80;90;100 ]) resultInt + Assert.AreEqual(106, resultIntAcc) + + // string ISeq + let funcStr (x:string) acc = match x.Length with 0 -> "empty", acc | _ -> x.ToLower(), sprintf "%s%s" acc x + let resultStr,resultStrAcc = Seq.mapFoldBack funcStr (seq [ "";"BB";"C";"" ]) "" + VerifySeqsEqual (seq [ "empty";"bb";"c";"empty" ]) resultStr + Assert.AreEqual("CBB", resultStrAcc) + + // empty ISeq + let resultEpt,resultEptAcc = Seq.mapFoldBack funcInt ISeq.empty 100 + VerifySeqsEqual ISeq.empty resultEpt + Assert.AreEqual(100, resultEptAcc) + + //// null ISeq + //let nullArr = null:seq + //CheckThrowsArgumentNullException (fun () -> Seq.mapFoldBack funcStr nullArr "" |> ignore) + + () + + member private this.MapWithSideEffectsTester (map : (int -> int) -> ISeq.Core.ISeq -> ISeq.Core.ISeq) expectExceptions = + let i = ref 0 + let f x = i := !i + 1; x*x + let e = (([1;2]|>ISeq.ofSeq) |> 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.ofSeq) |> 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.Core.ISeq -> ISeq.Core.ISeq) = + let raiser x = if x > 0 then raise(NotSupportedException()) else x + let e = (map raiser ([0; 1]|> ISeq.ofSeq)).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 ISeq.map true + + [] + member this.MapWithException () = + this.MapWithExceptionTester ISeq.map + + + //[] + //member this.SingletonCollectWithSideEffects () = + // this.MapWithSideEffectsTester (fun f-> Seq.collect (f >> Seq.singleton)) true + + //[] + //member this.SingletonCollectWithException () = + // this.MapWithExceptionTester (fun f-> Seq.collect (f >> Seq.singleton)) + +//#if !FX_NO_LINQ +// [] +// member this.SystemLinqSelectWithSideEffects () = +// this.MapWithSideEffectsTester (fun f s -> System.Linq.Enumerable.Select(s, Func<_,_>(f))) false + +// [] +// member this.SystemLinqSelectWithException () = +// this.MapWithExceptionTester (fun f s -> 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 = (([1;2]|> ISeq.ofSeq) |> ISeq.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.ofSeq) |> ISeq.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 = (ISeq.map2 f ([1;2]|> ISeq.ofSeq) ([1;2]|> ISeq.ofSeq)).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.map2 f ([]|> ISeq.ofSeq) ([]|> ISeq.ofSeq)).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 = (ISeq.mapi2 f ([1;2]|> ISeq.ofSeq) ([1;2]|> ISeq.ofSeq)).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.mapi2 f ([]|> ISeq.ofSeq) ([]|> ISeq.ofSeq)).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 ISeq + let funcInt x = seq [x+1] + let resultInt = Seq.collect funcInt { 1..10 } + + let expectedint = seq {2..11} + + VerifySeqsEqual expectedint resultInt + +#if !FX_NO_CHAR_PARSE + // string ISeq + let funcStr (y:string) = y+"ist" + + let resultStr = Seq.collect funcStr (seq ["L"]) + + + let expectedSeq = seq ['L';'i';'s';'t'] + + VerifySeqsEqual expectedSeq resultStr +#endif + // empty ISeq + let resultEpt = Seq.collect funcInt ISeq.empty + VerifySeqsEqual ISeq.empty resultEpt + + //// null ISeq + //let nullSeq:seq<'a> = null + + //CheckThrowsArgumentNullException (fun () -> Seq.collect funcInt nullSeq |> ignore) + + () + + [] + member this.Mapi() = + + // integer ISeq + let funcInt x y = x+y + let resultInt = ISeq.mapi funcInt ({ 10..2..20 } |> ISeq.ofSeq) + let expectedint = seq [10;13;16;19;22;25] + + VerifySeqsEqual expectedint resultInt + + // string ISeq + let funcStr (x:int) (y:string) =x+y.Length + + let resultStr = ISeq.mapi funcStr (seq ["Lists"; "Are"; "Commonly" ; "List" ] |> ISeq.ofSeq) + let expectedStr = seq [5;4;10;7] + + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.mapi funcInt ISeq.empty + VerifySeqsEqual ISeq.empty resultEpt + + //// null ISeq + //let nullSeq:seq<'a> = null + + //CheckThrowsArgumentNullException (fun () -> ISeq.mapi funcInt nullSeq |> ignore) + + () + + [] + member this.Mapi2() = + // integer ISeq + let funcInt x y z = x+y+z + let resultInt = ISeq.mapi2 funcInt ({ 1..10 }|> ISeq.ofSeq)( {2..2..20}|> ISeq.ofSeq) + let expectedint = seq [3;7;11;15;19;23;27;31;35;39] + + VerifySeqsEqual expectedint resultInt + + // string ISeq + let funcStr (x:int) (y:int) (z:string) = x+y+z.Length + let resultStr = ISeq.mapi2 funcStr (seq[3;6;9;11]|> ISeq.ofSeq) (seq ["Lists"; "Are"; "Commonly" ; "List" ]|> ISeq.ofSeq) + let expectedSeq = seq [8;10;19;18] + + VerifySeqsEqual expectedSeq resultStr + + // empty ISeq + let resultEpt = ISeq.mapi2 funcInt ISeq.empty ISeq.empty + VerifySeqsEqual ISeq.empty resultEpt + + //// null ISeq + //let nullSeq:seq<'a> = null + //let validSeq = seq [1] + //CheckThrowsArgumentNullException (fun () -> ISeq.mapi2 funcInt nullSeq validSeq |> ignore) + + // len1 <> len2 + let shorterSeq = seq { 1..10 }|> ISeq.ofSeq + let longerSeq = seq { 2..20 }|> ISeq.ofSeq + + let testSeqLengths seq1 seq2 = + let f x y z = x + y + z + ISeq.mapi2 f seq1 seq2 + + VerifySeqsEqual (seq [3;6;9;12;15;18;21;24;27;30]|> ISeq.ofSeq) (testSeqLengths shorterSeq longerSeq) + VerifySeqsEqual (seq [3;6;9;12;15;18;21;24;27;30]|> ISeq.ofSeq) (testSeqLengths longerSeq shorterSeq) + + [] + member this.Indexed() = + + // integer ISeq + let resultInt = ISeq.indexed ({ 10..2..20 }|> ISeq.ofSeq) + let expectedint = seq [(0,10);(1,12);(2,14);(3,16);(4,18);(5,20)]|> ISeq.ofSeq + + VerifySeqsEqual expectedint resultInt + + // string ISeq + let resultStr = ISeq.indexed (seq ["Lists"; "Are"; "Commonly"; "List" ]|> ISeq.ofSeq) + let expectedStr = seq [(0,"Lists");(1,"Are");(2,"Commonly");(3,"List")]|> ISeq.ofSeq + + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.indexed ISeq.empty + VerifySeqsEqual ISeq.empty resultEpt + + //// null ISeq + //let nullSeq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.indexed nullSeq |> ignore) + + () + + [] + member this.Max() = + // integer ISeq + let resultInt = ISeq.max ({ 10..20 } |> ISeq.ofSeq) + + Assert.AreEqual(20,resultInt) + + // string ISeq + + let resultStr = ISeq.max (seq ["Lists"; "Are"; "MaxString" ; "List" ]|> ISeq.ofSeq) + Assert.AreEqual("MaxString",resultStr) + + // empty ISeq + CheckThrowsArgumentException(fun () -> ISeq.max ( ISeq.empty ) |> ignore) + + //// null ISeq + //let nullSeq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.max nullSeq |> ignore) + + () + + [] + member this.MaxBy() = + + // integer ISeq + let funcInt x = x % 8 + let resultInt = ISeq.maxBy funcInt ({ 2..2..20 } |> ISeq.ofSeq) + Assert.AreEqual(6,resultInt) + + // string ISeq + let funcStr (x:string) =x.Length + let resultStr = ISeq.maxBy funcStr (seq ["Lists"; "Are"; "Commonly" ; "List" ]|> ISeq.ofSeq) + Assert.AreEqual("Commonly",resultStr) + + // empty ISeq + CheckThrowsArgumentException (fun () -> ISeq.maxBy funcInt (ISeq.empty ) |> ignore) + + //// null ISeq + //let nullSeq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () ->ISeq.maxBy funcInt nullSeq |> ignore) + + () + + [] + member this.MinBy() = + + // integer ISeq + let funcInt x = x % 8 + let resultInt = ISeq.minBy funcInt ({ 2..2..20 } |> ISeq.ofSeq) + Assert.AreEqual(8,resultInt) + + // string ISeq + let funcStr (x:string) =x.Length + let resultStr = ISeq.minBy funcStr (seq ["Lists"; "Are"; "Commonly" ; "List" ]|> ISeq.ofSeq) + Assert.AreEqual("Are",resultStr) + + // empty ISeq + CheckThrowsArgumentException (fun () -> ISeq.minBy funcInt (ISeq.empty ) |> ignore) + + //// null ISeq + //let nullSeq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () ->ISeq.minBy funcInt nullSeq |> ignore) + + () + + + [] + member this.Min() = + + // integer ISeq + let resultInt = ISeq.min ({ 10..20 } |> ISeq.ofSeq) + Assert.AreEqual(10,resultInt) + + // string ISeq + let resultStr = ISeq.min (seq ["Lists"; "Are"; "minString" ; "List" ]|> ISeq.ofSeq) + Assert.AreEqual("Are",resultStr) + + // empty ISeq + CheckThrowsArgumentException (fun () -> ISeq.min (ISeq.empty ) |> ignore) + + //// null ISeq + //let nullSeq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.min nullSeq |> ignore) + + () + + [] + member this.Item() = + // integer ISeq + let resultInt = Seq.item 3 ({ 10..20 }|> ISeq.ofSeq) + Assert.AreEqual(13, resultInt) + + // string ISeq + let resultStr = Seq.item 2 (seq ["Lists"; "Are"; "Cool" ; "List" ]|> ISeq.ofSeq) + Assert.AreEqual("Cool", resultStr) + + // empty ISeq + CheckThrowsArgumentException(fun () -> Seq.item 0 (ISeq.empty ) |> ignore) + + //// null ISeq + //let nullSeq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () ->Seq.item 3 nullSeq |> ignore) + + // Negative index + for i = -1 downto -10 do + CheckThrowsArgumentException (fun () -> Seq.item i { 10 .. 20 } |> ignore) + + // Out of range + for i = 11 to 20 do + CheckThrowsArgumentException (fun () -> Seq.item i { 10 .. 20 } |> ignore) + + [] + member this.``item should fail with correct number of missing elements``() = + try + Seq.item 0 (Array.zeroCreate 0) |> ignore + failwith "error expected" + with + | exn when exn.Message.Contains("seq was short by 1 element") -> () + + try + Seq.item 2 (Array.zeroCreate 0) |> ignore + failwith "error expected" + with + | exn when exn.Message.Contains("seq was short by 3 elements") -> () + + [] + member this.Of_Array() = + // integer ISeq + let resultInt = ISeq.ofArray [|1..10|] + let expectedInt = {1..10} + + VerifySeqsEqual expectedInt resultInt + + // string ISeq + let resultStr = ISeq.ofArray [|"Lists"; "Are"; "ofArrayString" ; "List" |] + let expectedStr = seq ["Lists"; "Are"; "ofArrayString" ; "List" ] + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.ofArray [| |] + VerifySeqsEqual resultEpt ISeq.empty + + () + + [] + member this.Of_List() = + // integer ISeq + let resultInt = ISeq.ofList [1..10] + let expectedInt = {1..10} + + VerifySeqsEqual expectedInt resultInt + + // string ISeq + + let resultStr =ISeq.ofList ["Lists"; "Are"; "ofListString" ; "List" ] + let expectedStr = seq ["Lists"; "Are"; "ofListString" ; "List" ] + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.ofList [] + VerifySeqsEqual resultEpt ISeq.empty + () + + + [] + member this.Pairwise() = + // integer ISeq + let resultInt = ISeq.pairwise ({1..3}|>ISeq.ofSeq) + + let expectedInt = seq [1,2;2,3] + + VerifySeqsEqual expectedInt resultInt + + // string ISeq + let resultStr =ISeq.pairwise (["str1"; "str2";"str3" ]|>ISeq.ofSeq) + let expectedStr = seq ["str1","str2";"str2","str3"]|>ISeq.ofSeq + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.pairwise ([] |>ISeq.ofSeq) + VerifySeqsEqual resultEpt ISeq.empty + + () + + [] + member this.Reduce() = + + // integer ISeq + let resultInt = ISeq.reduce (fun x y -> x/y) (seq [5*4*3*2; 4;3;2;1] |> ISeq.ofSeq) + Assert.AreEqual(5,resultInt) + + // string ISeq + let resultStr = ISeq.reduce (fun (x:string) (y:string) -> x.Remove(0,y.Length)) (seq ["ABCDE";"A"; "B"; "C" ; "D" ] |> ISeq.ofSeq) + Assert.AreEqual("E",resultStr) + + // empty ISeq + CheckThrowsArgumentException (fun () -> ISeq.reduce (fun x y -> x/y) ISeq.empty |> ignore) + + //// null ISeq + //let nullSeq : seq<'a> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.reduce (fun (x:string) (y:string) -> x.Remove(0,y.Length)) nullSeq |> ignore) + () + + [] + member this.ReduceBack() = + // int ISeq + let funcInt x y = x - y + let IntSeq = seq { 1..4 } |> ISeq.ofSeq + let reduceInt = ISeq.reduceBack funcInt IntSeq + Assert.AreEqual((1-(2-(3-4))), reduceInt) + + // string ISeq + let funcStr (x:string) (y:string) = y.Remove(0,x.Length) + let strSeq = seq [ "A"; "B"; "C"; "D" ; "ABCDE" ] |> ISeq.ofSeq + let reduceStr = ISeq.reduceBack funcStr strSeq + Assert.AreEqual("E", reduceStr) + + // string ISeq + let funcStr2 elem acc = sprintf "%s%s" elem acc + let strSeq2 = seq [ "A" ] |> ISeq.ofSeq + let reduceStr2 = ISeq.reduceBack funcStr2 strSeq2 + Assert.AreEqual("A", reduceStr2) + + // Empty ISeq + CheckThrowsArgumentException (fun () -> ISeq.reduceBack funcInt ISeq.empty |> ignore) + + //// null ISeq + //let nullSeq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.reduceBack funcInt nullSeq |> ignore) + + () + + [] + member this.Rev() = + // integer ISeq + let resultInt = ISeq.rev (seq [5;4;3;2;1] |> ISeq.ofSeq) + VerifySeqsEqual (seq[1;2;3;4;5]) resultInt + + // string ISeq + let resultStr = ISeq.rev (seq ["A"; "B"; "C" ; "D" ] |> ISeq.ofSeq) + VerifySeqsEqual (seq["D";"C";"B";"A"]) resultStr + + // empty ISeq + VerifySeqsEqual ISeq.empty (ISeq.rev ISeq.empty) + + //// null ISeq + //let nullSeq : seq<'a> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.rev nullSeq |> ignore) + () + + [] + member this.Scan() = + // integer ISeq + let funcInt x y = x+y + let resultInt = ISeq.scan funcInt 9 ({1..10}|> ISeq.ofSeq) + let expectedInt = seq [9;10;12;15;19;24;30;37;45;54;64] |> ISeq.ofSeq + VerifySeqsEqual expectedInt resultInt + + // string ISeq + let funcStr x y = x+y + let resultStr =ISeq.scan funcStr "x" (["str1"; "str2";"str3" ]|> ISeq.ofSeq) + + let expectedStr = seq ["x";"xstr1"; "xstr1str2";"xstr1str2str3"]|> ISeq.ofSeq + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.scan funcInt 5 ISeq.empty + + VerifySeqsEqual resultEpt (seq [ 5]) + + //// null ISeq + //let seqNull:seq<'a> = null + //CheckThrowsArgumentNullException(fun() -> ISeq.scan funcInt 5 seqNull |> ignore) + () + + [] + member this.ScanBack() = + // integer ISeq + let funcInt x y = x+y + let resultInt = ISeq.scanBack funcInt ({ 1..10 }|> ISeq.ofSeq) 9 + let expectedInt = seq [64;63;61;58;54;49;43;36;28;19;9] + VerifySeqsEqual expectedInt resultInt + + // string ISeq + let funcStr x y = x+y + let resultStr = ISeq.scanBack funcStr (seq ["A";"B";"C";"D"]|> ISeq.ofSeq) "X" + let expectedStr = seq ["ABCDX";"BCDX";"CDX";"DX";"X"]|> ISeq.ofSeq + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.scanBack funcInt ISeq.empty 5 + let expectedEpt = seq [5] + VerifySeqsEqual expectedEpt resultEpt + + //// null ISeq + //let seqNull:seq<'a> = null + //CheckThrowsArgumentNullException(fun() -> ISeq.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 = ISeq.scanBack funcEx (seq {1..10} |> ISeq.ofSeq) 0 + // reading from resultEx throws + CheckThrowsFormatException(fun() -> ISeq.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 = ISeq.scanBack funcState (seq {1..3} |> ISeq.ofSeq) 0 + Assert.AreEqual(0, !i) + use e = resultState.GetEnumerator() + Assert.AreEqual(6, !i) + + () + + [] + member this.Singleton() = + // integer ISeq + let resultInt = Seq.singleton 1 + + let expectedInt = seq [1] |> ISeq.ofSeq + VerifySeqsEqual expectedInt resultInt + + // string ISeq + let resultStr =Seq.singleton "str1" + let expectedStr = seq ["str1"] |> ISeq.ofSeq + VerifySeqsEqual expectedStr resultStr + + //// null ISeq + //let resultNull = Seq.singleton null + //let expectedNull = seq [null] + //VerifySeqsEqual expectedNull resultNull + () + + + [] + member this.Skip() = + + // integer ISeq + let resultInt = ISeq.skip 2 (seq [1;2;3;4] |> ISeq.ofSeq) + let expectedInt = seq [3;4] |> ISeq.ofSeq + VerifySeqsEqual expectedInt resultInt + + // string ISeq + let resultStr =ISeq.skip 2 (seq ["str1";"str2";"str3";"str4"] |> ISeq.ofSeq) + let expectedStr = seq ["str3";"str4"] |> ISeq.ofSeq + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.skip 0 ISeq.empty + VerifySeqsEqual resultEpt ISeq.empty + + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> ISeq.skip 1 null |> ignore) + () + + [] + member this.Skip_While() = + + // integer ISeq + let funcInt x = (x < 3) + let resultInt = ISeq.skipWhile funcInt (seq [1;2;3;4;5;6] |> ISeq.ofSeq) + let expectedInt = seq [3;4;5;6] |> ISeq.ofSeq + VerifySeqsEqual expectedInt resultInt + + // string ISeq + let funcStr (x:string) = x.Contains(".") + let resultStr =ISeq.skipWhile funcStr (seq [".";"asdfasdf.asdfasdf";"";"";"";"";"";"";"";"";""] |> ISeq.ofSeq) + let expectedStr = seq ["";"";"";"";"";"";"";"";""] |> ISeq.ofSeq + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.skipWhile funcInt ISeq.empty + VerifySeqsEqual resultEpt ISeq.empty + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> ISeq.skipWhile funcInt null |> ignore) + () + + [] + member this.Sort() = + + // integer ISeq + let resultInt = ISeq.sort (seq [1;3;2;4;6;5;7] |> ISeq.ofSeq) + let expectedInt = {1..7} |> ISeq.ofSeq + VerifySeqsEqual expectedInt resultInt + + // string ISeq + + let resultStr =ISeq.sort (seq ["str1";"str3";"str2";"str4"] |> ISeq.ofSeq) + let expectedStr = seq ["str1";"str2";"str3";"str4"] |> ISeq.ofSeq + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.sort ISeq.empty + VerifySeqsEqual resultEpt ISeq.empty + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> ISeq.sort null |> ignore) + () + + [] + member this.SortBy() = + + // integer ISeq + let funcInt x = Math.Abs(x-5) + let resultInt = ISeq.sortBy funcInt (seq [1;2;4;5;7] |> ISeq.ofSeq) + let expectedInt = seq [5;4;7;2;1] |> ISeq.ofSeq + VerifySeqsEqual expectedInt resultInt + + // string ISeq + let funcStr (x:string) = x.IndexOf("key") + let resultStr =ISeq.sortBy funcStr (seq ["st(key)r";"str(key)";"s(key)tr";"(key)str"] |> ISeq.ofSeq) + + let expectedStr = seq ["(key)str";"s(key)tr";"st(key)r";"str(key)"] |> ISeq.ofSeq + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.sortBy funcInt ISeq.empty + VerifySeqsEqual resultEpt ISeq.empty + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> ISeq.sortBy funcInt null |> ignore) + () + + [] + member this.SortDescending() = + + // integer ISeq + let resultInt = Seq.sortDescending (seq [1;3;2;Int32.MaxValue;4;6;Int32.MinValue;5;7;0]) + let expectedInt = seq{ + yield Int32.MaxValue; + yield! seq{ 7..-1..0 } + yield Int32.MinValue + } + VerifySeqsEqual expectedInt resultInt + + // string ISeq + + let resultStr = Seq.sortDescending (seq ["str1";null;"str3";"";"Str1";"str2";"str4"]) + let expectedStr = seq ["str4";"str3";"str2";"str1";"Str1";"";null] + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = Seq.sortDescending ISeq.empty + VerifySeqsEqual resultEpt ISeq.empty + + // tuple ISeq + let tupSeq = (seq[(2,"a");(1,"d");(1,"b");(1,"a");(2,"x");(2,"b");(1,"x")]) + let resultTup = Seq.sortDescending tupSeq + let expectedTup = (seq[(2,"x");(2,"b");(2,"a");(1,"x");(1,"d");(1,"b");(1,"a")]) + VerifySeqsEqual expectedTup resultTup + + // float ISeq + let minFloat,maxFloat,epsilon = System.Double.MinValue,System.Double.MaxValue,System.Double.Epsilon + let floatSeq = seq [0.0; 0.5; 2.0; 1.5; 1.0; minFloat;maxFloat;epsilon;-epsilon] + let resultFloat = Seq.sortDescending floatSeq + let expectedFloat = seq [maxFloat; 2.0; 1.5; 1.0; 0.5; epsilon; 0.0; -epsilon; minFloat; ] + VerifySeqsEqual expectedFloat resultFloat + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> ISeq.sort null |> ignore) + () + + [] + member this.SortByDescending() = + + // integer ISeq + let funcInt x = Math.Abs(x-5) + let resultInt = Seq.sortByDescending funcInt (seq [1;2;4;5;7]) + let expectedInt = seq [1;2;7;4;5] + VerifySeqsEqual expectedInt resultInt + + // string ISeq + let funcStr (x:string) = x.IndexOf("key") + let resultStr =Seq.sortByDescending funcStr (seq ["st(key)r";"str(key)";"s(key)tr";"(key)str"]) + + let expectedStr = seq ["str(key)";"st(key)r";"s(key)tr";"(key)str"] + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = Seq.sortByDescending funcInt ISeq.empty + VerifySeqsEqual resultEpt ISeq.empty + + // tuple ISeq + let tupSeq = (seq[(2,"a");(1,"d");(1,"b");(1,"a");(2,"x");(2,"b");(1,"x")]) + let resultTup = Seq.sortByDescending snd tupSeq + let expectedTup = (seq[(2,"x");(1,"x");(1,"d");(1,"b");(2,"b");(2,"a");(1,"a")]) + VerifySeqsEqual expectedTup resultTup + + // float ISeq + let minFloat,maxFloat,epsilon = System.Double.MinValue,System.Double.MaxValue,System.Double.Epsilon + let floatSeq = seq [0.0; 0.5; 2.0; 1.5; 1.0; minFloat;maxFloat;epsilon;-epsilon] + let resultFloat = Seq.sortByDescending id floatSeq + let expectedFloat = seq [maxFloat; 2.0; 1.5; 1.0; 0.5; epsilon; 0.0; -epsilon; minFloat; ] + VerifySeqsEqual expectedFloat resultFloat + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> Seq.sortByDescending funcInt null |> ignore) + () + + member this.SortWith() = + + // integer ISeq + let intComparer a b = compare (a%3) (b%3) + let resultInt = ISeq.sortWith intComparer (seq {0..10} |> ISeq.ofSeq) + let expectedInt = seq [0;3;6;9;1;4;7;10;2;5;8]|> ISeq.ofSeq + VerifySeqsEqual expectedInt resultInt + + // string ISeq + let resultStr = ISeq.sortWith compare (seq ["str1";"str3";"str2";"str4"]|> ISeq.ofSeq) + let expectedStr = seq ["str1";"str2";"str3";"str4"]|> ISeq.ofSeq + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.sortWith intComparer ISeq.empty + VerifySeqsEqual resultEpt ISeq.empty + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> ISeq.sortWith intComparer null |> ignore) + + () + + [] + member this.Sum() = + + // integer ISeq + let resultInt = ISeq.sum (seq [1..10]|> ISeq.ofSeq) + Assert.AreEqual(55,resultInt) + + // float32 ISeq + let floatSeq = (seq [ 1.2f;3.5f;6.7f ])|> ISeq.ofSeq + let resultFloat = ISeq.sum floatSeq + if resultFloat <> 11.4f then Assert.Fail() + + // double ISeq + let doubleSeq = (seq [ 1.0;8.0 ])|> ISeq.ofSeq + let resultDouble = ISeq.sum doubleSeq + if resultDouble <> 9.0 then Assert.Fail() + + // decimal ISeq + let decimalSeq = (seq [ 0M;19M;19.03M ])|> ISeq.ofSeq + let resultDecimal = ISeq.sum decimalSeq + if resultDecimal <> 38.03M then Assert.Fail() + + + // empty float32 ISeq + let emptyFloatSeq = ISeq.empty + let resultEptFloat = ISeq.sum emptyFloatSeq + if resultEptFloat <> 0.0f then Assert.Fail() + + // empty double ISeq + let emptyDoubleSeq = ISeq.empty + let resultDouEmp = ISeq.sum emptyDoubleSeq + if resultDouEmp <> 0.0 then Assert.Fail() + + // empty decimal ISeq + let emptyDecimalSeq = ISeq.empty + let resultDecEmp = ISeq.sum emptyDecimalSeq + if resultDecEmp <> 0M then Assert.Fail() + + () + + [] + member this.SumBy() = + + // integer ISeq + let resultInt = ISeq.sumBy int (seq [1..10]|> ISeq.ofSeq) + Assert.AreEqual(55,resultInt) + + // float32 ISeq + let floatSeq = (seq [ 1.2f;3.5f;6.7f ])|> ISeq.ofSeq + let resultFloat = ISeq.sumBy float32 floatSeq + if resultFloat <> 11.4f then Assert.Fail() + + // double ISeq + let doubleSeq = (seq [ 1.0;8.0 ])|> ISeq.ofSeq + let resultDouble = ISeq.sumBy double doubleSeq + if resultDouble <> 9.0 then Assert.Fail() + + // decimal ISeq + let decimalSeq = (seq [ 0M;19M;19.03M ]) |> ISeq.ofSeq + let resultDecimal = ISeq.sumBy decimal decimalSeq + if resultDecimal <> 38.03M then Assert.Fail() + + // empty float32 ISeq + let emptyFloatSeq = ISeq.empty + let resultEptFloat = ISeq.sumBy float32 emptyFloatSeq + if resultEptFloat <> 0.0f then Assert.Fail() + + // empty double ISeq + let emptyDoubleSeq = ISeq.empty + let resultDouEmp = ISeq.sumBy double emptyDoubleSeq + if resultDouEmp <> 0.0 then Assert.Fail() + + // empty decimal ISeq + let emptyDecimalSeq = ISeq.empty + let resultDecEmp = ISeq.sumBy decimal emptyDecimalSeq + if resultDecEmp <> 0M then Assert.Fail() + + () + + [] + member this.Take() = + // integer ISeq + + let resultInt = ISeq.take 3 (seq [1;2;4;5;7]|> ISeq.ofSeq) + + let expectedInt = seq [1;2;4] + VerifySeqsEqual expectedInt resultInt + + // string ISeq + + let resultStr =ISeq.take 2(seq ["str1";"str2";"str3";"str4"]|> ISeq.ofSeq) + + let expectedStr = seq ["str1";"str2"] + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.take 0 ISeq.empty + + VerifySeqsEqual resultEpt ISeq.empty + + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> ISeq.take 1 null |> ignore) + () + + [] + member this.takeWhile() = + // integer ISeq + let funcInt x = (x < 6) + let resultInt = ISeq.takeWhile funcInt (seq [1;2;4;5;6;7]|> ISeq.ofSeq) + + let expectedInt = seq [1;2;4;5] + VerifySeqsEqual expectedInt resultInt + + // string ISeq + let funcStr (x:string) = (x.Length < 4) + let resultStr =ISeq.takeWhile funcStr (seq ["a"; "ab"; "abc"; "abcd"; "abcde"]|> ISeq.ofSeq) + + let expectedStr = seq ["a"; "ab"; "abc"] + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.takeWhile funcInt ISeq.empty + VerifySeqsEqual resultEpt ISeq.empty + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> ISeq.takeWhile funcInt null |> ignore) + () + + [] + member this.ToArray() = + // integer ISeq + let resultInt = ISeq.toArray(seq [1;2;4;5;7]|> ISeq.ofSeq) + + let expectedInt = [|1;2;4;5;7|] + Assert.AreEqual(expectedInt,resultInt) + + // string ISeq + let resultStr =ISeq.toArray (seq ["str1";"str2";"str3"]|> ISeq.ofSeq) + + let expectedStr = [|"str1";"str2";"str3"|] + Assert.AreEqual(expectedStr,resultStr) + + // empty ISeq + let resultEpt = ISeq.toArray ISeq.empty + Assert.AreEqual([||],resultEpt) + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> ISeq.toArray null |> ignore) + () + + [] + member this.ToArrayFromICollection() = + let inputCollection = ResizeArray(seq [1;2;4;5;7]) + let resultInt = ISeq.toArray(inputCollection|> ISeq.ofSeq) + let expectedInt = [|1;2;4;5;7|] + Assert.AreEqual(expectedInt,resultInt) + + [] + member this.ToArrayEmptyInput() = + let resultInt = ISeq.toArray(ISeq.empty) + let expectedInt = Array.empty + Assert.AreEqual(expectedInt,resultInt) + + [] + member this.ToArrayFromArray() = + let resultInt = ISeq.toArray([|1;2;4;5;7|]|> ISeq.ofSeq) + let expectedInt = [|1;2;4;5;7|] + Assert.AreEqual(expectedInt,resultInt) + + [] + member this.ToArrayFromList() = + let resultInt = ISeq.toArray([1;2;4;5;7]|> ISeq.ofSeq) + let expectedInt = [|1;2;4;5;7|] + Assert.AreEqual(expectedInt,resultInt) + + [] + member this.ToList() = + // integer ISeq + let resultInt = Seq.toList (seq [1;2;4;5;7]) + let expectedInt = [1;2;4;5;7] + Assert.AreEqual(expectedInt,resultInt) + + // string ISeq + let resultStr =Seq.toList (seq ["str1";"str2";"str3"]) + let expectedStr = ["str1";"str2";"str3"] + Assert.AreEqual(expectedStr,resultStr) + + // empty ISeq + let resultEpt = Seq.toList ISeq.empty + Assert.AreEqual([],resultEpt) + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> Seq.toList null |> ignore) + () + + [] + member this.Truncate() = + // integer ISeq + let resultInt = ISeq.truncate 3 (seq [1;2;4;5;7]|> ISeq.ofSeq) + let expectedInt = [1;2;4] + VerifySeqsEqual expectedInt resultInt + + // string ISeq + let resultStr =ISeq.truncate 2 (seq ["str1";"str2";"str3"]|> ISeq.ofSeq) + let expectedStr = ["str1";"str2"] + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.truncate 0 ISeq.empty + VerifySeqsEqual ISeq.empty resultEpt + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> ISeq.truncate 1 null |> ignore) + + // negative count + VerifySeqsEqual ISeq.empty <| ISeq.truncate -1 (seq [1;2;4;5;7]|> ISeq.ofSeq) + VerifySeqsEqual ISeq.empty <| ISeq.truncate System.Int32.MinValue (seq [1;2;4;5;7]|> ISeq.ofSeq) + + () + + [] + member this.tryFind() = + // integer ISeq + let resultInt = ISeq.tryFind (fun x -> (x%2=0)) (seq [1;2;4;5;7]|> ISeq.ofSeq) + Assert.AreEqual(Some(2), resultInt) + + // integer ISeq - None + let resultInt = ISeq.tryFind (fun x -> (x%2=0)) (seq [1;3;5;7]|> ISeq.ofSeq) + Assert.AreEqual(None, resultInt) + + // string ISeq + let resultStr = ISeq.tryFind (fun (x:string) -> x.Contains("2")) (seq ["str1";"str2";"str3"]|> ISeq.ofSeq) + Assert.AreEqual(Some("str2"),resultStr) + + // string ISeq - None + let resultStr = ISeq.tryFind (fun (x:string) -> x.Contains("2")) (seq ["str1";"str4";"str3"] |> ISeq.ofSeq) + Assert.AreEqual(None,resultStr) + + + // empty ISeq + let resultEpt = ISeq.tryFind (fun x -> (x%2=0)) ISeq.empty + Assert.AreEqual(None,resultEpt) + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> ISeq.tryFind (fun x -> (x%2=0)) null |> ignore) + () + + [] + member this.TryFindBack() = + // integer ISeq + let resultInt = Seq.tryFindBack (fun x -> (x%2=0)) (seq [1;2;4;5;7]) + Assert.AreEqual(Some 4, resultInt) + + // integer ISeq - None + let resultInt = Seq.tryFindBack (fun x -> (x%2=0)) (seq [1;3;5;7]) + Assert.AreEqual(None, resultInt) + + // string ISeq + let resultStr = Seq.tryFindBack (fun (x:string) -> x.Contains("2")) (seq ["str1";"str2";"str2x";"str3"]) + Assert.AreEqual(Some "str2x", resultStr) + + // string ISeq - None + let resultStr = Seq.tryFindBack (fun (x:string) -> x.Contains("2")) (seq ["str1";"str4";"str3"]) + Assert.AreEqual(None, resultStr) + + // empty ISeq + let resultEpt = Seq.tryFindBack (fun x -> (x%2=0)) ISeq.empty + Assert.AreEqual(None, resultEpt) + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> Seq.tryFindBack (fun x -> (x%2=0)) null |> ignore) + () + + [] + member this.TryFindIndex() = + + // integer ISeq + let resultInt = ISeq.tryFindIndex (fun x -> (x % 5 = 0)) ([8; 9; 10] |> ISeq.ofSeq) + Assert.AreEqual(Some(2), resultInt) + + // integer ISeq - None + let resultInt = ISeq.tryFindIndex (fun x -> (x % 5 = 0)) ([9;3;11]|> ISeq.ofSeq) + Assert.AreEqual(None, resultInt) + + // string ISeq + let resultStr = ISeq.tryFindIndex (fun (x:string) -> x.Contains("2")) (["str1"; "str2"; "str3"]|> ISeq.ofSeq) + Assert.AreEqual(Some(1),resultStr) + + // string ISeq - None + let resultStr = ISeq.tryFindIndex (fun (x:string) -> x.Contains("2")) (["str1"; "str4"; "str3"]|> ISeq.ofSeq) + Assert.AreEqual(None,resultStr) + + + // empty ISeq + let resultEpt = ISeq.tryFindIndex (fun x -> (x%2=0)) ISeq.empty + Assert.AreEqual(None, resultEpt) + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> ISeq.tryFindIndex (fun x -> (x % 2 = 0)) null |> ignore) + () + + [] + member this.TryFindIndexBack() = + + // integer ISeq + let resultInt = Seq.tryFindIndexBack (fun x -> (x % 5 = 0)) [5; 9; 10; 12] + Assert.AreEqual(Some(2), resultInt) + + // integer ISeq - None + let resultInt = Seq.tryFindIndexBack (fun x -> (x % 5 = 0)) [9;3;11] + Assert.AreEqual(None, resultInt) + + // string ISeq + let resultStr = Seq.tryFindIndexBack (fun (x:string) -> x.Contains("2")) ["str1"; "str2"; "str2x"; "str3"] + Assert.AreEqual(Some(2), resultStr) + + // string ISeq - None + let resultStr = Seq.tryFindIndexBack (fun (x:string) -> x.Contains("2")) ["str1"; "str4"; "str3"] + Assert.AreEqual(None, resultStr) + + // empty ISeq + let resultEpt = Seq.tryFindIndexBack (fun x -> (x%2=0)) ISeq.empty + Assert.AreEqual(None, resultEpt) + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> Seq.tryFindIndexBack (fun x -> (x % 2 = 0)) null |> ignore) + () + + [] + member this.Unfold() = + // integer ISeq + + let resultInt = ISeq.unfold (fun x -> if x = 1 then Some(7,2) else None) 1 + + VerifySeqsEqual (seq [7]) resultInt + + // string ISeq + let resultStr =ISeq.unfold (fun (x:string) -> if x.Contains("unfold") then Some("a","b") else None) "unfold" + VerifySeqsEqual (seq ["a"]) resultStr + () + + + [] + member this.Windowed() = + + let testWindowed config = + try + config.InputSeq + |> ISeq.ofSeq + |> ISeq.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 = seq [1..10] + WindowSize = 1 + ExpectedSeq = seq { for i in 1..10 do yield [| i |] } + Exception = None + } |> testWindowed + { + InputSeq = seq [1..10] + WindowSize = 5 + ExpectedSeq = seq { for i in 1..6 do yield [| i; i+1; i+2; i+3; i+4 |] } + Exception = None + } |> testWindowed + { + InputSeq = seq [1..10] + WindowSize = 10 + ExpectedSeq = seq { yield [| 1 .. 10 |] } + Exception = None + } |> testWindowed + { + InputSeq = seq [1..10] + WindowSize = 25 + ExpectedSeq = ISeq.empty + Exception = None + } |> testWindowed + { + InputSeq = seq ["str1";"str2";"str3";"str4"] + WindowSize = 2 + ExpectedSeq = seq [ [|"str1";"str2"|];[|"str2";"str3"|];[|"str3";"str4"|]] + Exception = None + } |> testWindowed + { + InputSeq = ISeq.empty + WindowSize = 2 + ExpectedSeq = ISeq.empty + Exception = None + } |> testWindowed + { + InputSeq = null + WindowSize = 2 + ExpectedSeq = ISeq.empty + Exception = Some typeof + } |> testWindowed + { + InputSeq = seq [1..10] + WindowSize = 0 + ExpectedSeq = ISeq.empty + Exception = Some typeof + } |> testWindowed + + () + + [] + member this.Zip() = + + // integer ISeq + let resultInt = ISeq.zip (seq [1..7] |> ISeq.ofSeq) (seq [11..17] |> ISeq.ofSeq) + let expectedInt = + seq { for i in 1..7 do + yield i, i+10 } + VerifySeqsEqual expectedInt resultInt + + // string ISeq + let resultStr =ISeq.zip (seq ["str3";"str4"] |> ISeq.ofSeq) (seq ["str1";"str2"] |> ISeq.ofSeq) + let expectedStr = seq ["str3","str1";"str4","str2"] |> ISeq.ofSeq + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = ISeq.zip ISeq.empty ISeq.empty + VerifySeqsEqual ISeq.empty resultEpt + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> ISeq.zip null null |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.zip null (seq [1..7]) |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.zip (seq [1..7]) null |> ignore) + () + + [] + member this.Zip3() = + // integer ISeq + let resultInt = Seq.zip3 (seq [1..7]) (seq [11..17]) (seq [21..27]) + let expectedInt = + seq { for i in 1..7 do + yield i, (i + 10), (i + 20) } + VerifySeqsEqual expectedInt resultInt + + // string ISeq + let resultStr =Seq.zip3 (seq ["str1";"str2"]) (seq ["str11";"str12"]) (seq ["str21";"str22"]) + let expectedStr = seq ["str1","str11","str21";"str2","str12","str22" ] + VerifySeqsEqual expectedStr resultStr + + // empty ISeq + let resultEpt = Seq.zip3 ISeq.empty ISeq.empty ISeq.empty + VerifySeqsEqual ISeq.empty resultEpt + + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> Seq.zip3 null null null |> ignore) + //CheckThrowsArgumentNullException(fun() -> Seq.zip3 null (seq [1..7]) (seq [1..7]) |> ignore) + //CheckThrowsArgumentNullException(fun() -> Seq.zip3 (seq [1..7]) null (seq [1..7]) |> ignore) + //CheckThrowsArgumentNullException(fun() -> Seq.zip3 (seq [1..7]) (seq [1..7]) null |> ignore) + () + + [] + member this.tryPick() = + // integer ISeq + let resultInt = ISeq.tryPick (fun x-> if x = 1 then Some("got") else None) (seq [1..5]|> ISeq.ofSeq) + + Assert.AreEqual(Some("got"),resultInt) + + // string ISeq + let resultStr = ISeq.tryPick (fun x-> if x = "Are" then Some("got") else None) (seq ["Lists"; "Are"] |> ISeq.ofSeq) + Assert.AreEqual(Some("got"),resultStr) + + // empty ISeq + let resultEpt = ISeq.tryPick (fun x-> if x = 1 then Some("got") else None) ISeq.empty + Assert.IsNull(resultEpt) + + //// null ISeq + //let nullSeq : seq<'a> = null + //let funcNull x = Some(1) + + //CheckThrowsArgumentNullException(fun () -> ISeq.tryPick funcNull nullSeq |> ignore) + + () + + [] + member this.tryItem() = + // integer ISeq + let resultInt = ISeq.tryItem 3 ({ 10..20 }|> ISeq.ofSeq) + Assert.AreEqual(Some(13), resultInt) + + // string ISeq + let resultStr = ISeq.tryItem 2 (seq ["Lists"; "Are"; "Cool"; "List" ]|> ISeq.ofSeq) + Assert.AreEqual(Some("Cool"), resultStr) + + // empty ISeq + let resultEmpty = ISeq.tryItem 0 ISeq.empty + Assert.AreEqual(None, resultEmpty) + + //// null ISeq + //let nullSeq:seq<'a> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.tryItem 3 nullSeq |> ignore) + + // Negative index + let resultNegativeIndex = ISeq.tryItem -1 ({ 10..20 }|> ISeq.ofSeq) + Assert.AreEqual(None, resultNegativeIndex) + + // Index greater than length + let resultIndexGreater = ISeq.tryItem 31 ({ 10..20 }|> ISeq.ofSeq) + Assert.AreEqual(None, resultIndexGreater) diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqProperties.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqProperties.fs new file mode 100644 index 0000000000..d37172bf0b --- /dev/null +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqProperties.fs @@ -0,0 +1,39 @@ +// 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.ISeqProperties + +open System +open System.Collections.Generic +open NUnit.Framework +open FsCheck +open Utils + +let sortByStable<'a when 'a : comparison> (xs : 'a []) = + let indexed = xs|> ISeq.ofSeq |> ISeq.indexed + let sorted = indexed |> ISeq.sortBy snd + isStable sorted + +[] +let ``ISeq.sortBy is stable`` () = + Check.QuickThrowOnFailure sortByStable + Check.QuickThrowOnFailure sortByStable + +let sortWithStable<'a when 'a : comparison> (xs : 'a []) = + let indexed = xs |> ISeq.ofSeq |> ISeq.indexed |> Seq.toList + let sorted = indexed |> ISeq.ofSeq |> ISeq.sortWith (fun x y -> compare (snd x) (snd y)) + isStable sorted + +[] +let ``ISeq.sortWithStable is stable`` () = + Check.QuickThrowOnFailure sortWithStable + Check.QuickThrowOnFailure sortWithStable + +let distinctByStable<'a when 'a : comparison> (xs : 'a []) = + let indexed = xs|> ISeq.ofSeq |> ISeq.indexed + let sorted = indexed |> ISeq.distinctBy snd + isStable sorted + +[] +let ``ISeq.distinctBy is stable`` () = + Check.QuickThrowOnFailure distinctByStable + Check.QuickThrowOnFailure distinctByStable From 96847b2a2b9e5b9950cb5a2405050a9d86600679 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 17 Mar 2017 18:25:40 +1100 Subject: [PATCH 04/83] Fix ordering in append --- src/fsharp/FSharp.Core/iseq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index d99e39639c..b751745d80 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -356,7 +356,7 @@ namespace Microsoft.FSharp.Collections abstract member Append : (ISeq<'T>) -> ISeq<'T> - default this.Append source = Upcast.seq (AppendEnumerable [this; source]) + default this.Append source = Upcast.seq (AppendEnumerable [source; this]) interface IEnumerable with member this.GetEnumerator () : IEnumerator = From 0429f21f6c59261631b19fb37ce377fa38b50808 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 17 Mar 2017 18:33:12 +1100 Subject: [PATCH 05/83] mod test until cache is implemented --- .../FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs index 0286684808..48aa60e2af 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs @@ -56,13 +56,12 @@ type ISeqModule() = let cachedSeq = ISeq.initInfinite (fun i -> evaluatedItems := i :: !evaluatedItems; i) |> Seq.cache - |> ISeq.ofSeq // Verify no items have been evaluated from the ISeq yet Assert.AreEqual(List.length !evaluatedItems, 0) // Force evaluation of 10 elements - ISeq.take 10 cachedSeq + Seq.take 10 cachedSeq |> Seq.toList |> ignore @@ -70,7 +69,7 @@ type ISeqModule() = Assert.AreEqual(List.length !evaluatedItems, 10) // Force evaluation of 10 elements - ISeq.take 10 cachedSeq + Seq.take 10 cachedSeq |> Seq.toList |> ignore @@ -82,7 +81,7 @@ type ISeqModule() = (box cachedSeq :?> System.IDisposable) .Dispose() // Force evaluation of 10 elements - ISeq.take 10 cachedSeq + Seq.take 10 cachedSeq |> Seq.toList |> ignore From b8978889ad2d85ac28246996e1d6e2031868191d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 17 Mar 2017 19:03:31 +1100 Subject: [PATCH 06/83] Fix indexing for iteri2 --- src/fsharp/FSharp.Core/iseq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index b751745d80..2fa507ff3b 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -970,7 +970,7 @@ namespace Microsoft.FSharp.Collections [] let inline iteri2 (f:int->'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = source1.Fold (fun pipeIdx -> - upcast { new FolderWithPostProcessing<'T,unit,Values>>((),Values<_,_>(-1,source2.GetEnumerator())) with + upcast { new FolderWithPostProcessing<'T,unit,Values>>((),Values<_,_>(0,source2.GetEnumerator())) with override this.ProcessNext value = if this.State._2.MoveNext() then f this.State._1 value this.State._2.Current From eb9b0c5a3bedd03bf37e672a7df428efb12c4ce8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 17 Mar 2017 19:25:05 +1100 Subject: [PATCH 07/83] fix scan to include initialState --- src/fsharp/FSharp.Core/iseq.fs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 2fa507ff3b..853eb7f17b 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1306,14 +1306,21 @@ namespace Microsoft.FSharp.Collections invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString override this.OnDispose () = () }) + [] + let concat (sources:ISeq<#ISeq<'T>>) : ISeq<'T> = + Upcast.seq (Enumerable.ConcatEnumerable sources) + [] let inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = - source.PushTransform { new TransformFactory<'T,'State>() with - override __.Compose _ _ next = - upcast { new Transform<'T,'V,'State>(next, initialState) with - override this.ProcessNext (input:'T) : bool = - this.State <- folder this.State input - TailCall.avoid (next.ProcessNext this.State) } } + let head = ofSeq [| initialState |] + let tail = + source.PushTransform { new TransformFactory<'T,'State>() with + override __.Compose _ _ next = + upcast { new Transform<'T,'V,'State>(next, initialState) with + override this.ProcessNext (input:'T) : bool = + this.State <- folder this.State input + TailCall.avoid (next.ProcessNext this.State) } } + concat (ofSeq [| head ; tail |]) [] let skip (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = @@ -1546,10 +1553,6 @@ namespace Microsoft.FSharp.Collections Array.Copy (circularBuffer, 0, window, windowSize - idx, idx) TailCall.avoid (next.ProcessNext window) }} - [] - let concat (sources:ISeq<#ISeq<'T>>) : ISeq<'T> = - Upcast.seq (Enumerable.ConcatEnumerable sources) - [] let append (source1:ISeq<'T>) (source2: ISeq<'T>) : ISeq<'T> = match source1 with From 0bb5ab66d173f00ed740ea8590557135fa52dab9 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 17 Mar 2017 19:47:13 +1100 Subject: [PATCH 08/83] fixed tryItem when index > size of input seq --- src/fsharp/FSharp.Core/iseq.fs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 853eb7f17b..32e03c7324 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1461,7 +1461,29 @@ namespace Microsoft.FSharp.Collections [] let tryItem index (source:ISeq<'T>) = if index < 0 then None else - source |> skip index |> tryHead + source.PushTransform { new TransformFactory<'T,'T>() with + override __.Compose _ _ next = + let mutable this = Unchecked.defaultof> + let skipper = + { new Transform<'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 + upcast this } + |> tryHead [] let inline tryPick f (source:ISeq<'T>) = From 00679b599c3a0bd6bfddb6c2a64ca1ed90d33947 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 18 Mar 2017 15:24:25 +1100 Subject: [PATCH 09/83] Stubbed in remaining functions Took implementations from seq.fs --- .../SurfaceArea.coreclr.fs | 23 ++ .../SurfaceArea.net40.fs | 23 ++ src/fsharp/FSharp.Core/iseq.fs | 233 ++++++++++++++++++ src/fsharp/FSharp.Core/iseq.fsi | 69 ++++++ .../fsharpqa/Source/Misc/LongSourceFile01.fs | 23 ++ 5 files changed, 371 insertions(+) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs index 64bb5ea2ef..badb570823 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs @@ -410,8 +410,14 @@ Microsoft.FSharp.Collections.ISeqModule: Boolean Exists2[T,TResult](Microsoft.FS Microsoft.FSharp.Collections.ISeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], ISeq`1, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean IsEmpty[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 AllPairs[T1,T2](ISeq`1, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Append[T](ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Cache[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Cast[T](System.Collections.IEnumerable) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Choose[a,b](Microsoft.FSharp.Core.FSharpFunc`2[a,Microsoft.FSharp.Core.FSharpOption`1[b]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 ChunkBySize[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Collect[T,TCollection,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TCollection], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Concat[TCollection,T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) @@ -437,36 +443,52 @@ Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfResizeArrayUnchecked[T](System Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfSeq[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Pairwise[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Permute[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Replicate[T](Int32, T) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Reverse[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], ISeq`1, TState) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Scan[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Singleton[T](T) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SkipWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Skip[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortByDescending[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortDescending[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Sort[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SplitInto[T](Int32, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Tail[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Take[T](Int32, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Truncate[T](Int32, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Unfold[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Windowed[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Zip3[T1,T2,T3](ISeq`1, ISeq`1, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Zip[T1,T2](ISeq`1, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule: Int32 Length[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.FSharpList`1[T] ToList[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.ISeqModule+Core +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[TResult] TryPick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFind[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryHead[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryItem[T](Int32, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[TResult],TState] MapFoldBack[T,TState,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,System.Tuple`2[TResult,TState]]], ISeq`1, TState) +Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`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, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule: T Average[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T ExactlyOne[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T FindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Find[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T Head[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Item[T](Int32, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T Last[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T Max[T](ISeq`1) @@ -476,6 +498,7 @@ Microsoft.FSharp.Collections.ISeqModule: T ReduceBack[T](Microsoft.FSharp.Core.F Microsoft.FSharp.Collections.ISeqModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T Sum[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: TResult Pick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: 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, ISeq`1, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: TState FoldBack2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], ISeq`1, ISeq`1, TState) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs index dd26877111..116f99f99f 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs @@ -397,8 +397,14 @@ Microsoft.FSharp.Collections.ISeqModule: Boolean Exists2[T,TResult](Microsoft.FS Microsoft.FSharp.Collections.ISeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], ISeq`1, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean IsEmpty[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 AllPairs[T1,T2](ISeq`1, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Append[T](ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Cache[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Cast[T](System.Collections.IEnumerable) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Choose[a,b](Microsoft.FSharp.Core.FSharpFunc`2[a,Microsoft.FSharp.Core.FSharpOption`1[b]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 ChunkBySize[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Collect[T,TCollection,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TCollection], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Concat[TCollection,T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) @@ -424,36 +430,52 @@ Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfResizeArrayUnchecked[T](System Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfSeq[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Pairwise[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Permute[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Replicate[T](Int32, T) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Reverse[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], ISeq`1, TState) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Scan[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Singleton[T](T) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SkipWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Skip[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortByDescending[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortDescending[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Sort[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SplitInto[T](Int32, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Tail[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Take[T](Int32, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Truncate[T](Int32, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Unfold[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Windowed[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Zip3[T1,T2,T3](ISeq`1, ISeq`1, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Zip[T1,T2](ISeq`1, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule: Int32 Length[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.FSharpList`1[T] ToList[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.ISeqModule+Core +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[TResult] TryPick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFind[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryHead[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryItem[T](Int32, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[TResult],TState] MapFoldBack[T,TState,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,System.Tuple`2[TResult,TState]]], ISeq`1, TState) +Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`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, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule: T Average[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T ExactlyOne[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T FindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Find[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T Head[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Item[T](Int32, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T Last[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T Max[T](ISeq`1) @@ -463,6 +485,7 @@ Microsoft.FSharp.Collections.ISeqModule: T ReduceBack[T](Microsoft.FSharp.Core.F Microsoft.FSharp.Collections.ISeqModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T Sum[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: TResult Pick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: 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, ISeq`1, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: TState FoldBack2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], ISeq`1, ISeq`1, TState) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 32e03c7324..9d446d2080 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1748,3 +1748,236 @@ namespace Microsoft.FSharp.Collections match arr.Length with | 0 -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString | len -> foldArraySubRight f arr 0 (len - 2) arr.[len - 1] + + [] + 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() + + [] + let cache (source:ISeq<'T>) : ISeq<'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) |> ofSeq) + + [] + let collect f sources = map f sources |> concat + + [] + let allPairs (source1:ISeq<'T1>) (source2:ISeq<'T2>) : ISeq<'T1 * 'T2> = + checkNonNull "source1" source1 + checkNonNull "source2" source2 + let cached = cache source2 + source1 |> collect (fun x -> cached |> map (fun y -> x,y)) + + [] + let toList (source : ISeq<'T>) = + checkNonNull "source" source + Microsoft.FSharp.Primitives.Basics.List.ofSeq source + + [] + let replicate count x = + System.Linq.Enumerable.Repeat(x,count) |> ofSeq + + [] + let isEmpty (source : ISeq<'T>) = + checkNonNull "source" source + use ie = source.GetEnumerator() + not (ie.MoveNext()) + + [] + let cast (source: IEnumerable) : ISeq<'T> = + checkNonNull "source" source + mkSeq (fun () -> IEnumerator.cast (source.GetEnumerator())) |> ofSeq + + [] + let chunkBySize chunkSize (source : ISeq<'T>) : ISeq<'T[]> = + 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() } |> ofSeq + raise (NotImplementedException ("TBD")) + + let mkDelayedSeq (f: unit -> IEnumerable<'T>) = mkSeq (fun () -> f().GetEnumerator()) |> ofSeq + + [] + let splitInto count (source:ISeq<'T>) : ISeq<'T[]> = + 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<_>) + + let inline indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) + + [] + let find f source = + checkNonNull "source" source + match tryFind f source with + | None -> indexNotFound() + | Some x -> x + + [] + let findIndex p (source:ISeq<_>) = + checkNonNull "source" source + use ie = source.GetEnumerator() + let rec loop i = + if ie.MoveNext() then + if p ie.Current then + i + else loop (i+1) + else + indexNotFound() + loop 0 + + [] + let findBack f source = + checkNonNull "source" source + source |> toArray |> Array.findBack f + + [] + let findIndexBack f source = + checkNonNull "source" source + source |> toArray |> Array.findIndexBack f + + [] + let pick f source = + checkNonNull "source" source + match tryPick f source with + | None -> indexNotFound() + | Some x -> x + + [] + [] + let readonly (source:seq<_>) = + checkNonNull "source" source + mkSeq (fun () -> source.GetEnumerator()) |> ofSeq + + [] + let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = + checkNonNull "source" source + let arr,state = source |> toArray |> Array.mapFold f acc + readonly arr, state + + [] + let mapFoldBack<'T,'State,'Result> (f: 'T -> 'State -> 'Result * 'State) source acc = + checkNonNull "source" source + let array = source |> toArray + let arr,state = Array.mapFoldBack f array acc + readonly arr, state + + 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 + + [] + let item i (source : ISeq<'T>) = + checkNonNull "source" source + if i < 0 then invalidArgInputMustBeNonNegative "index" i + use e = source.GetEnumerator() + nth i e + + [] + let singleton x = mkSeq (fun () -> IEnumerator.Singleton x) |> ofSeq + + [] + let inline sortDescending source = + checkNonNull "source" source + let inline compareDescending a b = compare b a + sortWith compareDescending source + + [] + let inline sortByDescending keyf source = + checkNonNull "source" source + let inline compareDescending a b = compare (keyf b) (keyf a) + sortWith compareDescending source + + [] + let tryFindBack f (source : ISeq<'T>) = + checkNonNull "source" source + source |> toArray |> Array.tryFindBack f + + [] + let tryFindIndexBack f (source : ISeq<'T>) = + checkNonNull "source" source + source |> toArray |> Array.tryFindIndexBack f + + [] + 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) diff --git a/src/fsharp/FSharp.Core/iseq.fsi b/src/fsharp/FSharp.Core/iseq.fsi index 8f030782f1..7d3534ae76 100644 --- a/src/fsharp/FSharp.Core/iseq.fsi +++ b/src/fsharp/FSharp.Core/iseq.fsi @@ -360,3 +360,72 @@ namespace Microsoft.FSharp.Collections module internal CountBy = val inline byVal : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * int> when 'Key : equality val inline byRef : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * int> when 'Key : equality + + [] + val cache: source:ISeq<'T> -> ISeq<'T> + + [] + val collect: mapping:('T -> 'Collection) -> source:ISeq<'T> -> ISeq<'U> when 'Collection :> ISeq<'U> + + [] + val allPairs: source1:ISeq<'T1> -> source2:ISeq<'T2> -> ISeq<'T1 * 'T2> + + [] + val toList: source:ISeq<'T> -> 'T list + + [] + val replicate: count:int -> initial:'T -> ISeq<'T> + + [] + val isEmpty: source:ISeq<'T> -> bool + + [] + val cast: source:IEnumerable -> ISeq<'T> + + [] + val chunkBySize: chunkSize:int -> source:ISeq<'T> -> ISeq<'T[]> + + [] + val splitInto: count:int -> source:ISeq<'T> -> ISeq<'T[]> + + [] + val find: predicate:('T -> bool) -> source:ISeq<'T> -> 'T + + [] + val findBack: predicate:('T -> bool) -> source:ISeq<'T> -> 'T + + [] + val findIndex: predicate:('T -> bool) -> source:ISeq<'T> -> int + + [] + val findIndexBack: predicate:('T -> bool) -> source:ISeq<'T> -> int + + [] + val pick: chooser:('T -> 'U option) -> source:ISeq<'T> -> 'U + + [] + val mapFold<'T,'State,'Result> : mapping:('State -> 'T -> 'Result * 'State) -> state:'State -> source:ISeq<'T> -> ISeq<'Result> * 'State + + [] + val mapFoldBack<'T,'State,'Result> : mapping:('T -> 'State -> 'Result * 'State) -> source:ISeq<'T> -> state:'State -> ISeq<'Result> * 'State + + [] + val item: index:int -> source:ISeq<'T> -> 'T + + [] + val singleton: value:'T -> ISeq<'T> + + [] + val inline sortDescending : source:ISeq<'T> -> ISeq<'T> when 'T : comparison + + [] + val inline sortByDescending : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'T> when 'Key : comparison + + [] + val tryFindBack: predicate:('T -> bool) -> source:ISeq<'T> -> 'T option + + [] + val tryFindIndexBack : predicate:('T -> bool) -> source:ISeq<'T> -> int option + + [] + val zip3: source1:ISeq<'T1> -> source2:ISeq<'T2> -> source3:ISeq<'T3> -> ISeq<'T1 * 'T2 * 'T3> diff --git a/tests/fsharpqa/Source/Misc/LongSourceFile01.fs b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs index 5cffea8000..c144938159 100644 --- a/tests/fsharpqa/Source/Misc/LongSourceFile01.fs +++ b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs @@ -364,8 +364,14 @@ Microsoft.FSharp.Collections.ISeqModule: Boolean Exists2[T,TResult](Microsoft.FS Microsoft.FSharp.Collections.ISeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], ISeq`1, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean IsEmpty[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 AllPairs[T1,T2](ISeq`1, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Append[T](ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Cache[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Cast[T](System.Collections.IEnumerable) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Choose[a,b](Microsoft.FSharp.Core.FSharpFunc`2[a,Microsoft.FSharp.Core.FSharpOption`1[b]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 ChunkBySize[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Collect[T,TCollection,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TCollection], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Concat[TCollection,T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) @@ -391,36 +397,52 @@ Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfResizeArrayUnchecked[T](System Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfSeq[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Pairwise[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Permute[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Replicate[T](Int32, T) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Reverse[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], ISeq`1, TState) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Scan[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Singleton[T](T) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SkipWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Skip[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortByDescending[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortDescending[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Sort[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SplitInto[T](Int32, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Tail[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Take[T](Int32, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Truncate[T](Int32, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Unfold[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Windowed[T](Int32, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Zip3[T1,T2,T3](ISeq`1, ISeq`1, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Zip[T1,T2](ISeq`1, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule: Int32 Length[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.FSharpList`1[T] ToList[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.ISeqModule+Core +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[TResult] TryPick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFind[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryHead[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryItem[T](Int32, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[TResult],TState] MapFoldBack[T,TState,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,System.Tuple`2[TResult,TState]]], ISeq`1, TState) +Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`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, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule: T Average[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T ExactlyOne[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T FindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Find[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T Head[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Item[T](Int32, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T Last[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T Max[T](ISeq`1) @@ -430,6 +452,7 @@ Microsoft.FSharp.Collections.ISeqModule: T ReduceBack[T](Microsoft.FSharp.Core.F Microsoft.FSharp.Collections.ISeqModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: T Sum[T](ISeq`1) Microsoft.FSharp.Collections.ISeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: TResult Pick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) Microsoft.FSharp.Collections.ISeqModule: 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, ISeq`1, ISeq`1) Microsoft.FSharp.Collections.ISeqModule: TState FoldBack2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], ISeq`1, ISeq`1, TState) From 39ffb7b42f867606babc366c2e9c5448c30efd98 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 18 Mar 2017 16:04:13 +1100 Subject: [PATCH 10/83] Expanded tests to cover previous missing ISeq functions --- .../ISeqModule.fs | 548 ++++++------- .../ISeqModule2.fs | 770 +++++++++--------- 2 files changed, 661 insertions(+), 657 deletions(-) diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs index 48aa60e2af..873fd4274e 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs @@ -8,7 +8,7 @@ open NUnit.Framework open FSharp.Core.Unittests.LibraryTestFx // Various tests for the: -// Microsoft.FSharp.Collections.seq type +// Microsoft.FSharp.Collections.iseq type (* [Test Strategy] @@ -19,34 +19,37 @@ Make sure each method works on: * Null ISeq (null) *) +type iseq<'a> = ISeq.Core.ISeq<'a> + [] type ISeqModule() = + let iseq (x:seq<_>) = x |> ISeq.ofSeq [] member this.AllPairs() = // integer ISeq - let resultInt = Seq.allPairs (seq [1..7]) (seq [11..17]) + let resultInt = ISeq.allPairs (iseq [1..7]) (iseq [11..17]) let expectedInt = - seq { for i in 1..7 do - for j in 11..17 do - yield i, j } + iseq <| seq { for i in 1..7 do + for j in 11..17 do + yield i, j } VerifySeqsEqual expectedInt resultInt // string ISeq - let resultStr = Seq.allPairs (seq ["str3";"str4"]) (seq ["str1";"str2"]) - let expectedStr = seq ["str3","str1";"str3","str2";"str4","str1";"str4","str2"] + let resultStr = ISeq.allPairs (iseq ["str3";"str4"]) (iseq ["str1";"str2"]) + let expectedStr = iseq ["str3","str1";"str3","str2";"str4","str1";"str4","str2"] VerifySeqsEqual expectedStr resultStr // empty ISeq - VerifySeqsEqual ISeq.empty <| Seq.allPairs ISeq.empty ISeq.empty - VerifySeqsEqual ISeq.empty <| Seq.allPairs { 1..7 } ISeq.empty - VerifySeqsEqual ISeq.empty <| Seq.allPairs ISeq.empty { 1..7 } + VerifySeqsEqual ISeq.empty <| ISeq.allPairs ISeq.empty ISeq.empty + VerifySeqsEqual ISeq.empty <| ISeq.allPairs (iseq { 1..7 }) ISeq.empty + VerifySeqsEqual ISeq.empty <| ISeq.allPairs ISeq.empty (iseq { 1..7 }) - // null ISeq - CheckThrowsArgumentNullException(fun() -> Seq.allPairs null null |> ignore) - CheckThrowsArgumentNullException(fun() -> Seq.allPairs null (seq [1..7]) |> ignore) - CheckThrowsArgumentNullException(fun() -> Seq.allPairs (seq [1..7]) null |> ignore) + //// null ISeq + //CheckThrowsArgumentNullException(fun() -> ISeq.allPairs null null |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.allPairs null (iseq [1..7]) |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.allPairs (iseq [1..7]) null |> ignore) () [] @@ -55,22 +58,22 @@ type ISeqModule() = let evaluatedItems : int list ref = ref [] let cachedSeq = ISeq.initInfinite (fun i -> evaluatedItems := i :: !evaluatedItems; i) - |> Seq.cache + |> ISeq.cache // Verify no items have been evaluated from the ISeq yet Assert.AreEqual(List.length !evaluatedItems, 0) // Force evaluation of 10 elements - Seq.take 10 cachedSeq - |> Seq.toList + ISeq.take 10 cachedSeq + |> ISeq.toList |> ignore // verify ref clear switch length Assert.AreEqual(List.length !evaluatedItems, 10) // Force evaluation of 10 elements - Seq.take 10 cachedSeq - |> Seq.toList + ISeq.take 10 cachedSeq + |> ISeq.toList |> ignore // Verify ref clear switch length (should be cached) @@ -81,8 +84,8 @@ type ISeqModule() = (box cachedSeq :?> System.IDisposable) .Dispose() // Force evaluation of 10 elements - Seq.take 10 cachedSeq - |> Seq.toList + ISeq.take 10 cachedSeq + |> ISeq.toList |> ignore // Verify length of evaluatedItemList is 20 @@ -101,33 +104,34 @@ type ISeqModule() = VerifySeqsEqual expectResultEmpty appendEmptySeq // Integer ISeq - let integerSeq1 = seq [0..4] |> ISeq.ofSeq - let integerSeq2 = seq [5..9] |> ISeq.ofSeq + let integerSeq1:iseq = iseq [0..4] + let integerSeq2:iseq = iseq [5..9] let appendIntergerSeq = ISeq.append integerSeq1 integerSeq2 - let expectResultInteger = seq { for i in 0..9 -> i} + let expectResultInteger = iseq <| seq { for i in 0..9 -> i} VerifySeqsEqual expectResultInteger appendIntergerSeq // String ISeq - let stringSeq1 = seq ["1";"2"] |> ISeq.ofSeq - let stringSeq2 = seq ["3";"4"] |> ISeq.ofSeq + let stringSeq1:iseq = iseq ["1";"2"] + let stringSeq2:iseq = iseq ["3";"4"] let appendStringSeq = ISeq.append stringSeq1 stringSeq2 - let expectedResultString = seq ["1";"2";"3";"4"] + let expectedResultString = iseq ["1";"2";"3";"4"] VerifySeqsEqual expectedResultString appendStringSeq // null ISeq - let nullSeq1 = seq [null;null] |> ISeq.ofSeq - let nullSeq2 = seq [null;null] |> ISeq.ofSeq + let nullSeq1 = iseq [null;null] + + let nullSeq2 =iseq [null;null] let appendNullSeq = ISeq.append nullSeq1 nullSeq2 - let expectedResultNull = seq [ null;null;null;null] + let expectedResultNull = iseq [ null;null;null;null] VerifySeqsEqual expectedResultNull appendNullSeq @@ -136,45 +140,45 @@ type ISeqModule() = [] member this.replicate() = // replicate should create multiple copies of the given value - Assert.IsTrue(Seq.isEmpty <| Seq.replicate 0 null) - Assert.IsTrue(Seq.isEmpty <| Seq.replicate 0 1) - Assert.AreEqual(null, ISeq.head <| (Seq.replicate 1 null |> ISeq.ofSeq)) - Assert.AreEqual(["1";"1"],Seq.replicate 2 "1" |> Seq.toList) + Assert.IsTrue(ISeq.isEmpty <| ISeq.replicate 0 null) + Assert.IsTrue(ISeq.isEmpty <| ISeq.replicate 0 1) + Assert.AreEqual(null, ISeq.head <| ISeq.replicate 1 null) + Assert.AreEqual(["1";"1"],ISeq.replicate 2 "1" |> ISeq.toList) - CheckThrowsArgumentException (fun () -> Seq.replicate -1 null |> ignore) + CheckThrowsArgumentException (fun () -> ISeq.replicate -1 null |> ignore) [] member this.Average() = // empty ISeq - let emptySeq = ISeq.empty + let emptySeq:iseq = ISeq.empty CheckThrowsArgumentException (fun () -> ISeq.average emptySeq |> ignore) // double ISeq - let doubleSeq = seq [1.0;2.2;2.5;4.3] |> ISeq.ofSeq + let doubleSeq:iseq = iseq [1.0;2.2;2.5;4.3] let averageDouble = ISeq.average doubleSeq Assert.IsFalse( averageDouble <> 2.5) // float32 ISeq - let floatSeq = seq [ 2.0f;4.4f;5.0f;8.6f] |> ISeq.ofSeq + let floatSeq:iseq = iseq [ 2.0f;4.4f;5.0f;8.6f] let averageFloat = ISeq.average floatSeq Assert.IsFalse( averageFloat <> 5.0f) // decimal ISeq - let decimalSeq = seq [ 0M;19M;19.03M] |> ISeq.ofSeq + let decimalSeq:iseq = iseq [ 0M;19M;19.03M] let averageDecimal = ISeq.average decimalSeq Assert.IsFalse( averageDecimal <> 12.676666666666666666666666667M ) - // null ISeq - //let nullSeq : ISeq.Core.ISeq = null + //// null ISeq + //let nullSeq:iseq = null //CheckThrowsArgumentNullException (fun () -> ISeq.average nullSeq |> ignore) () @@ -183,33 +187,33 @@ type ISeqModule() = [] member this.AverageBy() = // empty ISeq - let emptySeq = ISeq.empty + let emptySeq:iseq = ISeq.empty CheckThrowsArgumentException (fun () -> ISeq.averageBy (fun x -> x+1.0) emptySeq |> ignore) // double ISeq - let doubleSeq = seq [1.0;2.2;2.5;4.3] |> ISeq.ofSeq + let doubleSeq:iseq = iseq [1.0;2.2;2.5;4.3] let averageDouble = ISeq.averageBy (fun x -> x-2.0) doubleSeq Assert.IsFalse( averageDouble <> 0.5 ) // float32 ISeq - let floatSeq = seq [ 2.0f;4.4f;5.0f;8.6f] |> ISeq.ofSeq + let floatSeq:iseq = iseq [ 2.0f;4.4f;5.0f;8.6f] let averageFloat = ISeq.averageBy (fun x -> x*3.3f) floatSeq Assert.IsFalse( averageFloat <> 16.5f ) // decimal ISeq - let decimalSeq = seq [ 0M;19M;19.03M] |> ISeq.ofSeq + let decimalSeq:iseq = iseq [ 0M;19M;19.03M] let averageDecimal = ISeq.averageBy (fun x -> x/10.7M) decimalSeq Assert.IsFalse( averageDecimal <> 1.1847352024922118380062305296M ) //// null ISeq - //let nullSeq = null + //let nullSeq:iseq = null //CheckThrowsArgumentNullException (fun () -> ISeq.averageBy (fun (x:double)->x+4.0) nullSeq |> ignore) () @@ -217,40 +221,40 @@ type ISeqModule() = [] member this.Cache() = // empty ISeq - let emptySeq = ISeq.empty + let emptySeq:iseq = ISeq.empty - let cacheEmpty = Seq.cache emptySeq + let cacheEmpty = ISeq.cache emptySeq let expectedResultEmpty = ISeq.empty VerifySeqsEqual expectedResultEmpty cacheEmpty // double ISeq - let doubleSeq = seq [1.0;2.2;2.5;4.3] |> ISeq.ofSeq + let doubleSeq:iseq = iseq [1.0;2.2;2.5;4.3] - let cacheDouble = Seq.cache doubleSeq + let cacheDouble = ISeq.cache doubleSeq VerifySeqsEqual doubleSeq cacheDouble // float32 ISeq - let floatSeq = seq [ 2.0f;4.4f;5.0f;8.6f] + let floatSeq:iseq = iseq [ 2.0f;4.4f;5.0f;8.6f] - let cacheFloat = Seq.cache floatSeq + let cacheFloat = ISeq.cache floatSeq VerifySeqsEqual floatSeq cacheFloat // decimal ISeq - let decimalSeq = seq [ 0M; 19M; 19.03M] + let decimalSeq:iseq = iseq [ 0M; 19M; 19.03M] - let cacheDecimal = Seq.cache decimalSeq + let cacheDecimal = ISeq.cache decimalSeq VerifySeqsEqual decimalSeq cacheDecimal // null ISeq - let nullSeq = seq [null] + let nullSeq = iseq [null] - let cacheNull = Seq.cache nullSeq + let cacheNull = ISeq.cache nullSeq VerifySeqsEqual nullSeq cacheNull () @@ -260,43 +264,43 @@ type ISeqModule() = // integer ISeq let integerArray = [|1;2|] - let integerSeq = Seq.cast integerArray + let integerSeq = ISeq.cast integerArray - let expectedIntegerSeq = seq [1;2] + let expectedIntegerSeq = iseq [1;2] VerifySeqsEqual expectedIntegerSeq integerSeq // string ISeq let stringArray = [|"a";"b"|] - let stringSeq = Seq.cast stringArray + let stringSeq = ISeq.cast stringArray - let expectedStringSeq = seq["a";"b"] + let expectedStringSeq = iseq["a";"b"] VerifySeqsEqual expectedStringSeq stringSeq // empty ISeq - let emptySeq = Seq.cast ISeq.empty + let emptySeq = ISeq.cast ISeq.empty let expectedEmptySeq = ISeq.empty VerifySeqsEqual expectedEmptySeq ISeq.empty // null ISeq let nullArray = [|null;null|] - let NullSeq = Seq.cast nullArray - let expectedNullSeq = seq [null;null] + let NullSeq = ISeq.cast nullArray + let expectedNullSeq = iseq [null;null] VerifySeqsEqual expectedNullSeq NullSeq CheckThrowsExn(fun () -> let strings = integerArray - |> Seq.cast + |> ISeq.cast for o in strings do ()) CheckThrowsExn(fun () -> let strings = integerArray - |> Seq.cast + |> ISeq.cast :> System.Collections.IEnumerable // without this upcast the for loop throws, so it should with this upcast too for o in strings do ()) @@ -306,23 +310,23 @@ type ISeqModule() = member this.Choose() = // int ISeq - let intSeq = seq [1..20] |> ISeq.ofSeq + let intSeq = iseq [1..20] let funcInt x = if (x%5=0) then Some x else None let intChoosed = ISeq.choose funcInt intSeq - let expectedIntChoosed = seq { for i = 1 to 4 do yield i*5} + let expectedIntChoosed = iseq <| seq { for i = 1 to 4 do yield i*5} VerifySeqsEqual expectedIntChoosed intChoosed // string ISeq - let stringSrc = seq ["list";"List"] |> ISeq.ofSeq + let stringSrc = iseq ["list";"List"] let funcString x = match x with | "list"-> Some x | "List" -> Some x | _ -> None let strChoosed = ISeq.choose funcString stringSrc - let expectedStrChoose = seq ["list";"List"] + let expectedStrChoose = iseq ["list";"List"] VerifySeqsEqual expectedStrChoose strChoosed @@ -335,8 +339,8 @@ type ISeqModule() = VerifySeqsEqual expectedEmptyChoose emptySeq - // null ISeq - //let nullSeq = null + //// null ISeq + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.choose funcInt nullSeq |> ignore) () @@ -345,37 +349,35 @@ type ISeqModule() = member this.ChunkBySize() = let verify expected actual = - ISeq.zip (expected |> ISeq.ofSeq) (actual |> ISeq.ofSeq) + ISeq.zip expected actual |> ISeq.iter ((<||) VerifySeqsEqual) // int ISeq - verify [[1..4];[5..8]] <| Seq.chunkBySize 4 {1..8} - verify [[1..4];[5..8];[9..10]] <| Seq.chunkBySize 4 {1..10} - verify [[1]; [2]; [3]; [4]] <| Seq.chunkBySize 1 {1..4} + verify (iseq [[1..4];[5..8]]) <| ISeq.chunkBySize 4 (iseq {1..8}) + verify (iseq [[1..4];[5..8];[9..10]]) <| ISeq.chunkBySize 4 (iseq {1..10}) + verify (iseq [[1]; [2]; [3]; [4]]) <| ISeq.chunkBySize 1 (iseq {1..4}) - Seq.chunkBySize 2 (ISeq.initInfinite id) - |> ISeq.ofSeq + ISeq.chunkBySize 2 (ISeq.initInfinite id) |> ISeq.take 3 - |> verify [[0;1];[2;3];[4;5]] + |> verify (iseq [[0;1];[2;3];[4;5]]) - Seq.chunkBySize 1 (ISeq.initInfinite id) - |> ISeq.ofSeq + ISeq.chunkBySize 1 (ISeq.initInfinite id) |> ISeq.take 5 - |> verify [[0];[1];[2];[3];[4]] + |> verify (iseq [[0];[1];[2];[3];[4]]) // string ISeq - verify [["a"; "b"];["c";"d"];["e"]] <| Seq.chunkBySize 2 ["a";"b";"c";"d";"e"] + verify (iseq [["a"; "b"];["c";"d"];["e"]]) <| ISeq.chunkBySize 2 (iseq ["a";"b";"c";"d";"e"]) // empty ISeq - verify ISeq.empty <| Seq.chunkBySize 3 ISeq.empty + verify ISeq.empty <| ISeq.chunkBySize 3 ISeq.empty - // null ISeq - let nullSeq:seq<_> = null - CheckThrowsArgumentNullException (fun () -> Seq.chunkBySize 3 nullSeq |> ignore) + //// null ISeq + //let nullSeq:iseq<_> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.chunkBySize 3 nullSeq |> ignore) // invalidArg - CheckThrowsArgumentException (fun () -> Seq.chunkBySize 0 {1..10} |> ignore) - CheckThrowsArgumentException (fun () -> Seq.chunkBySize -1 {1..10} |> ignore) + CheckThrowsArgumentException (fun () -> ISeq.chunkBySize 0 (iseq {1..10}) |> ignore) + CheckThrowsArgumentException (fun () -> ISeq.chunkBySize -1 (iseq {1..10}) |> ignore) () @@ -383,30 +385,30 @@ type ISeqModule() = member this.SplitInto() = let verify expected actual = - ISeq.zip (expected |> ISeq.ofSeq) (actual |> ISeq.ofSeq) + ISeq.zip expected actual |> ISeq.iter ((<||) VerifySeqsEqual) // int ISeq - Seq.splitInto 3 {1..10} |> verify (seq [ {1..4}; {5..7}; {8..10} ]) - Seq.splitInto 3 {1..11} |> verify (seq [ {1..4}; {5..8}; {9..11} ]) - Seq.splitInto 3 {1..12} |> verify (seq [ {1..4}; {5..8}; {9..12} ]) + ISeq.splitInto 3 (iseq {1..10}) |> verify (iseq [ {1..4}; {5..7}; {8..10} ]) + ISeq.splitInto 3 (iseq {1..11}) |> verify (iseq [ {1..4}; {5..8}; {9..11} ]) + ISeq.splitInto 3 (iseq {1..12}) |> verify (iseq [ {1..4}; {5..8}; {9..12} ]) - Seq.splitInto 4 {1..5} |> verify (seq [ [1..2]; [3]; [4]; [5] ]) - Seq.splitInto 20 {1..4} |> verify (seq [ [1]; [2]; [3]; [4] ]) + ISeq.splitInto 4 (iseq {1..5}) |> verify (iseq [ [1..2]; [3]; [4]; [5] ]) + ISeq.splitInto 20 (iseq {1..4}) |> verify (iseq [ [1]; [2]; [3]; [4] ]) // string ISeq - Seq.splitInto 3 ["a";"b";"c";"d";"e"] |> verify ([ ["a"; "b"]; ["c";"d"]; ["e"] ]) + ISeq.splitInto 3 (iseq ["a";"b";"c";"d";"e"]) |> verify (iseq [ ["a"; "b"]; ["c";"d"]; ["e"] ]) // empty ISeq - VerifySeqsEqual [] <| Seq.splitInto 3 [] + VerifySeqsEqual [] <| ISeq.splitInto 3 (iseq []) - // null ISeq - let nullSeq:seq<_> = null - CheckThrowsArgumentNullException (fun () -> Seq.splitInto 3 nullSeq |> ignore) + //// null ISeq + //let nullSeq:iseq<_> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.splitInto 3 nullSeq |> ignore) // invalidArg - CheckThrowsArgumentException (fun () -> Seq.splitInto 0 [1..10] |> ignore) - CheckThrowsArgumentException (fun () -> Seq.splitInto -1 [1..10] |> ignore) + CheckThrowsArgumentException (fun () -> ISeq.splitInto 0 (iseq [1..10]) |> ignore) + CheckThrowsArgumentException (fun () -> ISeq.splitInto -1 (iseq [1..10]) |> ignore) () @@ -414,16 +416,16 @@ type ISeqModule() = member this.Compare() = // int ISeq - let intSeq1 = seq [1;3;7;9] |> ISeq.ofSeq - let intSeq2 = seq [2;4;6;8] |> ISeq.ofSeq + 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 = ISeq.compareWith funcInt intSeq1 intSeq2 Assert.IsFalse( intcompared <> 7 ) // string ISeq - let stringSeq1 = seq ["a"; "b"] |> ISeq.ofSeq - let stringSeq2 = seq ["c"; "d"] |> ISeq.ofSeq + let stringSeq1 = iseq ["a"; "b"] + let stringSeq2 = iseq ["c"; "d"] let funcString x y = match (x,y) with | "a", "c" -> 0 | "b", "d" -> 1 @@ -437,8 +439,8 @@ type ISeqModule() = Assert.IsFalse( emptycompared <> 0 ) - // null ISeq - //let nullSeq = null + //// null ISeq + //let nullSeq:iseq = null //CheckThrowsArgumentNullException (fun () -> ISeq.compareWith funcInt nullSeq emptySeq |> ignore) //CheckThrowsArgumentNullException (fun () -> ISeq.compareWith funcInt emptySeq nullSeq |> ignore) @@ -450,33 +452,33 @@ type ISeqModule() = member this.Concat() = // integer ISeq let seqInt = - seq { for i in 0..9 do - yield seq {for j in 0..9 do - yield i*10+j} |> ISeq.ofSeq } |> ISeq.ofSeq + iseq <| seq { for i in 0..9 do + yield iseq <| seq {for j in 0..9 do + yield i*10+j}} let conIntSeq = ISeq.concat seqInt - let expectedIntSeq = seq { for i in 0..99 do yield i} + let expectedIntSeq = iseq <| seq { for i in 0..99 do yield i} VerifySeqsEqual expectedIntSeq conIntSeq // string ISeq let strSeq = - seq { for a in 'a' .. 'b' do - for b in 'a' .. 'b' do - yield seq [a; b] |> ISeq.ofSeq }|> ISeq.ofSeq + iseq <| seq { for a in 'a' .. 'b' do + for b in 'a' .. 'b' do + yield iseq [a; b] } let conStrSeq = ISeq.concat strSeq - let expectedStrSeq = seq ['a';'a';'a';'b';'b';'a';'b';'b';] + let expectedStrSeq = iseq ['a';'a';'a';'b';'b';'a';'b';'b';] VerifySeqsEqual expectedStrSeq conStrSeq // Empty ISeq - let emptySeqs = seq [seq[ ISeq.empty;ISeq.empty]|> ISeq.ofSeq;seq[ ISeq.empty;ISeq.empty]|> ISeq.ofSeq]|> ISeq.ofSeq + let emptySeqs = iseq [iseq[ ISeq.empty;ISeq.empty];iseq[ ISeq.empty;ISeq.empty]] let conEmptySeq = ISeq.concat emptySeqs - let expectedEmptySeq =seq { for i in 1..4 do yield ISeq.empty} + let expectedEmptySeq =iseq <| seq { for i in 1..4 do yield ISeq.empty} VerifySeqsEqual expectedEmptySeq conEmptySeq //// null ISeq - //let nullSeq = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.concat nullSeq |> ignore) @@ -487,33 +489,33 @@ type ISeqModule() = // integer ISeq let funcIntCount_by (x:int) = x%3 let seqInt = - seq { for i in 0..9 do - yield i} - let countIntSeq = Seq.countBy funcIntCount_by seqInt + iseq <| seq { for i in 0..9 do + yield i} + let countIntSeq = ISeq.countByVal funcIntCount_by seqInt - let expectedIntSeq = seq [0,4;1,3;2,3] + let expectedIntSeq = iseq [0,4;1,3;2,3] VerifySeqsEqual expectedIntSeq countIntSeq // string ISeq let funcStrCount_by (s:string) = s.IndexOf("key") - let strSeq = seq [ "key";"blank key";"key";"blank blank key"] + let strSeq = iseq [ "key";"blank key";"key";"blank blank key"] - let countStrSeq = Seq.countBy funcStrCount_by strSeq - let expectedStrSeq = seq [0,2;6,1;12,1] + let countStrSeq = ISeq.countByVal funcStrCount_by strSeq + let expectedStrSeq = iseq [0,2;6,1;12,1] VerifySeqsEqual expectedStrSeq countStrSeq // Empty ISeq let emptySeq = ISeq.empty - let countEmptySeq = Seq.countBy funcIntCount_by emptySeq - let expectedEmptySeq =seq [] + let countEmptySeq = ISeq.countByVal funcIntCount_by emptySeq + let expectedEmptySeq =iseq [] VerifySeqsEqual expectedEmptySeq countEmptySeq - // null ISeq - let nullSeq = null + //// null ISeq + //let nullSeq:iseq<'a> = null - CheckThrowsArgumentNullException (fun () -> Seq.countBy funcIntCount_by nullSeq |> ignore) + //CheckThrowsArgumentNullException (fun () -> ISeq.countBy funcIntCount_by nullSeq |> ignore) () [] @@ -521,31 +523,31 @@ type ISeqModule() = // integer ISeq let IntDistinctSeq = - seq { for i in 0..9 do - yield i % 3 } |> ISeq.ofSeq + iseq <| seq { for i in 0..9 do + yield i % 3 } let DistinctIntSeq = ISeq.distinct IntDistinctSeq - let expectedIntSeq = seq [0;1;2] + let expectedIntSeq = iseq [0;1;2] VerifySeqsEqual expectedIntSeq DistinctIntSeq // string ISeq - let strDistinctSeq = seq ["elementDup"; "ele1"; "ele2"; "elementDup"] |> ISeq.ofSeq + let strDistinctSeq = iseq ["elementDup"; "ele1"; "ele2"; "elementDup"] let DistnctStrSeq = ISeq.distinct strDistinctSeq - let expectedStrSeq = seq ["elementDup"; "ele1"; "ele2"] |> ISeq.ofSeq + let expectedStrSeq = iseq ["elementDup"; "ele1"; "ele2"] VerifySeqsEqual expectedStrSeq DistnctStrSeq // Empty ISeq - let emptySeq = ISeq.empty - let distinctEmptySeq = ISeq.distinct emptySeq - let expectedEmptySeq = seq [] |> ISeq.ofSeq + let emptySeq : iseq = ISeq.empty + let distinctEmptySeq : iseq = ISeq.distinct emptySeq + let expectedEmptySeq : iseq = iseq [] VerifySeqsEqual expectedEmptySeq distinctEmptySeq //// null ISeq - //let nullSeq = null + //let nullSeq:iseq = null //CheckThrowsArgumentNullException(fun () -> ISeq.distinct nullSeq |> ignore) () @@ -555,32 +557,32 @@ type ISeqModule() = // integer ISeq let funcInt x = x % 3 let IntDistinct_bySeq = - seq { for i in 0..9 do - yield i } |> ISeq.ofSeq + iseq <| seq { for i in 0..9 do + yield i } let distinct_byIntSeq = ISeq.distinctBy funcInt IntDistinct_bySeq - let expectedIntSeq = seq [0;1;2] |> ISeq.ofSeq + let expectedIntSeq = iseq [0;1;2] VerifySeqsEqual expectedIntSeq distinct_byIntSeq // string ISeq let funcStrDistinct (s:string) = s.IndexOf("key") - let strSeq = seq [ "key"; "blank key"; "key dup"; "blank key dup"] |> ISeq.ofSeq + let strSeq = iseq [ "key"; "blank key"; "key dup"; "blank key dup"] let DistnctStrSeq = ISeq.distinctBy funcStrDistinct strSeq - let expectedStrSeq = seq ["key"; "blank key"] |> ISeq.ofSeq + let expectedStrSeq = iseq ["key"; "blank key"] VerifySeqsEqual expectedStrSeq DistnctStrSeq // Empty ISeq - let emptySeq = ISeq.empty - let distinct_byEmptySeq = ISeq.distinctBy funcInt emptySeq - let expectedEmptySeq = seq [] |> ISeq.ofSeq + let emptySeq : iseq = ISeq.empty + let distinct_byEmptySeq : iseq = ISeq.distinctBy funcInt emptySeq + let expectedEmptySeq : iseq = iseq [] VerifySeqsEqual expectedEmptySeq distinct_byEmptySeq //// null ISeq - //let nullSeq = null + //let nullSeq : iseq<'a> = null //CheckThrowsArgumentNullException(fun () -> ISeq.distinctBy funcInt nullSeq |> ignore) () @@ -588,23 +590,23 @@ type ISeqModule() = [] member this.Except() = // integer ISeq - let intSeq1 = seq { yield! {1..100} - yield! {1..100} } |> ISeq.ofSeq - let intSeq2 = {1..10} |> ISeq.ofSeq - let expectedIntSeq = {11..100} |> ISeq.ofSeq + let intSeq1 = iseq <| seq { yield! {1..100} + yield! {1..100} } + let intSeq2 = {1..10} + let expectedIntSeq = {11..100} VerifySeqsEqual expectedIntSeq <| ISeq.except intSeq2 intSeq1 // string ISeq - let strSeq1 = seq ["a"; "b"; "c"; "d"; "a"] |> ISeq.ofSeq - let strSeq2 = seq ["b"; "c"] |> ISeq.ofSeq - let expectedStrSeq = seq ["a"; "d"] |> ISeq.ofSeq + let strSeq1 = iseq ["a"; "b"; "c"; "d"; "a"] + let strSeq2 = iseq ["b"; "c"] + let expectedStrSeq = iseq ["a"; "d"] VerifySeqsEqual expectedStrSeq <| ISeq.except strSeq2 strSeq1 // double ISeq // Sequences with nan do not behave, due to the F# generic equality comparisons -// let floatSeq1 = seq [1.0; 1.0; System.Double.MaxValue; nan; nan] +// let floatSeq1 = iseq [1.0; 1.0; System.Double.MaxValue; nan; nan] // // VerifySeqsEqual [1.0; System.Double.MaxValue; nan; nan] <| ISeq.except [] floatSeq1 // VerifySeqsEqual [1.0; System.Double.MaxValue] <| ISeq.except [nan] floatSeq1 @@ -617,7 +619,7 @@ type ISeqModule() = VerifySeqsEqual emptyIntSeq <| ISeq.except intSeq1 intSeq1 //// null ISeq - //let nullSeq = null + //let nullSeq : iseq = null //CheckThrowsArgumentNullException(fun () -> ISeq.except nullSeq emptyIntSeq |> ignore) //CheckThrowsArgumentNullException(fun () -> ISeq.except emptyIntSeq nullSeq |> ignore) //CheckThrowsArgumentNullException(fun () -> ISeq.except nullSeq nullSeq |> ignore) @@ -630,8 +632,8 @@ type ISeqModule() = // Integer ISeq let funcInt x = (x % 2 = 0) let IntexistsSeq = - seq { for i in 0..9 do - yield i} |> ISeq.ofSeq + iseq <| seq { for i in 0..9 do + yield i} let ifExistInt = ISeq.exists funcInt IntexistsSeq @@ -639,7 +641,7 @@ type ISeqModule() = // String ISeq let funcStr (s:string) = s.Contains("key") - let strSeq = seq ["key"; "blank key"] |> ISeq.ofSeq + let strSeq = iseq ["key"; "blank key"] let ifExistStr = ISeq.exists funcStr strSeq @@ -654,7 +656,7 @@ type ISeqModule() = //// null ISeq - //let nullSeq = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.exists funcInt nullSeq |> ignore) () @@ -663,16 +665,16 @@ type ISeqModule() = member this.Exists2() = // Integer ISeq let funcInt x y = (x+y)%3=0 - let Intexists2Seq1 = seq [1;3;7] |> ISeq.ofSeq - let Intexists2Seq2 = seq [1;6;3] |> ISeq.ofSeq + let Intexists2Seq1 = iseq [1;3;7] + let Intexists2Seq2 = iseq [1;6;3] let ifExist2Int = ISeq.exists2 funcInt Intexists2Seq1 Intexists2Seq2 Assert.IsTrue( ifExist2Int) // String ISeq let funcStr s1 s2 = ((s1 + s2) = "CombinedString") - let strSeq1 = seq [ "Combined"; "Not Combined"] |> ISeq.ofSeq - let strSeq2 = seq ["String"; "Other String"] |> ISeq.ofSeq + let strSeq1 = iseq [ "Combined"; "Not Combined"] + let strSeq2 = iseq ["String"; "Other String"] let ifexists2Str = ISeq.exists2 funcStr strSeq1 strSeq2 Assert.IsTrue(ifexists2Str) @@ -682,7 +684,7 @@ type ISeqModule() = Assert.IsFalse( ifexists2Empty) //// null ISeq - //let nullSeq = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.exists2 funcInt nullSeq nullSeq |> ignore) () @@ -692,36 +694,36 @@ type ISeqModule() = // integer ISeq let funcInt x = if (x % 5 = 0) then true else false let IntSeq = - seq { for i in 1..20 do - yield i } |> ISeq.ofSeq + iseq <| seq { for i in 1..20 do + yield i } let filterIntSeq = ISeq.filter funcInt IntSeq - let expectedfilterInt = seq [ 5;10;15;20] + let expectedfilterInt = iseq [ 5;10;15;20] VerifySeqsEqual expectedfilterInt filterIntSeq // string ISeq let funcStr (s:string) = s.Contains("Expected Content") - let strSeq = seq [ "Expected Content"; "Not Expected"; "Expected Content"; "Not Expected"] |> ISeq.ofSeq + let strSeq = iseq [ "Expected Content"; "Not Expected"; "Expected Content"; "Not Expected"] let filterStrSeq = ISeq.filter funcStr strSeq - let expectedfilterStr = seq ["Expected Content"; "Expected Content"] |> ISeq.ofSeq + let expectedfilterStr = iseq ["Expected Content"; "Expected Content"] VerifySeqsEqual expectedfilterStr filterStrSeq // Empty ISeq let emptySeq = ISeq.empty let filterEmptySeq = ISeq.filter funcInt emptySeq - let expectedEmptySeq =seq [] + let expectedEmptySeq =iseq [] VerifySeqsEqual expectedEmptySeq filterEmptySeq //// null ISeq - //let nullSeq = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.filter funcInt nullSeq |> ignore) () @@ -732,54 +734,54 @@ type ISeqModule() = // integer ISeq let funcInt x = if (x % 5 = 0) then true else false let IntSeq = - seq { for i in 1..20 do - yield i } |> ISeq.ofSeq + iseq <| seq { for i in 1..20 do + yield i } - let findInt = Seq.find funcInt IntSeq + let findInt = ISeq.find funcInt IntSeq Assert.AreEqual(findInt, 5) // string ISeq let funcStr (s:string) = s.Contains("Expected Content") - let strSeq = seq [ "Expected Content";"Not Expected"] |> ISeq.ofSeq + let strSeq = iseq [ "Expected Content";"Not Expected"] - let findStr = Seq.find funcStr strSeq + let findStr = ISeq.find funcStr strSeq Assert.AreEqual(findStr, "Expected Content") // Empty ISeq let emptySeq = ISeq.empty - CheckThrowsKeyNotFoundException(fun () -> Seq.find funcInt emptySeq |> ignore) + CheckThrowsKeyNotFoundException(fun () -> ISeq.find funcInt emptySeq |> ignore) - //// null ISeq - //let nullSeq = null - //CheckThrowsArgumentNullException (fun () -> Seq.find funcInt nullSeq |> ignore) + // null ISeq + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.find funcInt nullSeq |> ignore) () [] member this.FindBack() = // integer ISeq let funcInt x = x % 5 = 0 - Assert.AreEqual(20, Seq.findBack funcInt <| seq { 1..20 }) - Assert.AreEqual(15, Seq.findBack funcInt <| seq { 1..19 }) - Assert.AreEqual(5, Seq.findBack funcInt <| seq { 5..9 }) + Assert.AreEqual(20, ISeq.findBack funcInt <| (iseq <| seq { 1..20 })) + Assert.AreEqual(15, ISeq.findBack funcInt <| (iseq <| seq { 1..19 })) + Assert.AreEqual(5, ISeq.findBack funcInt <| (iseq <| seq { 5..9 })) // string ISeq let funcStr (s:string) = s.Contains("Expected") - let strSeq = seq [ "Not Expected"; "Expected Content"] |> ISeq.ofSeq - let findStr = Seq.findBack funcStr strSeq + let strSeq = iseq [ "Not Expected"; "Expected Content"] + let findStr = ISeq.findBack funcStr strSeq Assert.AreEqual("Expected Content", findStr) // Empty ISeq let emptySeq = ISeq.empty - CheckThrowsKeyNotFoundException(fun () -> Seq.findBack funcInt emptySeq |> ignore) + CheckThrowsKeyNotFoundException(fun () -> ISeq.findBack funcInt emptySeq |> ignore) // Not found let emptySeq = ISeq.empty - CheckThrowsKeyNotFoundException(fun () -> seq { 1..20 } |> Seq.findBack (fun _ -> false) |> ignore) + CheckThrowsKeyNotFoundException(fun () -> iseq <| seq { 1..20 } |> ISeq.findBack (fun _ -> false) |> ignore) //// null ISeq - //let nullSeq = null - //CheckThrowsArgumentNullException (fun () -> Seq.findBack funcInt nullSeq |> ignore) + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.findBack funcInt nullSeq |> ignore) () [] @@ -787,74 +789,74 @@ type ISeqModule() = // integer ISeq let digits = [1 .. 100] |> ISeq.ofList - let idx = digits |> Seq.findIndex (fun i -> i.ToString().Length > 1) + let idx = digits |> ISeq.findIndex (fun i -> i.ToString().Length > 1) Assert.AreEqual(idx, 9) // empty ISeq - CheckThrowsKeyNotFoundException(fun () -> Seq.findIndex (fun i -> true) ISeq.empty |> ignore) + CheckThrowsKeyNotFoundException(fun () -> ISeq.findIndex (fun i -> true) ISeq.empty |> ignore) //// null ISeq - //CheckThrowsArgumentNullException(fun() -> Seq.findIndex (fun i -> true) null |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.findIndex (fun i -> true) null |> ignore) () [] member this.Permute() = let mapIndex i = (i + 1) % 4 - // integer seq - let intSeq = seq { 1..4 }|> ISeq.ofSeq + // integer iseq + let intSeq = iseq <| seq { 1..4 } let resultInt = ISeq.permute mapIndex intSeq - VerifySeqsEqual (seq [4;1;2;3]) resultInt + VerifySeqsEqual (iseq [4;1;2;3]) resultInt - // string seq - let resultStr = ISeq.permute mapIndex ([|"Lists"; "are"; "commonly"; "list" |] |> ISeq.ofSeq) - VerifySeqsEqual (seq ["list"; "Lists"; "are"; "commonly" ]) resultStr + // string iseq + let resultStr = ISeq.permute mapIndex (iseq [|"Lists"; "are"; "commonly"; "list" |]) + VerifySeqsEqual (iseq ["list"; "Lists"; "are"; "commonly" ]) resultStr - // empty seq - let resultEpt = ISeq.permute mapIndex ([||] |> ISeq.ofSeq) + // empty iseq + let resultEpt = ISeq.permute mapIndex (iseq [||]) VerifySeqsEqual ISeq.empty resultEpt - //// null seq - //let nullSeq = null + //// null iseq + //let nullSeq = null:string[] //CheckThrowsArgumentNullException (fun () -> ISeq.permute mapIndex nullSeq |> ignore) // argument exceptions - CheckThrowsArgumentException (fun () -> ISeq.permute (fun _ -> 10) ([0..9]|> ISeq.ofSeq) |> ISeq.iter ignore) - CheckThrowsArgumentException (fun () -> ISeq.permute (fun _ -> 0) ([0..9]|> ISeq.ofSeq) |> ISeq.iter ignore) + CheckThrowsArgumentException (fun () -> ISeq.permute (fun _ -> 10) (iseq [0..9]) |> ISeq.iter ignore) + CheckThrowsArgumentException (fun () -> ISeq.permute (fun _ -> 0) (iseq [0..9]) |> ISeq.iter ignore) () [] member this.FindIndexBack() = // integer ISeq - let digits = seq { 1..100 }|> ISeq.ofSeq - let idx = digits |> Seq.findIndexBack (fun i -> i.ToString().Length = 1) + let digits = iseq <| seq { 1..100 } + let idx = digits |> ISeq.findIndexBack (fun i -> i.ToString().Length = 1) Assert.AreEqual(idx, 8) // string ISeq let funcStr (s:string) = s.Contains("Expected") - let strSeq = seq [ "Not Expected"; "Expected Content" ] |> ISeq.ofSeq - let findStr = Seq.findIndexBack funcStr strSeq + let strSeq = iseq [ "Not Expected"; "Expected Content" ] + let findStr = ISeq.findIndexBack funcStr strSeq Assert.AreEqual(1, findStr) // empty ISeq - CheckThrowsKeyNotFoundException(fun () -> Seq.findIndexBack (fun i -> true) ISeq.empty |> ignore) + CheckThrowsKeyNotFoundException(fun () -> ISeq.findIndexBack (fun i -> true) ISeq.empty |> ignore) //// null ISeq - //CheckThrowsArgumentNullException(fun() -> Seq.findIndexBack (fun i -> true) null |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.findIndexBack (fun i -> true) null |> ignore) () [] member this.Pick() = let digits = [| 1 .. 10 |] |> ISeq.ofArray - let result = Seq.pick (fun i -> if i > 5 then Some(i.ToString()) else None) digits + let result = ISeq.pick (fun i -> if i > 5 then Some(i.ToString()) else None) digits Assert.AreEqual(result, "6") - // Empty seq (Bugged, 4173) - CheckThrowsKeyNotFoundException (fun () -> Seq.pick (fun i -> Some('a')) ([| |] : int[]) |> ignore) + // Empty iseq (Bugged, 4173) + CheckThrowsKeyNotFoundException (fun () -> ISeq.pick (fun i -> Some('a')) (iseq ([| |] : int[])) |> ignore) - // Null - CheckThrowsArgumentNullException (fun () -> Seq.pick (fun i -> Some(i + 0)) null |> ignore) + //// Null + //CheckThrowsArgumentNullException (fun () -> ISeq.pick (fun i -> Some(i + 0)) null |> ignore) () [] @@ -862,15 +864,15 @@ type ISeqModule() = let funcInt x y = x+y let IntSeq = - seq { for i in 1..10 do - yield i} |> ISeq.ofSeq + iseq <| seq { for i in 1..10 do + yield i} let foldInt = ISeq.fold funcInt 1 IntSeq if foldInt <> 56 then Assert.Fail() // string ISeq let funcStr (x:string) (y:string) = x+y - let strSeq = seq ["B"; "C"; "D" ; "E"] |> ISeq.ofSeq + let strSeq = iseq ["B"; "C"; "D" ; "E"] let foldStr = ISeq.fold funcStr "A" strSeq if foldStr <> "ABCDE" then Assert.Fail() @@ -882,7 +884,7 @@ type ISeqModule() = if foldEmpty <> 1 then Assert.Fail() //// null ISeq - //let nullSeq = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.fold funcInt 1 nullSeq |> ignore) () @@ -891,53 +893,53 @@ type ISeqModule() = [] member this.Fold2() = - Assert.AreEqual([(3,5); (2,3); (1,1)],ISeq.fold2 (fun acc x y -> (x,y)::acc) [] (seq [ 1..3 ] |> ISeq.ofSeq) (seq [1..2..6] |> ISeq.ofSeq)) + Assert.AreEqual([(3,5); (2,3); (1,1)],ISeq.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 = ISeq.fold2 funcInt 9 (seq [ 1..10 ] |> ISeq.ofSeq) (seq [1..2..20] |> ISeq.ofSeq) + let resultInt = ISeq.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 = ISeq.fold2 funcStr "*" (["a"; "b"; "c" ; "d" ] |> ISeq.ofSeq) (["A"; "B"; "C" ; "D" ] |> ISeq.ofSeq) + let resultStr = ISeq.fold2 funcStr "*" (iseq ["a"; "b"; "c" ; "d" ]) (iseq ["A"; "B"; "C" ; "D" ] ) Assert.AreEqual("*aAbBcCdD", resultStr) // empty List - let emptyArr = [ ] |> ISeq.ofSeq - let resultEpt = ISeq.fold2 funcInt 5 emptyArr emptyArr + let emptyArr:int list = [ ] + let resultEpt = ISeq.fold2 funcInt 5 (iseq emptyArr) (iseq emptyArr) Assert.AreEqual(5, resultEpt) - Assert.AreEqual(0,ISeq.fold2 funcInt 0 ISeq.empty (seq [1] |> ISeq.ofSeq)) - Assert.AreEqual(-1,ISeq.fold2 funcInt -1 (seq [1] |> ISeq.ofSeq) ISeq.empty) + Assert.AreEqual(0,ISeq.fold2 funcInt 0 ISeq.empty (iseq [1])) + Assert.AreEqual(-1,ISeq.fold2 funcInt -1 (iseq [1]) ISeq.empty) - Assert.AreEqual(2,ISeq.fold2 funcInt 0 (seq [1;2] |> ISeq.ofSeq) (seq [1] |> ISeq.ofSeq)) - Assert.AreEqual(4,ISeq.fold2 funcInt 0 (seq [1] |> ISeq.ofSeq) (seq [3;6] |> ISeq.ofSeq)) + Assert.AreEqual(2,ISeq.fold2 funcInt 0 (iseq [1;2]) (iseq [1])) + Assert.AreEqual(4,ISeq.fold2 funcInt 0 (iseq [1]) (iseq [3;6])) //// null ISeq - //let nullSeq = null + //let nullSeq:iseq<'a> = null - //CheckThrowsArgumentNullException (fun () -> ISeq.fold2 funcInt 0 nullSeq (seq [1] |> ISeq.ofSeq) |> ignore) - //CheckThrowsArgumentNullException (fun () -> ISeq.fold2 funcInt 0 (seq [1] |> ISeq.ofSeq) nullSeq |> ignore) + //CheckThrowsArgumentNullException (fun () -> ISeq.fold2 funcInt 0 nullSeq (iseq [1]) |> ignore) + //CheckThrowsArgumentNullException (fun () -> ISeq.fold2 funcInt 0 (iseq [1]) nullSeq |> ignore) () [] member this.FoldBack() = // int ISeq let funcInt x y = x-y - let IntSeq = seq { 1..4 } |> ISeq.ofSeq + let IntSeq = iseq <| seq { 1..4 } let foldInt = ISeq.foldBack funcInt IntSeq 6 Assert.AreEqual((1-(2-(3-(4-6)))), foldInt) // string ISeq let funcStr (x:string) (y:string) = y.Remove(0,x.Length) - let strSeq = seq [ "A"; "B"; "C"; "D" ] |> ISeq.ofSeq + let strSeq = iseq [ "A"; "B"; "C"; "D" ] let foldStr = ISeq.foldBack funcStr strSeq "ABCDE" Assert.AreEqual("E", foldStr) // single element let funcStr2 elem acc = sprintf "%s%s" elem acc - let strSeq2 = seq [ "A" ] |> ISeq.ofSeq + let strSeq2 = iseq [ "A" ] let foldStr2 = ISeq.foldBack funcStr2 strSeq2 "X" Assert.AreEqual("AX", foldStr2) @@ -947,7 +949,7 @@ type ISeqModule() = Assert.AreEqual(1, foldEmpty) //// null ISeq - //let nullSeq = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.foldBack funcInt nullSeq 1 |> ignore) // Validate that foldBack with the cons operator and the empty list returns a copy of the sequence @@ -961,21 +963,21 @@ type ISeqModule() = member this.foldBack2() = // int ISeq let funcInt x y z = x + y + z - let intSeq = seq { 1..10 } |> ISeq.ofSeq - let resultInt = ISeq.foldBack2 funcInt intSeq (seq { 1..2..20 } |> ISeq.ofSeq) 9 + let intSeq = iseq <| seq { 1..10 } + let resultInt = ISeq.foldBack2 funcInt intSeq (iseq <| seq { 1..2..20 }) 9 Assert.AreEqual(164, resultInt) // string ISeq let funcStr = sprintf "%s%s%s" - let strSeq = seq [ "A"; "B"; "C"; "D" ] |> ISeq.ofSeq - let resultStr = ISeq.foldBack2 funcStr strSeq (seq [ "a"; "b"; "c"; "d"] |> ISeq.ofSeq) "*" + let strSeq = iseq [ "A"; "B"; "C"; "D" ] + let resultStr = ISeq.foldBack2 funcStr strSeq (iseq [ "a"; "b"; "c"; "d"]) "*" Assert.AreEqual("AaBbCcDd*", resultStr) // single element - let strSeqSingle = seq [ "X" ] |> ISeq.ofSeq + let strSeqSingle = iseq [ "X" ] Assert.AreEqual("XAZ", ISeq.foldBack2 funcStr strSeqSingle strSeq "Z") Assert.AreEqual("AXZ", ISeq.foldBack2 funcStr strSeq strSeqSingle "Z") - Assert.AreEqual("XYZ", ISeq.foldBack2 funcStr strSeqSingle (seq [ "Y" ] |> ISeq.ofSeq) "Z") + Assert.AreEqual("XYZ", ISeq.foldBack2 funcStr strSeqSingle (iseq [ "Y" ]) "Z") // empty ISeq let emptySeq = ISeq.empty @@ -989,7 +991,7 @@ type ISeqModule() = Assert.AreEqual(164, ISeq.foldBack2 funcInt infiniteSeq intSeq 9) //// null ISeq - //let nullSeq = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.foldBack2 funcInt nullSeq intSeq 1 |> ignore) //CheckThrowsArgumentNullException (fun () -> ISeq.foldBack2 funcInt intSeq nullSeq 1 |> ignore) //CheckThrowsArgumentNullException (fun () -> ISeq.foldBack2 funcInt nullSeq nullSeq 1 |> ignore) @@ -1001,8 +1003,8 @@ type ISeqModule() = let funcInt x = if x%2 = 0 then true else false let IntSeq = - seq { for i in 1..10 do - yield i*2} |> ISeq.ofSeq + iseq <| seq { for i in 1..10 do + yield i*2} let for_allInt = ISeq.forall funcInt IntSeq if for_allInt <> true then Assert.Fail() @@ -1010,7 +1012,7 @@ type ISeqModule() = // string ISeq let funcStr (x:string) = x.Contains("a") - let strSeq = seq ["a"; "ab"; "abc" ; "abcd"] |> ISeq.ofSeq + let strSeq = iseq ["a"; "ab"; "abc" ; "abcd"] let for_allStr = ISeq.forall funcStr strSeq if for_allStr <> true then Assert.Fail() @@ -1023,7 +1025,7 @@ type ISeqModule() = if for_allEmpty <> true then Assert.Fail() //// null ISeq - //let nullSeq = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.forall funcInt nullSeq |> ignore) () @@ -1032,8 +1034,8 @@ type ISeqModule() = let funcInt x y = if (x+y)%2 = 0 then true else false let IntSeq = - seq { for i in 1..10 do - yield i} |> ISeq.ofSeq + iseq <| seq { for i in 1..10 do + yield i} let for_all2Int = ISeq.forall2 funcInt IntSeq IntSeq @@ -1041,8 +1043,8 @@ type ISeqModule() = // string ISeq let funcStr (x:string) (y:string) = (x+y).Length = 5 - let strSeq1 = seq ["a"; "ab"; "abc" ; "abcd"] |> ISeq.ofSeq - let strSeq2 = seq ["abcd"; "abc"; "ab" ; "a"] |> ISeq.ofSeq + let strSeq1 = iseq ["a"; "ab"; "abc" ; "abcd"] + let strSeq2 = iseq ["abcd"; "abc"; "ab" ; "a"] let for_all2Str = ISeq.forall2 funcStr strSeq1 strSeq2 if for_all2Str <> true then Assert.Fail() @@ -1054,7 +1056,7 @@ type ISeqModule() = if for_all2Empty <> true then Assert.Fail() //// null ISeq - //let nullSeq = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.forall2 funcInt nullSeq nullSeq |> ignore) @@ -1064,47 +1066,47 @@ type ISeqModule() = let funcInt x = x%5 let IntSeq = - seq { for i in 0 .. 9 do - yield i } |> ISeq.ofSeq + iseq <| seq { for i in 0 .. 9 do + yield i } - let group_byInt = ISeq.groupByVal funcInt IntSeq |> ISeq.map (fun (i, v) -> i, Seq.toList v) + let group_byInt = ISeq.groupByVal funcInt IntSeq |> ISeq.map (fun (i, v) -> i, ISeq.toList v) let expectedIntSeq = - seq { for i in 0..4 do - yield i, [i; i+5] } |> ISeq.ofSeq + iseq <| seq { for i in 0..4 do + yield i, [i; i+5] } VerifySeqsEqual group_byInt expectedIntSeq // string ISeq let funcStr (x:string) = x.Length - let strSeq = seq ["length7"; "length 8"; "length7" ; "length 9"] |> ISeq.ofSeq + let strSeq = iseq ["length7"; "length 8"; "length7" ; "length 9"] - let group_byStr = ISeq.groupByVal funcStr strSeq |> ISeq.map (fun (i, v) -> i, Seq.toList v) + let group_byStr = ISeq.groupByVal funcStr strSeq |> ISeq.map (fun (i, v) -> i, ISeq.toList v) let expectedStrSeq = - seq { + iseq <| seq { yield 7, ["length7"; "length7"] yield 8, ["length 8"] - yield 9, ["length 9"] } |> ISeq.ofSeq + yield 9, ["length 9"] } VerifySeqsEqual expectedStrSeq group_byStr // Empty ISeq let emptySeq = ISeq.empty let group_byEmpty = ISeq.groupByVal funcInt emptySeq - let expectedEmptySeq = seq [] + let expectedEmptySeq = iseq [] VerifySeqsEqual expectedEmptySeq group_byEmpty //// null ISeq - //let nullSeq = null - //let group_byNull = ISeq.groupByVal funcInt nullSeq + //let nullSeq:iseq<'a> = null + //let group_byNull = ISeq.groupBy funcInt nullSeq //CheckThrowsArgumentNullException (fun () -> ISeq.iter (fun _ -> ()) group_byNull) () [] member this.DisposalOfUnstartedEnumerator() = let run = ref false - let f() = seq { + let f() = iseq <| seq { try () finally @@ -1117,36 +1119,36 @@ type ISeqModule() = [] member this.WeirdLocalNames() = - let f pc = seq { + let f pc = iseq <| seq { yield pc yield (pc+1) yield (pc+2) } - let l = f 3 |> Seq.toList + let l = f 3 |> ISeq.toList Assert.AreEqual([3;4;5], l) - let f i = seq { + let f i = iseq <| seq { let pc = i*2 yield pc yield (pc+1) yield (pc+2) } - let l = f 3 |> Seq.toList + let l = f 3 |> ISeq.toList Assert.AreEqual([6;7;8], l) [] member this.Contains() = // Integer ISeq - let intSeq = seq { 0..9 } |> ISeq.ofSeq + let intSeq = iseq <| seq { 0..9 } let ifContainsInt = ISeq.contains 5 intSeq Assert.IsTrue(ifContainsInt) // String ISeq - let strSeq = seq ["key"; "blank key"] |> ISeq.ofSeq + let strSeq = iseq ["key"; "blank key"] let ifContainsStr = ISeq.contains "key" strSeq @@ -1159,6 +1161,6 @@ type ISeqModule() = Assert.IsFalse(ifContainsEmpty) //// null ISeq - //let nullSeq = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.contains 5 nullSeq |> ignore) diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule2.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule2.fs index 36d8839f10..859a3a7f46 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule2.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule2.fs @@ -7,28 +7,31 @@ open NUnit.Framework open FSharp.Core.Unittests.LibraryTestFx +//type iseq<'a> = ISeq.Core.ISeq<'a> + type ISeqWindowedTestInput<'t> = { - InputSeq : seq<'t> + InputSeq : iseq<'t> WindowSize : int - ExpectedSeq : seq<'t[]> + ExpectedSeq : iseq<'t[]> Exception : Type option } [] type ISeqModule2() = + let iseq (x:seq<_>) = x |> ISeq.ofSeq [] member this.Hd() = let IntSeq = - seq { for i in 0 .. 9 do - yield i } |> ISeq.ofSeq + iseq <| seq { for i in 0 .. 9 do + yield i } if ISeq.head IntSeq <> 0 then Assert.Fail() // string ISeq - let strSeq = seq ["first"; "second"; "third"] |> ISeq.ofSeq + let strSeq = iseq ["first"; "second"; "third"] if ISeq.head strSeq <> "first" then Assert.Fail() // Empty ISeq @@ -36,7 +39,7 @@ type ISeqModule2() = CheckThrowsArgumentException ( fun() -> ISeq.head emptySeq) //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () ->ISeq.head nullSeq) () @@ -44,12 +47,12 @@ type ISeqModule2() = member this.TryHead() = // int ISeq let IntSeq = - seq { for i in 0 .. 9 -> i } |> ISeq.ofSeq + iseq <| seq { for i in 0 .. 9 -> i } let intResult = ISeq.tryHead IntSeq // string ISeq - let strResult = ISeq.tryHead (seq ["first"; "second"; "third"] |> ISeq.ofSeq) + let strResult = ISeq.tryHead (iseq ["first"; "second"; "third"]) Assert.AreEqual("first", strResult.Value) // Empty ISeq @@ -57,23 +60,23 @@ type ISeqModule2() = Assert.AreEqual(None, emptyResult) //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () ->ISeq.head nullSeq) () [] member this.Tl() = - // integer seq - let resultInt = ISeq.tail <| (seq { 1..10 } |> ISeq.ofSeq) - Assert.AreEqual(Array.ofSeq (seq { 2..10 } |> ISeq.ofSeq), Array.ofSeq resultInt) + // integer iseq + let resultInt = ISeq.tail <| (iseq <| seq { 1..10 } ) + Assert.AreEqual(Array.ofSeq (iseq <| seq { 2..10 }), Array.ofSeq resultInt) - // string seq - let resultStr = ISeq.tail <| (seq { yield "a"; yield "b"; yield "c"; yield "d" } |> ISeq.ofSeq) - Assert.AreEqual(Array.ofSeq (seq { yield "b"; yield "c" ; yield "d" } |> ISeq.ofSeq), Array.ofSeq resultStr) + // string iseq + let resultStr = ISeq.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 seq - let resultStr2 = ISeq.tail <| (seq { yield "a" } |> ISeq.ofSeq) - Assert.AreEqual(Array.ofSeq (ISeq.empty ), Array.ofSeq resultStr2) + // 1-element iseq + let resultStr2 = ISeq.tail <| (iseq <| seq { yield "a" }) + Assert.AreEqual(Array.ofSeq (ISeq.empty : iseq), Array.ofSeq resultStr2) //CheckThrowsArgumentNullException(fun () -> ISeq.tail null |> ignore) CheckThrowsArgumentException(fun () -> ISeq.tail ISeq.empty |> ISeq.iter (fun _ -> failwith "Should not be reached")) @@ -83,13 +86,13 @@ type ISeqModule2() = member this.Last() = let IntSeq = - seq { for i in 0 .. 9 do - yield i } |> ISeq.ofSeq + iseq <| seq { for i in 0 .. 9 do + yield i } if ISeq.last IntSeq <> 9 then Assert.Fail() // string ISeq - let strSeq = seq ["first"; "second"; "third"] |> ISeq.ofSeq + let strSeq = iseq ["first"; "second"; "third"] if ISeq.last strSeq <> "third" then Assert.Fail() // Empty ISeq @@ -97,7 +100,7 @@ type ISeqModule2() = CheckThrowsArgumentException ( fun() -> ISeq.last emptySeq) //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () ->ISeq.last nullSeq) () @@ -105,13 +108,13 @@ type ISeqModule2() = member this.TryLast() = let IntSeq = - seq { for i in 0 .. 9 -> i } |> ISeq.ofSeq + iseq <| seq { for i in 0 .. 9 -> i } let intResult = ISeq.tryLast IntSeq Assert.AreEqual(9, intResult.Value) // string ISeq - let strResult = ISeq.tryLast (seq ["first"; "second"; "third"] |> ISeq.ofSeq) + let strResult = ISeq.tryLast (iseq ["first"; "second"; "third"]) Assert.AreEqual("third", strResult.Value) // Empty ISeq @@ -119,7 +122,7 @@ type ISeqModule2() = Assert.IsTrue(emptyResult.IsNone) //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () ->ISeq.tryLast nullSeq |> ignore) () @@ -127,13 +130,13 @@ type ISeqModule2() = member this.ExactlyOne() = let IntSeq = - seq { for i in 7 .. 7 do - yield i } |> ISeq.ofSeq + iseq <| seq { for i in 7 .. 7 do + yield i } if ISeq.exactlyOne IntSeq <> 7 then Assert.Fail() // string ISeq - let strSeq = seq ["second"] |> ISeq.ofSeq + let strSeq = iseq ["second"] if ISeq.exactlyOne strSeq <> "second" then Assert.Fail() // Empty ISeq @@ -142,10 +145,10 @@ type ISeqModule2() = // non-singleton ISeq let emptySeq = ISeq.empty - CheckThrowsArgumentException ( fun() -> ISeq.exactlyOne ([ 0 .. 1 ] |> ISeq.ofSeq) |> ignore ) + CheckThrowsArgumentException ( fun() -> ISeq.exactlyOne (iseq [ 0 .. 1 ]) |> ignore ) //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () ->ISeq.exactlyOne nullSeq) () @@ -155,7 +158,7 @@ type ISeqModule2() = let funcInt x = x let init_finiteInt = ISeq.init 9 funcInt - let expectedIntSeq = seq [ 0..8] |> ISeq.ofSeq + let expectedIntSeq = iseq [ 0..8] VerifySeqsEqual expectedIntSeq init_finiteInt @@ -163,16 +166,16 @@ type ISeqModule2() = // string ISeq let funcStr x = x.ToString() let init_finiteStr = ISeq.init 5 funcStr - let expectedStrSeq = seq ["0";"1";"2";"3";"4"] |> ISeq.ofSeq + let expectedStrSeq = iseq ["0";"1";"2";"3";"4"] VerifySeqsEqual expectedStrSeq init_finiteStr - //// null ISeq - //let funcNull x = null - //let init_finiteNull = ISeq.init 3 funcNull - //let expectedNullSeq = seq [ null;null;null] |> ISeq.ofSeq + // null ISeq + let funcNull x = null + let init_finiteNull = ISeq.init 3 funcNull + let expectedNullSeq = iseq [ null;null;null] - //VerifySeqsEqual expectedNullSeq init_finiteNull + VerifySeqsEqual expectedNullSeq init_finiteNull () [] @@ -180,7 +183,7 @@ type ISeqModule2() = let funcInt x = x let init_infiniteInt = ISeq.initInfinite funcInt - let resultint = Seq.find (fun x -> x =100) init_infiniteInt + let resultint = ISeq.find (fun x -> x =100) init_infiniteInt Assert.AreEqual(100,resultint) @@ -188,7 +191,7 @@ type ISeqModule2() = // string ISeq let funcStr x = x.ToString() let init_infiniteStr = ISeq.initInfinite funcStr - let resultstr = Seq.find (fun x -> x = "100") init_infiniteStr + let resultstr = ISeq.find (fun x -> x = "100") init_infiniteStr Assert.AreEqual("100",resultstr) @@ -196,40 +199,40 @@ type ISeqModule2() = [] member this.IsEmpty() = - //seq int - let seqint = seq [1;2;3] |> ISeq.ofSeq - let is_emptyInt = Seq.isEmpty seqint + //iseq int + let seqint = iseq [1;2;3] + let is_emptyInt = ISeq.isEmpty seqint Assert.IsFalse(is_emptyInt) - //seq str - let seqStr = seq["first";"second"] - let is_emptyStr = Seq.isEmpty seqStr + //iseq str + let seqStr = iseq["first";"second"] + let is_emptyStr = ISeq.isEmpty seqStr Assert.IsFalse(is_emptyInt) - //seq empty + //iseq empty let seqEmpty = ISeq.empty - let is_emptyEmpty = Seq.isEmpty seqEmpty + let is_emptyEmpty = ISeq.isEmpty seqEmpty Assert.IsTrue(is_emptyEmpty) - //seq null - let seqnull:seq<'a> = null - CheckThrowsArgumentNullException (fun () -> Seq.isEmpty seqnull |> ignore) + ////iseq null + //let seqnull:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () -> ISeq.isEmpty seqnull |> ignore) () [] member this.Iter() = - //seq int - let seqint = seq [ 1..3] |> ISeq.ofSeq + //iseq int + let seqint = iseq [ 1..3] let cacheint = ref 0 let funcint x = cacheint := !cacheint + x ISeq.iter funcint seqint Assert.AreEqual(6,!cacheint) - //seq str - let seqStr = seq ["first";"second"] |> ISeq.ofSeq + //iseq str + let seqStr = iseq ["first";"second"] let cachestr =ref "" let funcstr x = cachestr := !cachestr+x ISeq.iter funcstr seqStr @@ -241,8 +244,8 @@ type ISeqModule2() = let resultEpt = ref 0 ISeq.iter (fun x -> Assert.Fail()) emptyseq - // null seqay - //let nullseq:seq<'a> = null + //// null seqay + //let nullseq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.iter funcint nullseq |> ignore) () @@ -250,16 +253,16 @@ type ISeqModule2() = [] member this.Iter2() = - //seq int - let seqint = seq [ 1..3] |> ISeq.ofSeq + //iseq int + let seqint = iseq [ 1..3] let cacheint = ref 0 let funcint x y = cacheint := !cacheint + x+y ISeq.iter2 funcint seqint seqint Assert.AreEqual(12,!cacheint) - //seq str - let seqStr = seq ["first";"second"]|> ISeq.ofSeq + //iseq str + let seqStr = iseq ["first";"second"] let cachestr =ref "" let funcstr x y = cachestr := !cachestr+x+y ISeq.iter2 funcstr seqStr seqStr @@ -272,7 +275,7 @@ type ISeqModule2() = ISeq.iter2 (fun x y-> Assert.Fail()) emptyseq emptyseq //// null seqay - //let nullseq:seq<'a> = null + //let nullseq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.iter2 funcint nullseq nullseq |> ignore) () @@ -280,16 +283,16 @@ type ISeqModule2() = [] member this.Iteri() = - // seq int - let seqint = seq [ 1..10] |> ISeq.ofSeq + // iseq int + let seqint = iseq [ 1..10] let cacheint = ref 0 let funcint x y = cacheint := !cacheint + x+y ISeq.iteri funcint seqint Assert.AreEqual(100,!cacheint) - // seq str - let seqStr = seq ["first";"second"]|> ISeq.ofSeq + // iseq str + let seqStr = iseq ["first";"second"] let cachestr =ref 0 let funcstr (x:int) (y:string) = cachestr := !cachestr+ x + y.Length ISeq.iteri funcstr seqStr @@ -303,41 +306,41 @@ type ISeqModule2() = Assert.AreEqual(0,!resultEpt) //// null seqay - //let nullseq:seq<'a> = null + //let nullseq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.iteri funcint nullseq |> ignore) () [] member this.Iteri2() = - //seq int - let seqint = seq [ 1..3] |> ISeq.ofSeq + //iseq int + let seqint = iseq [ 1..3] let cacheint = ref 0 let funcint x y z = cacheint := !cacheint + x + y + z ISeq.iteri2 funcint seqint seqint Assert.AreEqual(15,!cacheint) - //seq str - let seqStr = seq ["first";"second"]|> ISeq.ofSeq + //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 ISeq.iteri2 funcstr seqStr seqStr Assert.AreEqual(23,!cachestr) - // empty seq + // empty iseq let emptyseq = ISeq.empty let resultEpt = ref 0 ISeq.iteri2 (fun x y z -> Assert.Fail()) emptyseq emptyseq - //// null seq - //let nullseq:seq<'a> = null + //// null iseq + //let nullseq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.iteri2 funcint nullseq nullseq |> ignore) // len1 <> len2 - let shorterSeq = seq { 1..3 } |> ISeq.ofSeq - let longerSeq = seq { 2..2..100 } |> ISeq.ofSeq + let shorterSeq = iseq <| seq { 1..3 } + let longerSeq = iseq <| seq { 2..2..100 } let testSeqLengths seq1 seq2 = let cache = ref 0 @@ -353,12 +356,12 @@ type ISeqModule2() = [] member this.Length() = - // integer seq - let resultInt = ISeq.length ({1..8}|> ISeq.ofSeq) + // integer iseq + let resultInt = ISeq.length (iseq {1..8}) if resultInt <> 8 then Assert.Fail() // string ISeq - let resultStr = ISeq.length (seq ["Lists"; "are"; "commonly" ; "list" ]|> ISeq.ofSeq) + let resultStr = ISeq.length (iseq ["Lists"; "are"; "commonly" ; "list" ]) if resultStr <> 4 then Assert.Fail() // empty ISeq @@ -366,7 +369,7 @@ type ISeqModule2() = if resultEpt <> 0 then Assert.Fail() //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.length nullSeq |> ignore) () @@ -380,15 +383,15 @@ type ISeqModule2() = | _ when x % 2 = 0 -> 10*x | _ -> x - let resultInt = ISeq.map funcInt ({ 1..10 }|> ISeq.ofSeq) - let expectedint = seq [1;20;3;40;5;60;7;80;9;100] + let resultInt = ISeq.map funcInt (iseq { 1..10 }) + let expectedint = iseq [1;20;3;40;5;60;7;80;9;100] VerifySeqsEqual expectedint resultInt // string ISeq let funcStr (x:string) = x.ToLower() - let resultStr = ISeq.map funcStr (seq ["Lists"; "Are"; "Commonly" ; "List" ] |> ISeq.ofSeq) - let expectedSeq = seq ["lists"; "are"; "commonly" ; "list"] |> ISeq.ofSeq + let resultStr = ISeq.map funcStr (iseq ["Lists"; "Are"; "Commonly" ; "List" ]) + let expectedSeq = iseq ["lists"; "are"; "commonly" ; "list"] VerifySeqsEqual expectedSeq resultStr @@ -397,7 +400,7 @@ type ISeqModule2() = VerifySeqsEqual ISeq.empty resultEpt //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.map funcStr nullSeq |> ignore) () @@ -406,15 +409,15 @@ type ISeqModule2() = member this.Map2() = // integer ISeq let funcInt x y = x+y - let resultInt = ISeq.map2 funcInt ({ 1..10 }|> ISeq.ofSeq) ( {2..2..20} |> ISeq.ofSeq) - let expectedint = seq [3;6;9;12;15;18;21;24;27;30]|> ISeq.ofSeq + let resultInt = ISeq.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 ISeq let funcStr (x:int) (y:string) = x+y.Length - let resultStr = ISeq.map2 funcStr (seq[3;6;9;11] |> ISeq.ofSeq) (seq ["Lists"; "Are"; "Commonly" ; "List" ] |> ISeq.ofSeq) - let expectedSeq = seq [8;9;17;15] + let resultStr = ISeq.map2 funcStr (iseq[3;6;9;11]) (iseq ["Lists"; "Are"; "Commonly" ; "List" ]) + let expectedSeq = iseq [8;9;17;15] VerifySeqsEqual expectedSeq resultStr @@ -423,40 +426,40 @@ type ISeqModule2() = VerifySeqsEqual ISeq.empty resultEpt //// null ISeq - //let nullSeq:seq<'a> = null - //let validSeq = seq [1] + //let nullSeq:iseq<'a> = null + //let validSeq = iseq [1] //CheckThrowsArgumentNullException (fun () -> ISeq.map2 funcInt nullSeq validSeq |> ignore) () [] member this.Map3() = - // Integer seq + // Integer iseq let funcInt a b c = (a + b) * c - let resultInt = ISeq.map3 funcInt ({ 1..8 }|> ISeq.ofSeq)( { 2..9 }|> ISeq.ofSeq)( { 3..10 }|> ISeq.ofSeq) - let expectedInt = seq [9; 20; 35; 54; 77; 104; 135; 170] + let resultInt = ISeq.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 seq is shorter - VerifySeqsEqual (seq [9; 20]) (ISeq.map3 funcInt ({ 1..2 }|> ISeq.ofSeq)( { 2..9 }|> ISeq.ofSeq)( { 3..10 }|> ISeq.ofSeq)) - // Second seq is shorter - VerifySeqsEqual (seq [9; 20; 35]) (ISeq.map3 funcInt ({ 1..8 }|> ISeq.ofSeq)( { 2..4 }|> ISeq.ofSeq)( { 3..10 }|> ISeq.ofSeq)) - // Third seq is shorter - VerifySeqsEqual (seq [9; 20; 35; 54]) (ISeq.map3 funcInt ({ 1..8 }|> ISeq.ofSeq) ( { 2..6 }|> ISeq.ofSeq)( { 3..6 }|> ISeq.ofSeq)) + // First iseq is shorter + VerifySeqsEqual (iseq [9; 20]) (ISeq.map3 funcInt (iseq { 1..2 }) (iseq { 2..9 }) (iseq { 3..10 })) + // Second iseq is shorter + VerifySeqsEqual (iseq [9; 20; 35]) (ISeq.map3 funcInt (iseq { 1..8 }) (iseq { 2..4 }) (iseq { 3..10 })) + // Third iseq is shorter + VerifySeqsEqual (iseq [9; 20; 35; 54]) (ISeq.map3 funcInt (iseq { 1..8 }) (iseq { 2..6 }) (iseq { 3..6 })) - // String seq + // String iseq let funcStr a b c = a + b + c - let resultStr = ISeq.map3 funcStr (["A";"B";"C";"D"]|> ISeq.ofSeq) ( ["a";"b";"c";"d"]|> ISeq.ofSeq)( ["1";"2";"3";"4"]|> ISeq.ofSeq) - let expectedStr = seq ["Aa1";"Bb2";"Cc3";"Dd4"]|> ISeq.ofSeq + let resultStr = ISeq.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 seq + // Empty iseq let resultEmpty = ISeq.map3 funcStr ISeq.empty ISeq.empty ISeq.empty VerifySeqsEqual ISeq.empty resultEmpty - //// Null seq - //let nullSeq = null : seq<_> - //let nonNullSeq = seq [1] + //// Null iseq + //let nullSeq = null : iseq<_> + //let nonNullSeq = iseq [1] //CheckThrowsArgumentNullException (fun () -> ISeq.map3 funcInt nullSeq nonNullSeq nullSeq |> ignore) () @@ -465,24 +468,24 @@ type ISeqModule2() = member this.MapFold() = // integer ISeq let funcInt acc x = if x % 2 = 0 then 10*x, acc + 1 else x, acc - let resultInt,resultIntAcc = Seq.mapFold funcInt 100 <| seq { 1..10 } - VerifySeqsEqual (seq [ 1;20;3;40;5;60;7;80;9;100 ]) resultInt + let resultInt,resultIntAcc = ISeq.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 ISeq let funcStr acc (x:string) = match x.Length with 0 -> "empty", acc | _ -> x.ToLower(), sprintf "%s%s" acc x - let resultStr,resultStrAcc = Seq.mapFold funcStr "" <| seq [ "";"BB";"C";"" ] - VerifySeqsEqual (seq [ "empty";"bb";"c";"empty" ]) resultStr + let resultStr,resultStrAcc = ISeq.mapFold funcStr "" <| iseq [ "";"BB";"C";"" ] + VerifySeqsEqual (iseq [ "empty";"bb";"c";"empty" ]) resultStr Assert.AreEqual("BBC", resultStrAcc) // empty ISeq - let resultEpt,resultEptAcc = Seq.mapFold funcInt 100 ISeq.empty + let resultEpt,resultEptAcc = ISeq.mapFold funcInt 100 ISeq.empty VerifySeqsEqual ISeq.empty resultEpt Assert.AreEqual(100, resultEptAcc) //// null ISeq - //let nullArr = null:seq - //CheckThrowsArgumentNullException (fun () -> Seq.mapFold funcStr "" nullArr |> ignore) + //let nullArr = null:iseq + //CheckThrowsArgumentNullException (fun () -> ISeq.mapFold funcStr "" nullArr |> ignore) () @@ -490,31 +493,31 @@ type ISeqModule2() = member this.MapFoldBack() = // integer ISeq let funcInt x acc = if acc < 105 then 10*x, acc + 2 else x, acc - let resultInt,resultIntAcc = Seq.mapFoldBack funcInt (seq { 1..10 }) 100 - VerifySeqsEqual (seq [ 1;2;3;4;5;6;7;80;90;100 ]) resultInt + let resultInt,resultIntAcc = ISeq.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 ISeq let funcStr (x:string) acc = match x.Length with 0 -> "empty", acc | _ -> x.ToLower(), sprintf "%s%s" acc x - let resultStr,resultStrAcc = Seq.mapFoldBack funcStr (seq [ "";"BB";"C";"" ]) "" - VerifySeqsEqual (seq [ "empty";"bb";"c";"empty" ]) resultStr + let resultStr,resultStrAcc = ISeq.mapFoldBack funcStr (iseq [ "";"BB";"C";"" ]) "" + VerifySeqsEqual (iseq [ "empty";"bb";"c";"empty" ]) resultStr Assert.AreEqual("CBB", resultStrAcc) // empty ISeq - let resultEpt,resultEptAcc = Seq.mapFoldBack funcInt ISeq.empty 100 + let resultEpt,resultEptAcc = ISeq.mapFoldBack funcInt ISeq.empty 100 VerifySeqsEqual ISeq.empty resultEpt Assert.AreEqual(100, resultEptAcc) //// null ISeq - //let nullArr = null:seq - //CheckThrowsArgumentNullException (fun () -> Seq.mapFoldBack funcStr nullArr "" |> ignore) + //let nullArr = null:iseq + //CheckThrowsArgumentNullException (fun () -> ISeq.mapFoldBack funcStr nullArr "" |> ignore) () - member private this.MapWithSideEffectsTester (map : (int -> int) -> ISeq.Core.ISeq -> ISeq.Core.ISeq) expectExceptions = + member private this.MapWithSideEffectsTester (map : (int -> int) -> iseq -> iseq) expectExceptions = let i = ref 0 let f x = i := !i + 1; x*x - let e = (([1;2]|>ISeq.ofSeq) |> map f).GetEnumerator() + let e = ((iseq [1;2]) |> map f).GetEnumerator() if expectExceptions then CheckThrowsInvalidOperationExn (fun _ -> e.Current|>ignore) @@ -541,16 +544,16 @@ type ISeqModule2() = i := 0 - let e = (([]|> ISeq.ofSeq) |> map f).GetEnumerator() + 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.Core.ISeq -> ISeq.Core.ISeq) = + member private this.MapWithExceptionTester (map : (int -> int) -> iseq -> iseq) = let raiser x = if x > 0 then raise(NotSupportedException()) else x - let e = (map raiser ([0; 1]|> ISeq.ofSeq)).GetEnumerator() + 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) @@ -565,29 +568,29 @@ type ISeqModule2() = this.MapWithExceptionTester ISeq.map - //[] - //member this.SingletonCollectWithSideEffects () = - // this.MapWithSideEffectsTester (fun f-> Seq.collect (f >> Seq.singleton)) true + [] + member this.SingletonCollectWithSideEffects () = + this.MapWithSideEffectsTester (fun f-> ISeq.collect (f >> ISeq.singleton)) true - //[] - //member this.SingletonCollectWithException () = - // this.MapWithExceptionTester (fun f-> Seq.collect (f >> Seq.singleton)) + [] + member this.SingletonCollectWithException () = + this.MapWithExceptionTester (fun f-> ISeq.collect (f >> ISeq.singleton)) -//#if !FX_NO_LINQ -// [] -// member this.SystemLinqSelectWithSideEffects () = -// this.MapWithSideEffectsTester (fun f s -> System.Linq.Enumerable.Select(s, Func<_,_>(f))) false +#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 -> System.Linq.Enumerable.Select(s, Func<_,_>(f))) -//#endif + [] + 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 = (([1;2]|> ISeq.ofSeq) |> ISeq.mapi f).GetEnumerator() + let e = ((iseq [1;2]) |> ISeq.mapi f).GetEnumerator() CheckThrowsInvalidOperationExn (fun _ -> e.Current|>ignore) Assert.AreEqual(0, !i) @@ -611,7 +614,7 @@ type ISeqModule2() = Assert.AreEqual(2, !i) i := 0 - let e = (([]|> ISeq.ofSeq) |> ISeq.mapi f).GetEnumerator() + let e = ((iseq []) |> ISeq.mapi f).GetEnumerator() if e.MoveNext() then Assert.Fail() Assert.AreEqual(0,!i) if e.MoveNext() then Assert.Fail() @@ -621,7 +624,7 @@ type ISeqModule2() = member this.Map2WithSideEffects () = let i = ref 0 let f x y = i := !i + 1; x*x - let e = (ISeq.map2 f ([1;2]|> ISeq.ofSeq) ([1;2]|> ISeq.ofSeq)).GetEnumerator() + let e = (ISeq.map2 f (iseq [1;2]) (iseq [1;2])).GetEnumerator() CheckThrowsInvalidOperationExn (fun _ -> e.Current|>ignore) Assert.AreEqual(0, !i) @@ -645,7 +648,7 @@ type ISeqModule2() = Assert.AreEqual(2, !i) i := 0 - let e = (ISeq.map2 f ([]|> ISeq.ofSeq) ([]|> ISeq.ofSeq)).GetEnumerator() + let e = (ISeq.map2 f (iseq []) (iseq [])).GetEnumerator() if e.MoveNext() then Assert.Fail() Assert.AreEqual(0,!i) if e.MoveNext() then Assert.Fail() @@ -655,7 +658,7 @@ type ISeqModule2() = member this.Mapi2WithSideEffects () = let i = ref 0 let f _ x y = i := !i + 1; x*x - let e = (ISeq.mapi2 f ([1;2]|> ISeq.ofSeq) ([1;2]|> ISeq.ofSeq)).GetEnumerator() + let e = (ISeq.mapi2 f (iseq [1;2]) (iseq [1;2])).GetEnumerator() CheckThrowsInvalidOperationExn (fun _ -> e.Current|>ignore) Assert.AreEqual(0, !i) @@ -679,7 +682,7 @@ type ISeqModule2() = Assert.AreEqual(2, !i) i := 0 - let e = (ISeq.mapi2 f ([]|> ISeq.ofSeq) ([]|> ISeq.ofSeq)).GetEnumerator() + let e = (ISeq.mapi2 f (iseq []) (iseq [])).GetEnumerator() if e.MoveNext() then Assert.Fail() Assert.AreEqual(0,!i) if e.MoveNext() then Assert.Fail() @@ -688,32 +691,32 @@ type ISeqModule2() = [] member this.Collect() = // integer ISeq - let funcInt x = seq [x+1] - let resultInt = Seq.collect funcInt { 1..10 } + let funcInt x = iseq [x+1] + let resultInt = ISeq.collect funcInt (iseq { 1..10 }) - let expectedint = seq {2..11} + let expectedint = iseq <| seq {2..11} VerifySeqsEqual expectedint resultInt -#if !FX_NO_CHAR_PARSE - // string ISeq - let funcStr (y:string) = y+"ist" +//#if !FX_NO_CHAR_PARSE +// // string ISeq +// let funcStr (y:string) = y+"ist" - let resultStr = Seq.collect funcStr (seq ["L"]) +// let resultStr = ISeq.collect funcStr (iseq ["L"]) - let expectedSeq = seq ['L';'i';'s';'t'] +// let expectedSeq = iseq ['L';'i';'s';'t'] - VerifySeqsEqual expectedSeq resultStr -#endif +// VerifySeqsEqual expectedSeq resultStr +//#endif // empty ISeq - let resultEpt = Seq.collect funcInt ISeq.empty + let resultEpt = ISeq.collect funcInt ISeq.empty VerifySeqsEqual ISeq.empty resultEpt //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null - //CheckThrowsArgumentNullException (fun () -> Seq.collect funcInt nullSeq |> ignore) + //CheckThrowsArgumentNullException (fun () -> ISeq.collect funcInt nullSeq |> ignore) () @@ -722,16 +725,16 @@ type ISeqModule2() = // integer ISeq let funcInt x y = x+y - let resultInt = ISeq.mapi funcInt ({ 10..2..20 } |> ISeq.ofSeq) - let expectedint = seq [10;13;16;19;22;25] + let resultInt = ISeq.mapi funcInt (iseq { 10..2..20 } ) + let expectedint = iseq [10;13;16;19;22;25] VerifySeqsEqual expectedint resultInt // string ISeq let funcStr (x:int) (y:string) =x+y.Length - let resultStr = ISeq.mapi funcStr (seq ["Lists"; "Are"; "Commonly" ; "List" ] |> ISeq.ofSeq) - let expectedStr = seq [5;4;10;7] + let resultStr = ISeq.mapi funcStr (iseq ["Lists"; "Are"; "Commonly" ; "List" ]) + let expectedStr = iseq [5;4;10;7] VerifySeqsEqual expectedStr resultStr @@ -740,7 +743,7 @@ type ISeqModule2() = VerifySeqsEqual ISeq.empty resultEpt //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.mapi funcInt nullSeq |> ignore) @@ -750,15 +753,15 @@ type ISeqModule2() = member this.Mapi2() = // integer ISeq let funcInt x y z = x+y+z - let resultInt = ISeq.mapi2 funcInt ({ 1..10 }|> ISeq.ofSeq)( {2..2..20}|> ISeq.ofSeq) - let expectedint = seq [3;7;11;15;19;23;27;31;35;39] + let resultInt = ISeq.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 ISeq let funcStr (x:int) (y:int) (z:string) = x+y+z.Length - let resultStr = ISeq.mapi2 funcStr (seq[3;6;9;11]|> ISeq.ofSeq) (seq ["Lists"; "Are"; "Commonly" ; "List" ]|> ISeq.ofSeq) - let expectedSeq = seq [8;10;19;18] + let resultStr = ISeq.mapi2 funcStr (iseq[3;6;9;11]) (iseq ["Lists"; "Are"; "Commonly" ; "List" ]) + let expectedSeq = iseq [8;10;19;18] VerifySeqsEqual expectedSeq resultStr @@ -767,33 +770,33 @@ type ISeqModule2() = VerifySeqsEqual ISeq.empty resultEpt //// null ISeq - //let nullSeq:seq<'a> = null - //let validSeq = seq [1] + //let nullSeq:iseq<'a> = null + //let validSeq = iseq [1] //CheckThrowsArgumentNullException (fun () -> ISeq.mapi2 funcInt nullSeq validSeq |> ignore) // len1 <> len2 - let shorterSeq = seq { 1..10 }|> ISeq.ofSeq - let longerSeq = seq { 2..20 }|> ISeq.ofSeq + let shorterSeq = iseq <| seq { 1..10 } + let longerSeq = iseq <| seq { 2..20 } let testSeqLengths seq1 seq2 = let f x y z = x + y + z ISeq.mapi2 f seq1 seq2 - VerifySeqsEqual (seq [3;6;9;12;15;18;21;24;27;30]|> ISeq.ofSeq) (testSeqLengths shorterSeq longerSeq) - VerifySeqsEqual (seq [3;6;9;12;15;18;21;24;27;30]|> ISeq.ofSeq) (testSeqLengths longerSeq shorterSeq) + 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 ISeq - let resultInt = ISeq.indexed ({ 10..2..20 }|> ISeq.ofSeq) - let expectedint = seq [(0,10);(1,12);(2,14);(3,16);(4,18);(5,20)]|> ISeq.ofSeq + let resultInt = ISeq.indexed (iseq { 10..2..20 }) + let expectedint = iseq [(0,10);(1,12);(2,14);(3,16);(4,18);(5,20)] VerifySeqsEqual expectedint resultInt // string ISeq - let resultStr = ISeq.indexed (seq ["Lists"; "Are"; "Commonly"; "List" ]|> ISeq.ofSeq) - let expectedStr = seq [(0,"Lists");(1,"Are");(2,"Commonly");(3,"List")]|> ISeq.ofSeq + let resultStr = ISeq.indexed (iseq ["Lists"; "Are"; "Commonly"; "List" ]) + let expectedStr = iseq [(0,"Lists");(1,"Are");(2,"Commonly");(3,"List")] VerifySeqsEqual expectedStr resultStr @@ -802,7 +805,7 @@ type ISeqModule2() = VerifySeqsEqual ISeq.empty resultEpt //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.indexed nullSeq |> ignore) () @@ -810,20 +813,20 @@ type ISeqModule2() = [] member this.Max() = // integer ISeq - let resultInt = ISeq.max ({ 10..20 } |> ISeq.ofSeq) + let resultInt = ISeq.max (iseq { 10..20 } ) Assert.AreEqual(20,resultInt) // string ISeq - let resultStr = ISeq.max (seq ["Lists"; "Are"; "MaxString" ; "List" ]|> ISeq.ofSeq) + let resultStr = ISeq.max (iseq ["Lists"; "Are"; "MaxString" ; "List" ]) Assert.AreEqual("MaxString",resultStr) // empty ISeq - CheckThrowsArgumentException(fun () -> ISeq.max ( ISeq.empty ) |> ignore) + CheckThrowsArgumentException(fun () -> ISeq.max ( ISeq.empty : iseq) |> ignore) //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.max nullSeq |> ignore) () @@ -833,19 +836,19 @@ type ISeqModule2() = // integer ISeq let funcInt x = x % 8 - let resultInt = ISeq.maxBy funcInt ({ 2..2..20 } |> ISeq.ofSeq) + let resultInt = ISeq.maxBy funcInt (iseq { 2..2..20 } ) Assert.AreEqual(6,resultInt) // string ISeq let funcStr (x:string) =x.Length - let resultStr = ISeq.maxBy funcStr (seq ["Lists"; "Are"; "Commonly" ; "List" ]|> ISeq.ofSeq) + let resultStr = ISeq.maxBy funcStr (iseq ["Lists"; "Are"; "Commonly" ; "List" ]) Assert.AreEqual("Commonly",resultStr) // empty ISeq - CheckThrowsArgumentException (fun () -> ISeq.maxBy funcInt (ISeq.empty ) |> ignore) + CheckThrowsArgumentException (fun () -> ISeq.maxBy funcInt (ISeq.empty : iseq) |> ignore) //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () ->ISeq.maxBy funcInt nullSeq |> ignore) () @@ -855,19 +858,19 @@ type ISeqModule2() = // integer ISeq let funcInt x = x % 8 - let resultInt = ISeq.minBy funcInt ({ 2..2..20 } |> ISeq.ofSeq) + let resultInt = ISeq.minBy funcInt (iseq { 2..2..20 } ) Assert.AreEqual(8,resultInt) // string ISeq let funcStr (x:string) =x.Length - let resultStr = ISeq.minBy funcStr (seq ["Lists"; "Are"; "Commonly" ; "List" ]|> ISeq.ofSeq) + let resultStr = ISeq.minBy funcStr (iseq ["Lists"; "Are"; "Commonly" ; "List" ]) Assert.AreEqual("Are",resultStr) // empty ISeq - CheckThrowsArgumentException (fun () -> ISeq.minBy funcInt (ISeq.empty ) |> ignore) + CheckThrowsArgumentException (fun () -> ISeq.minBy funcInt (ISeq.empty : iseq) |> ignore) //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () ->ISeq.minBy funcInt nullSeq |> ignore) () @@ -877,18 +880,18 @@ type ISeqModule2() = member this.Min() = // integer ISeq - let resultInt = ISeq.min ({ 10..20 } |> ISeq.ofSeq) + let resultInt = ISeq.min (iseq { 10..20 } ) Assert.AreEqual(10,resultInt) // string ISeq - let resultStr = ISeq.min (seq ["Lists"; "Are"; "minString" ; "List" ]|> ISeq.ofSeq) + let resultStr = ISeq.min (iseq ["Lists"; "Are"; "minString" ; "List" ]) Assert.AreEqual("Are",resultStr) // empty ISeq - CheckThrowsArgumentException (fun () -> ISeq.min (ISeq.empty ) |> ignore) + CheckThrowsArgumentException (fun () -> ISeq.min (ISeq.empty : iseq) |> ignore) //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.min nullSeq |> ignore) () @@ -896,41 +899,41 @@ type ISeqModule2() = [] member this.Item() = // integer ISeq - let resultInt = Seq.item 3 ({ 10..20 }|> ISeq.ofSeq) + let resultInt = ISeq.item 3 (iseq { 10..20 }) Assert.AreEqual(13, resultInt) // string ISeq - let resultStr = Seq.item 2 (seq ["Lists"; "Are"; "Cool" ; "List" ]|> ISeq.ofSeq) + let resultStr = ISeq.item 2 (iseq ["Lists"; "Are"; "Cool" ; "List" ]) Assert.AreEqual("Cool", resultStr) // empty ISeq - CheckThrowsArgumentException(fun () -> Seq.item 0 (ISeq.empty ) |> ignore) + CheckThrowsArgumentException(fun () -> ISeq.item 0 (ISeq.empty : iseq) |> ignore) //// null ISeq - //let nullSeq:seq<'a> = null - //CheckThrowsArgumentNullException (fun () ->Seq.item 3 nullSeq |> ignore) + //let nullSeq:iseq<'a> = null + //CheckThrowsArgumentNullException (fun () ->ISeq.item 3 nullSeq |> ignore) // Negative index for i = -1 downto -10 do - CheckThrowsArgumentException (fun () -> Seq.item i { 10 .. 20 } |> ignore) + CheckThrowsArgumentException (fun () -> ISeq.item i (iseq { 10 .. 20 }) |> ignore) // Out of range for i = 11 to 20 do - CheckThrowsArgumentException (fun () -> Seq.item i { 10 .. 20 } |> ignore) + CheckThrowsArgumentException (fun () -> ISeq.item i (iseq { 10 .. 20 }) |> ignore) [] member this.``item should fail with correct number of missing elements``() = try - Seq.item 0 (Array.zeroCreate 0) |> ignore + ISeq.item 0 (iseq (Array.zeroCreate 0)) |> ignore failwith "error expected" with - | exn when exn.Message.Contains("seq was short by 1 element") -> () + | exn when exn.Message.Contains("iseq was short by 1 element") -> () try - Seq.item 2 (Array.zeroCreate 0) |> ignore + ISeq.item 2 (iseq (Array.zeroCreate 0)) |> ignore failwith "error expected" with - | exn when exn.Message.Contains("seq was short by 3 elements") -> () + | exn when exn.Message.Contains("iseq was short by 3 elements") -> () [] member this.Of_Array() = @@ -942,7 +945,7 @@ type ISeqModule2() = // string ISeq let resultStr = ISeq.ofArray [|"Lists"; "Are"; "ofArrayString" ; "List" |] - let expectedStr = seq ["Lists"; "Are"; "ofArrayString" ; "List" ] + let expectedStr = iseq ["Lists"; "Are"; "ofArrayString" ; "List" ] VerifySeqsEqual expectedStr resultStr // empty ISeq @@ -962,7 +965,7 @@ type ISeqModule2() = // string ISeq let resultStr =ISeq.ofList ["Lists"; "Are"; "ofListString" ; "List" ] - let expectedStr = seq ["Lists"; "Are"; "ofListString" ; "List" ] + let expectedStr = iseq ["Lists"; "Are"; "ofListString" ; "List" ] VerifySeqsEqual expectedStr resultStr // empty ISeq @@ -974,19 +977,19 @@ type ISeqModule2() = [] member this.Pairwise() = // integer ISeq - let resultInt = ISeq.pairwise ({1..3}|>ISeq.ofSeq) + let resultInt = ISeq.pairwise (iseq {1..3}) - let expectedInt = seq [1,2;2,3] + let expectedInt = iseq [1,2;2,3] VerifySeqsEqual expectedInt resultInt // string ISeq - let resultStr =ISeq.pairwise (["str1"; "str2";"str3" ]|>ISeq.ofSeq) - let expectedStr = seq ["str1","str2";"str2","str3"]|>ISeq.ofSeq + let resultStr =ISeq.pairwise (iseq ["str1"; "str2";"str3" ]) + let expectedStr = iseq ["str1","str2";"str2","str3"] VerifySeqsEqual expectedStr resultStr // empty ISeq - let resultEpt = ISeq.pairwise ([] |>ISeq.ofSeq) + let resultEpt = ISeq.pairwise (iseq [] ) VerifySeqsEqual resultEpt ISeq.empty () @@ -995,18 +998,18 @@ type ISeqModule2() = member this.Reduce() = // integer ISeq - let resultInt = ISeq.reduce (fun x y -> x/y) (seq [5*4*3*2; 4;3;2;1] |> ISeq.ofSeq) + let resultInt = ISeq.reduce (fun x y -> x/y) (iseq [5*4*3*2; 4;3;2;1]) Assert.AreEqual(5,resultInt) // string ISeq - let resultStr = ISeq.reduce (fun (x:string) (y:string) -> x.Remove(0,y.Length)) (seq ["ABCDE";"A"; "B"; "C" ; "D" ] |> ISeq.ofSeq) + let resultStr = ISeq.reduce (fun (x:string) (y:string) -> x.Remove(0,y.Length)) (iseq ["ABCDE";"A"; "B"; "C" ; "D" ]) Assert.AreEqual("E",resultStr) // empty ISeq CheckThrowsArgumentException (fun () -> ISeq.reduce (fun x y -> x/y) ISeq.empty |> ignore) //// null ISeq - //let nullSeq : seq<'a> = null + //let nullSeq : iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.reduce (fun (x:string) (y:string) -> x.Remove(0,y.Length)) nullSeq |> ignore) () @@ -1014,19 +1017,19 @@ type ISeqModule2() = member this.ReduceBack() = // int ISeq let funcInt x y = x - y - let IntSeq = seq { 1..4 } |> ISeq.ofSeq + let IntSeq = iseq <| seq { 1..4 } let reduceInt = ISeq.reduceBack funcInt IntSeq Assert.AreEqual((1-(2-(3-4))), reduceInt) // string ISeq let funcStr (x:string) (y:string) = y.Remove(0,x.Length) - let strSeq = seq [ "A"; "B"; "C"; "D" ; "ABCDE" ] |> ISeq.ofSeq + let strSeq = iseq [ "A"; "B"; "C"; "D" ; "ABCDE" ] let reduceStr = ISeq.reduceBack funcStr strSeq Assert.AreEqual("E", reduceStr) // string ISeq let funcStr2 elem acc = sprintf "%s%s" elem acc - let strSeq2 = seq [ "A" ] |> ISeq.ofSeq + let strSeq2 = iseq [ "A" ] let reduceStr2 = ISeq.reduceBack funcStr2 strSeq2 Assert.AreEqual("A", reduceStr2) @@ -1034,7 +1037,7 @@ type ISeqModule2() = CheckThrowsArgumentException (fun () -> ISeq.reduceBack funcInt ISeq.empty |> ignore) //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.reduceBack funcInt nullSeq |> ignore) () @@ -1042,18 +1045,18 @@ type ISeqModule2() = [] member this.Rev() = // integer ISeq - let resultInt = ISeq.rev (seq [5;4;3;2;1] |> ISeq.ofSeq) - VerifySeqsEqual (seq[1;2;3;4;5]) resultInt + let resultInt = ISeq.rev (iseq [5;4;3;2;1]) + VerifySeqsEqual (iseq[1;2;3;4;5]) resultInt // string ISeq - let resultStr = ISeq.rev (seq ["A"; "B"; "C" ; "D" ] |> ISeq.ofSeq) - VerifySeqsEqual (seq["D";"C";"B";"A"]) resultStr + let resultStr = ISeq.rev (iseq ["A"; "B"; "C" ; "D" ]) + VerifySeqsEqual (iseq["D";"C";"B";"A"]) resultStr // empty ISeq VerifySeqsEqual ISeq.empty (ISeq.rev ISeq.empty) //// null ISeq - //let nullSeq : seq<'a> = null + //let nullSeq : iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.rev nullSeq |> ignore) () @@ -1061,24 +1064,24 @@ type ISeqModule2() = member this.Scan() = // integer ISeq let funcInt x y = x+y - let resultInt = ISeq.scan funcInt 9 ({1..10}|> ISeq.ofSeq) - let expectedInt = seq [9;10;12;15;19;24;30;37;45;54;64] |> ISeq.ofSeq + let resultInt = ISeq.scan funcInt 9 (iseq {1..10}) + let expectedInt = iseq [9;10;12;15;19;24;30;37;45;54;64] VerifySeqsEqual expectedInt resultInt // string ISeq let funcStr x y = x+y - let resultStr =ISeq.scan funcStr "x" (["str1"; "str2";"str3" ]|> ISeq.ofSeq) + let resultStr =ISeq.scan funcStr "x" (iseq ["str1"; "str2";"str3" ]) - let expectedStr = seq ["x";"xstr1"; "xstr1str2";"xstr1str2str3"]|> ISeq.ofSeq + let expectedStr = iseq ["x";"xstr1"; "xstr1str2";"xstr1str2str3"] VerifySeqsEqual expectedStr resultStr // empty ISeq let resultEpt = ISeq.scan funcInt 5 ISeq.empty - VerifySeqsEqual resultEpt (seq [ 5]) + VerifySeqsEqual resultEpt (iseq [ 5]) //// null ISeq - //let seqNull:seq<'a> = null + //let seqNull:iseq<'a> = null //CheckThrowsArgumentNullException(fun() -> ISeq.scan funcInt 5 seqNull |> ignore) () @@ -1086,36 +1089,36 @@ type ISeqModule2() = member this.ScanBack() = // integer ISeq let funcInt x y = x+y - let resultInt = ISeq.scanBack funcInt ({ 1..10 }|> ISeq.ofSeq) 9 - let expectedInt = seq [64;63;61;58;54;49;43;36;28;19;9] + let resultInt = ISeq.scanBack funcInt (iseq { 1..10 }) 9 + let expectedInt = iseq [64;63;61;58;54;49;43;36;28;19;9] VerifySeqsEqual expectedInt resultInt // string ISeq let funcStr x y = x+y - let resultStr = ISeq.scanBack funcStr (seq ["A";"B";"C";"D"]|> ISeq.ofSeq) "X" - let expectedStr = seq ["ABCDX";"BCDX";"CDX";"DX";"X"]|> ISeq.ofSeq + let resultStr = ISeq.scanBack funcStr (iseq ["A";"B";"C";"D"]) "X" + let expectedStr = iseq ["ABCDX";"BCDX";"CDX";"DX";"X"] VerifySeqsEqual expectedStr resultStr // empty ISeq let resultEpt = ISeq.scanBack funcInt ISeq.empty 5 - let expectedEpt = seq [5] + let expectedEpt = iseq [5] VerifySeqsEqual expectedEpt resultEpt //// null ISeq - //let seqNull:seq<'a> = null + //let seqNull:iseq<'a> = null //CheckThrowsArgumentNullException(fun() -> ISeq.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 = ISeq.scanBack funcEx (seq {1..10} |> ISeq.ofSeq) 0 + let resultEx = ISeq.scanBack funcEx (iseq <| seq {1..10}) 0 // reading from resultEx throws CheckThrowsFormatException(fun() -> ISeq.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 = ISeq.scanBack funcState (seq {1..3} |> ISeq.ofSeq) 0 + let resultState = ISeq.scanBack funcState (iseq <| seq {1..3}) 0 Assert.AreEqual(0, !i) use e = resultState.GetEnumerator() Assert.AreEqual(6, !i) @@ -1125,20 +1128,20 @@ type ISeqModule2() = [] member this.Singleton() = // integer ISeq - let resultInt = Seq.singleton 1 + let resultInt = ISeq.singleton 1 - let expectedInt = seq [1] |> ISeq.ofSeq + let expectedInt = iseq [1] VerifySeqsEqual expectedInt resultInt // string ISeq - let resultStr =Seq.singleton "str1" - let expectedStr = seq ["str1"] |> ISeq.ofSeq + let resultStr =ISeq.singleton "str1" + let expectedStr = iseq ["str1"] VerifySeqsEqual expectedStr resultStr - //// null ISeq - //let resultNull = Seq.singleton null - //let expectedNull = seq [null] - //VerifySeqsEqual expectedNull resultNull + // null ISeq + let resultNull = ISeq.singleton null + let expectedNull = iseq [null] + VerifySeqsEqual expectedNull resultNull () @@ -1146,13 +1149,13 @@ type ISeqModule2() = member this.Skip() = // integer ISeq - let resultInt = ISeq.skip 2 (seq [1;2;3;4] |> ISeq.ofSeq) - let expectedInt = seq [3;4] |> ISeq.ofSeq + let resultInt = ISeq.skip 2 (iseq [1;2;3;4]) + let expectedInt = iseq [3;4] VerifySeqsEqual expectedInt resultInt // string ISeq - let resultStr =ISeq.skip 2 (seq ["str1";"str2";"str3";"str4"] |> ISeq.ofSeq) - let expectedStr = seq ["str3";"str4"] |> ISeq.ofSeq + let resultStr =ISeq.skip 2 (iseq ["str1";"str2";"str3";"str4"]) + let expectedStr = iseq ["str3";"str4"] VerifySeqsEqual expectedStr resultStr // empty ISeq @@ -1169,14 +1172,14 @@ type ISeqModule2() = // integer ISeq let funcInt x = (x < 3) - let resultInt = ISeq.skipWhile funcInt (seq [1;2;3;4;5;6] |> ISeq.ofSeq) - let expectedInt = seq [3;4;5;6] |> ISeq.ofSeq + let resultInt = ISeq.skipWhile funcInt (iseq [1;2;3;4;5;6]) + let expectedInt = iseq [3;4;5;6] VerifySeqsEqual expectedInt resultInt // string ISeq let funcStr (x:string) = x.Contains(".") - let resultStr =ISeq.skipWhile funcStr (seq [".";"asdfasdf.asdfasdf";"";"";"";"";"";"";"";"";""] |> ISeq.ofSeq) - let expectedStr = seq ["";"";"";"";"";"";"";"";""] |> ISeq.ofSeq + let resultStr =ISeq.skipWhile funcStr (iseq [".";"asdfasdf.asdfasdf";"";"";"";"";"";"";"";"";""]) + let expectedStr = iseq ["";"";"";"";"";"";"";"";""] VerifySeqsEqual expectedStr resultStr // empty ISeq @@ -1191,14 +1194,14 @@ type ISeqModule2() = member this.Sort() = // integer ISeq - let resultInt = ISeq.sort (seq [1;3;2;4;6;5;7] |> ISeq.ofSeq) - let expectedInt = {1..7} |> ISeq.ofSeq + let resultInt = ISeq.sort (iseq [1;3;2;4;6;5;7]) + let expectedInt = {1..7} VerifySeqsEqual expectedInt resultInt // string ISeq - let resultStr =ISeq.sort (seq ["str1";"str3";"str2";"str4"] |> ISeq.ofSeq) - let expectedStr = seq ["str1";"str2";"str3";"str4"] |> ISeq.ofSeq + let resultStr =ISeq.sort (iseq ["str1";"str3";"str2";"str4"]) + let expectedStr = iseq ["str1";"str2";"str3";"str4"] VerifySeqsEqual expectedStr resultStr // empty ISeq @@ -1214,15 +1217,15 @@ type ISeqModule2() = // integer ISeq let funcInt x = Math.Abs(x-5) - let resultInt = ISeq.sortBy funcInt (seq [1;2;4;5;7] |> ISeq.ofSeq) - let expectedInt = seq [5;4;7;2;1] |> ISeq.ofSeq + let resultInt = ISeq.sortBy funcInt (iseq [1;2;4;5;7]) + let expectedInt = iseq [5;4;7;2;1] VerifySeqsEqual expectedInt resultInt // string ISeq let funcStr (x:string) = x.IndexOf("key") - let resultStr =ISeq.sortBy funcStr (seq ["st(key)r";"str(key)";"s(key)tr";"(key)str"] |> ISeq.ofSeq) + let resultStr =ISeq.sortBy funcStr (iseq ["st(key)r";"str(key)";"s(key)tr";"(key)str"]) - let expectedStr = seq ["(key)str";"s(key)tr";"st(key)r";"str(key)"] |> ISeq.ofSeq + let expectedStr = iseq ["(key)str";"s(key)tr";"st(key)r";"str(key)"] VerifySeqsEqual expectedStr resultStr // empty ISeq @@ -1237,35 +1240,35 @@ type ISeqModule2() = member this.SortDescending() = // integer ISeq - let resultInt = Seq.sortDescending (seq [1;3;2;Int32.MaxValue;4;6;Int32.MinValue;5;7;0]) - let expectedInt = seq{ + let resultInt = ISeq.sortDescending (iseq [1;3;2;Int32.MaxValue;4;6;Int32.MinValue;5;7;0]) + let expectedInt = iseq <| seq { yield Int32.MaxValue; - yield! seq{ 7..-1..0 } + yield! iseq{ 7..-1..0 } yield Int32.MinValue } VerifySeqsEqual expectedInt resultInt // string ISeq - let resultStr = Seq.sortDescending (seq ["str1";null;"str3";"";"Str1";"str2";"str4"]) - let expectedStr = seq ["str4";"str3";"str2";"str1";"Str1";"";null] + let resultStr = ISeq.sortDescending (iseq ["str1";null;"str3";"";"Str1";"str2";"str4"]) + let expectedStr = iseq ["str4";"str3";"str2";"str1";"Str1";"";null] VerifySeqsEqual expectedStr resultStr // empty ISeq - let resultEpt = Seq.sortDescending ISeq.empty + let resultEpt = ISeq.sortDescending ISeq.empty VerifySeqsEqual resultEpt ISeq.empty // tuple ISeq - let tupSeq = (seq[(2,"a");(1,"d");(1,"b");(1,"a");(2,"x");(2,"b");(1,"x")]) - let resultTup = Seq.sortDescending tupSeq - let expectedTup = (seq[(2,"x");(2,"b");(2,"a");(1,"x");(1,"d");(1,"b");(1,"a")]) + let tupSeq = (iseq[(2,"a");(1,"d");(1,"b");(1,"a");(2,"x");(2,"b");(1,"x")]) + let resultTup = ISeq.sortDescending tupSeq + let expectedTup = (iseq[(2,"x");(2,"b");(2,"a");(1,"x");(1,"d");(1,"b");(1,"a")]) VerifySeqsEqual expectedTup resultTup // float ISeq let minFloat,maxFloat,epsilon = System.Double.MinValue,System.Double.MaxValue,System.Double.Epsilon - let floatSeq = seq [0.0; 0.5; 2.0; 1.5; 1.0; minFloat;maxFloat;epsilon;-epsilon] - let resultFloat = Seq.sortDescending floatSeq - let expectedFloat = seq [maxFloat; 2.0; 1.5; 1.0; 0.5; epsilon; 0.0; -epsilon; minFloat; ] + let floatSeq = iseq [0.0; 0.5; 2.0; 1.5; 1.0; minFloat;maxFloat;epsilon;-epsilon] + let resultFloat = ISeq.sortDescending floatSeq + let expectedFloat = iseq [maxFloat; 2.0; 1.5; 1.0; 0.5; epsilon; 0.0; -epsilon; minFloat; ] VerifySeqsEqual expectedFloat resultFloat //// null ISeq @@ -1277,49 +1280,49 @@ type ISeqModule2() = // integer ISeq let funcInt x = Math.Abs(x-5) - let resultInt = Seq.sortByDescending funcInt (seq [1;2;4;5;7]) - let expectedInt = seq [1;2;7;4;5] + let resultInt = ISeq.sortByDescending funcInt (iseq [1;2;4;5;7]) + let expectedInt = iseq [1;2;7;4;5] VerifySeqsEqual expectedInt resultInt // string ISeq let funcStr (x:string) = x.IndexOf("key") - let resultStr =Seq.sortByDescending funcStr (seq ["st(key)r";"str(key)";"s(key)tr";"(key)str"]) + let resultStr =ISeq.sortByDescending funcStr (iseq ["st(key)r";"str(key)";"s(key)tr";"(key)str"]) - let expectedStr = seq ["str(key)";"st(key)r";"s(key)tr";"(key)str"] + let expectedStr = iseq ["str(key)";"st(key)r";"s(key)tr";"(key)str"] VerifySeqsEqual expectedStr resultStr // empty ISeq - let resultEpt = Seq.sortByDescending funcInt ISeq.empty + let resultEpt = ISeq.sortByDescending funcInt ISeq.empty VerifySeqsEqual resultEpt ISeq.empty // tuple ISeq - let tupSeq = (seq[(2,"a");(1,"d");(1,"b");(1,"a");(2,"x");(2,"b");(1,"x")]) - let resultTup = Seq.sortByDescending snd tupSeq - let expectedTup = (seq[(2,"x");(1,"x");(1,"d");(1,"b");(2,"b");(2,"a");(1,"a")]) + let tupSeq = (iseq[(2,"a");(1,"d");(1,"b");(1,"a");(2,"x");(2,"b");(1,"x")]) + let resultTup = ISeq.sortByDescending snd tupSeq + let expectedTup = (iseq[(2,"x");(1,"x");(1,"d");(1,"b");(2,"b");(2,"a");(1,"a")]) VerifySeqsEqual expectedTup resultTup // float ISeq let minFloat,maxFloat,epsilon = System.Double.MinValue,System.Double.MaxValue,System.Double.Epsilon - let floatSeq = seq [0.0; 0.5; 2.0; 1.5; 1.0; minFloat;maxFloat;epsilon;-epsilon] - let resultFloat = Seq.sortByDescending id floatSeq - let expectedFloat = seq [maxFloat; 2.0; 1.5; 1.0; 0.5; epsilon; 0.0; -epsilon; minFloat; ] + let floatSeq = iseq [0.0; 0.5; 2.0; 1.5; 1.0; minFloat;maxFloat;epsilon;-epsilon] + let resultFloat = ISeq.sortByDescending id floatSeq + let expectedFloat = iseq [maxFloat; 2.0; 1.5; 1.0; 0.5; epsilon; 0.0; -epsilon; minFloat; ] VerifySeqsEqual expectedFloat resultFloat //// null ISeq - //CheckThrowsArgumentNullException(fun() -> Seq.sortByDescending funcInt null |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.sortByDescending funcInt null |> ignore) () member this.SortWith() = // integer ISeq let intComparer a b = compare (a%3) (b%3) - let resultInt = ISeq.sortWith intComparer (seq {0..10} |> ISeq.ofSeq) - let expectedInt = seq [0;3;6;9;1;4;7;10;2;5;8]|> ISeq.ofSeq + let resultInt = ISeq.sortWith intComparer (iseq <| seq {0..10}) + let expectedInt = iseq [0;3;6;9;1;4;7;10;2;5;8] VerifySeqsEqual expectedInt resultInt // string ISeq - let resultStr = ISeq.sortWith compare (seq ["str1";"str3";"str2";"str4"]|> ISeq.ofSeq) - let expectedStr = seq ["str1";"str2";"str3";"str4"]|> ISeq.ofSeq + let resultStr = ISeq.sortWith compare (iseq ["str1";"str3";"str2";"str4"]) + let expectedStr = iseq ["str1";"str2";"str3";"str4"] VerifySeqsEqual expectedStr resultStr // empty ISeq @@ -1335,21 +1338,21 @@ type ISeqModule2() = member this.Sum() = // integer ISeq - let resultInt = ISeq.sum (seq [1..10]|> ISeq.ofSeq) + let resultInt = ISeq.sum (iseq [1..10]) Assert.AreEqual(55,resultInt) // float32 ISeq - let floatSeq = (seq [ 1.2f;3.5f;6.7f ])|> ISeq.ofSeq + let floatSeq = (iseq [ 1.2f;3.5f;6.7f ]) let resultFloat = ISeq.sum floatSeq if resultFloat <> 11.4f then Assert.Fail() // double ISeq - let doubleSeq = (seq [ 1.0;8.0 ])|> ISeq.ofSeq + let doubleSeq = (iseq [ 1.0;8.0 ]) let resultDouble = ISeq.sum doubleSeq if resultDouble <> 9.0 then Assert.Fail() // decimal ISeq - let decimalSeq = (seq [ 0M;19M;19.03M ])|> ISeq.ofSeq + let decimalSeq = (iseq [ 0M;19M;19.03M ]) let resultDecimal = ISeq.sum decimalSeq if resultDecimal <> 38.03M then Assert.Fail() @@ -1375,21 +1378,21 @@ type ISeqModule2() = member this.SumBy() = // integer ISeq - let resultInt = ISeq.sumBy int (seq [1..10]|> ISeq.ofSeq) + let resultInt = ISeq.sumBy int (iseq [1..10]) Assert.AreEqual(55,resultInt) // float32 ISeq - let floatSeq = (seq [ 1.2f;3.5f;6.7f ])|> ISeq.ofSeq + let floatSeq = (iseq [ 1.2f;3.5f;6.7f ]) let resultFloat = ISeq.sumBy float32 floatSeq if resultFloat <> 11.4f then Assert.Fail() // double ISeq - let doubleSeq = (seq [ 1.0;8.0 ])|> ISeq.ofSeq + let doubleSeq = (iseq [ 1.0;8.0 ]) let resultDouble = ISeq.sumBy double doubleSeq if resultDouble <> 9.0 then Assert.Fail() // decimal ISeq - let decimalSeq = (seq [ 0M;19M;19.03M ]) |> ISeq.ofSeq + let decimalSeq = (iseq [ 0M;19M;19.03M ]) let resultDecimal = ISeq.sumBy decimal decimalSeq if resultDecimal <> 38.03M then Assert.Fail() @@ -1414,16 +1417,16 @@ type ISeqModule2() = member this.Take() = // integer ISeq - let resultInt = ISeq.take 3 (seq [1;2;4;5;7]|> ISeq.ofSeq) + let resultInt = ISeq.take 3 (iseq [1;2;4;5;7]) - let expectedInt = seq [1;2;4] + let expectedInt = iseq [1;2;4] VerifySeqsEqual expectedInt resultInt // string ISeq - let resultStr =ISeq.take 2(seq ["str1";"str2";"str3";"str4"]|> ISeq.ofSeq) + let resultStr =ISeq.take 2(iseq ["str1";"str2";"str3";"str4"]) - let expectedStr = seq ["str1";"str2"] + let expectedStr = iseq ["str1";"str2"] VerifySeqsEqual expectedStr resultStr // empty ISeq @@ -1440,16 +1443,16 @@ type ISeqModule2() = member this.takeWhile() = // integer ISeq let funcInt x = (x < 6) - let resultInt = ISeq.takeWhile funcInt (seq [1;2;4;5;6;7]|> ISeq.ofSeq) + let resultInt = ISeq.takeWhile funcInt (iseq [1;2;4;5;6;7]) - let expectedInt = seq [1;2;4;5] + let expectedInt = iseq [1;2;4;5] VerifySeqsEqual expectedInt resultInt // string ISeq let funcStr (x:string) = (x.Length < 4) - let resultStr =ISeq.takeWhile funcStr (seq ["a"; "ab"; "abc"; "abcd"; "abcde"]|> ISeq.ofSeq) + let resultStr =ISeq.takeWhile funcStr (iseq ["a"; "ab"; "abc"; "abcd"; "abcde"]) - let expectedStr = seq ["a"; "ab"; "abc"] + let expectedStr = iseq ["a"; "ab"; "abc"] VerifySeqsEqual expectedStr resultStr // empty ISeq @@ -1463,13 +1466,13 @@ type ISeqModule2() = [] member this.ToArray() = // integer ISeq - let resultInt = ISeq.toArray(seq [1;2;4;5;7]|> ISeq.ofSeq) + let resultInt = ISeq.toArray(iseq [1;2;4;5;7]) let expectedInt = [|1;2;4;5;7|] Assert.AreEqual(expectedInt,resultInt) // string ISeq - let resultStr =ISeq.toArray (seq ["str1";"str2";"str3"]|> ISeq.ofSeq) + let resultStr =ISeq.toArray (iseq ["str1";"str2";"str3"]) let expectedStr = [|"str1";"str2";"str3"|] Assert.AreEqual(expectedStr,resultStr) @@ -1484,8 +1487,8 @@ type ISeqModule2() = [] member this.ToArrayFromICollection() = - let inputCollection = ResizeArray(seq [1;2;4;5;7]) - let resultInt = ISeq.toArray(inputCollection|> ISeq.ofSeq) + let inputCollection = ResizeArray(iseq [1;2;4;5;7]) + let resultInt = ISeq.toArray((iseq inputCollection)) let expectedInt = [|1;2;4;5;7|] Assert.AreEqual(expectedInt,resultInt) @@ -1497,45 +1500,45 @@ type ISeqModule2() = [] member this.ToArrayFromArray() = - let resultInt = ISeq.toArray([|1;2;4;5;7|]|> ISeq.ofSeq) + let resultInt = ISeq.toArray((iseq [|1;2;4;5;7|])) let expectedInt = [|1;2;4;5;7|] Assert.AreEqual(expectedInt,resultInt) [] member this.ToArrayFromList() = - let resultInt = ISeq.toArray([1;2;4;5;7]|> ISeq.ofSeq) + let resultInt = ISeq.toArray((iseq [1;2;4;5;7])) let expectedInt = [|1;2;4;5;7|] Assert.AreEqual(expectedInt,resultInt) [] member this.ToList() = // integer ISeq - let resultInt = Seq.toList (seq [1;2;4;5;7]) + let resultInt = ISeq.toList (iseq [1;2;4;5;7]) let expectedInt = [1;2;4;5;7] Assert.AreEqual(expectedInt,resultInt) // string ISeq - let resultStr =Seq.toList (seq ["str1";"str2";"str3"]) + let resultStr =ISeq.toList (iseq ["str1";"str2";"str3"]) let expectedStr = ["str1";"str2";"str3"] Assert.AreEqual(expectedStr,resultStr) // empty ISeq - let resultEpt = Seq.toList ISeq.empty + let resultEpt = ISeq.toList ISeq.empty Assert.AreEqual([],resultEpt) //// null ISeq - //CheckThrowsArgumentNullException(fun() -> Seq.toList null |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.toList null |> ignore) () [] member this.Truncate() = // integer ISeq - let resultInt = ISeq.truncate 3 (seq [1;2;4;5;7]|> ISeq.ofSeq) + let resultInt = ISeq.truncate 3 (iseq [1;2;4;5;7]) let expectedInt = [1;2;4] VerifySeqsEqual expectedInt resultInt // string ISeq - let resultStr =ISeq.truncate 2 (seq ["str1";"str2";"str3"]|> ISeq.ofSeq) + let resultStr =ISeq.truncate 2 (iseq ["str1";"str2";"str3"]) let expectedStr = ["str1";"str2"] VerifySeqsEqual expectedStr resultStr @@ -1547,27 +1550,27 @@ type ISeqModule2() = //CheckThrowsArgumentNullException(fun() -> ISeq.truncate 1 null |> ignore) // negative count - VerifySeqsEqual ISeq.empty <| ISeq.truncate -1 (seq [1;2;4;5;7]|> ISeq.ofSeq) - VerifySeqsEqual ISeq.empty <| ISeq.truncate System.Int32.MinValue (seq [1;2;4;5;7]|> ISeq.ofSeq) + VerifySeqsEqual ISeq.empty <| ISeq.truncate -1 (iseq [1;2;4;5;7]) + VerifySeqsEqual ISeq.empty <| ISeq.truncate System.Int32.MinValue (iseq [1;2;4;5;7]) () [] member this.tryFind() = // integer ISeq - let resultInt = ISeq.tryFind (fun x -> (x%2=0)) (seq [1;2;4;5;7]|> ISeq.ofSeq) + let resultInt = ISeq.tryFind (fun x -> (x%2=0)) (iseq [1;2;4;5;7]) Assert.AreEqual(Some(2), resultInt) // integer ISeq - None - let resultInt = ISeq.tryFind (fun x -> (x%2=0)) (seq [1;3;5;7]|> ISeq.ofSeq) + let resultInt = ISeq.tryFind (fun x -> (x%2=0)) (iseq [1;3;5;7]) Assert.AreEqual(None, resultInt) // string ISeq - let resultStr = ISeq.tryFind (fun (x:string) -> x.Contains("2")) (seq ["str1";"str2";"str3"]|> ISeq.ofSeq) + let resultStr = ISeq.tryFind (fun (x:string) -> x.Contains("2")) (iseq ["str1";"str2";"str3"]) Assert.AreEqual(Some("str2"),resultStr) // string ISeq - None - let resultStr = ISeq.tryFind (fun (x:string) -> x.Contains("2")) (seq ["str1";"str4";"str3"] |> ISeq.ofSeq) + let resultStr = ISeq.tryFind (fun (x:string) -> x.Contains("2")) (iseq ["str1";"str4";"str3"]) Assert.AreEqual(None,resultStr) @@ -1582,46 +1585,46 @@ type ISeqModule2() = [] member this.TryFindBack() = // integer ISeq - let resultInt = Seq.tryFindBack (fun x -> (x%2=0)) (seq [1;2;4;5;7]) + let resultInt = ISeq.tryFindBack (fun x -> (x%2=0)) (iseq [1;2;4;5;7]) Assert.AreEqual(Some 4, resultInt) // integer ISeq - None - let resultInt = Seq.tryFindBack (fun x -> (x%2=0)) (seq [1;3;5;7]) + let resultInt = ISeq.tryFindBack (fun x -> (x%2=0)) (iseq [1;3;5;7]) Assert.AreEqual(None, resultInt) // string ISeq - let resultStr = Seq.tryFindBack (fun (x:string) -> x.Contains("2")) (seq ["str1";"str2";"str2x";"str3"]) + let resultStr = ISeq.tryFindBack (fun (x:string) -> x.Contains("2")) (iseq ["str1";"str2";"str2x";"str3"]) Assert.AreEqual(Some "str2x", resultStr) // string ISeq - None - let resultStr = Seq.tryFindBack (fun (x:string) -> x.Contains("2")) (seq ["str1";"str4";"str3"]) + let resultStr = ISeq.tryFindBack (fun (x:string) -> x.Contains("2")) (iseq ["str1";"str4";"str3"]) Assert.AreEqual(None, resultStr) // empty ISeq - let resultEpt = Seq.tryFindBack (fun x -> (x%2=0)) ISeq.empty + let resultEpt = ISeq.tryFindBack (fun x -> (x%2=0)) ISeq.empty Assert.AreEqual(None, resultEpt) //// null ISeq - //CheckThrowsArgumentNullException(fun() -> Seq.tryFindBack (fun x -> (x%2=0)) null |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.tryFindBack (fun x -> (x%2=0)) null |> ignore) () [] member this.TryFindIndex() = // integer ISeq - let resultInt = ISeq.tryFindIndex (fun x -> (x % 5 = 0)) ([8; 9; 10] |> ISeq.ofSeq) + let resultInt = ISeq.tryFindIndex (fun x -> (x % 5 = 0)) (iseq [8; 9; 10]) Assert.AreEqual(Some(2), resultInt) // integer ISeq - None - let resultInt = ISeq.tryFindIndex (fun x -> (x % 5 = 0)) ([9;3;11]|> ISeq.ofSeq) + let resultInt = ISeq.tryFindIndex (fun x -> (x % 5 = 0)) (iseq [9;3;11]) Assert.AreEqual(None, resultInt) // string ISeq - let resultStr = ISeq.tryFindIndex (fun (x:string) -> x.Contains("2")) (["str1"; "str2"; "str3"]|> ISeq.ofSeq) + let resultStr = ISeq.tryFindIndex (fun (x:string) -> x.Contains("2")) (iseq ["str1"; "str2"; "str3"]) Assert.AreEqual(Some(1),resultStr) // string ISeq - None - let resultStr = ISeq.tryFindIndex (fun (x:string) -> x.Contains("2")) (["str1"; "str4"; "str3"]|> ISeq.ofSeq) + let resultStr = ISeq.tryFindIndex (fun (x:string) -> x.Contains("2")) (iseq ["str1"; "str4"; "str3"]) Assert.AreEqual(None,resultStr) @@ -1637,27 +1640,27 @@ type ISeqModule2() = member this.TryFindIndexBack() = // integer ISeq - let resultInt = Seq.tryFindIndexBack (fun x -> (x % 5 = 0)) [5; 9; 10; 12] + let resultInt = ISeq.tryFindIndexBack (fun x -> (x % 5 = 0)) (iseq [5; 9; 10; 12]) Assert.AreEqual(Some(2), resultInt) // integer ISeq - None - let resultInt = Seq.tryFindIndexBack (fun x -> (x % 5 = 0)) [9;3;11] + let resultInt = ISeq.tryFindIndexBack (fun x -> (x % 5 = 0)) (iseq [9;3;11]) Assert.AreEqual(None, resultInt) // string ISeq - let resultStr = Seq.tryFindIndexBack (fun (x:string) -> x.Contains("2")) ["str1"; "str2"; "str2x"; "str3"] + let resultStr = ISeq.tryFindIndexBack (fun (x:string) -> x.Contains("2")) (iseq ["str1"; "str2"; "str2x"; "str3"]) Assert.AreEqual(Some(2), resultStr) // string ISeq - None - let resultStr = Seq.tryFindIndexBack (fun (x:string) -> x.Contains("2")) ["str1"; "str4"; "str3"] + let resultStr = ISeq.tryFindIndexBack (fun (x:string) -> x.Contains("2")) (iseq ["str1"; "str4"; "str3"]) Assert.AreEqual(None, resultStr) // empty ISeq - let resultEpt = Seq.tryFindIndexBack (fun x -> (x%2=0)) ISeq.empty + let resultEpt = ISeq.tryFindIndexBack (fun x -> (x%2=0)) ISeq.empty Assert.AreEqual(None, resultEpt) //// null ISeq - //CheckThrowsArgumentNullException(fun() -> Seq.tryFindIndexBack (fun x -> (x % 2 = 0)) null |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.tryFindIndexBack (fun x -> (x % 2 = 0)) null |> ignore) () [] @@ -1666,11 +1669,11 @@ type ISeqModule2() = let resultInt = ISeq.unfold (fun x -> if x = 1 then Some(7,2) else None) 1 - VerifySeqsEqual (seq [7]) resultInt + VerifySeqsEqual (iseq [7]) resultInt // string ISeq let resultStr =ISeq.unfold (fun (x:string) -> if x.Contains("unfold") then Some("a","b") else None) "unfold" - VerifySeqsEqual (seq ["a"]) resultStr + VerifySeqsEqual (iseq ["a"]) resultStr () @@ -1680,7 +1683,6 @@ type ISeqModule2() = let testWindowed config = try config.InputSeq - |> ISeq.ofSeq |> ISeq.windowed config.WindowSize |> VerifySeqsEqual config.ExpectedSeq with @@ -1689,33 +1691,33 @@ type ISeqModule2() = | _ -> Assert.Fail() { - InputSeq = seq [1..10] + InputSeq = iseq [1..10] WindowSize = 1 - ExpectedSeq = seq { for i in 1..10 do yield [| i |] } + ExpectedSeq = iseq <| seq { for i in 1..10 do yield [| i |] } Exception = None } |> testWindowed { - InputSeq = seq [1..10] + InputSeq = iseq [1..10] WindowSize = 5 - ExpectedSeq = seq { for i in 1..6 do yield [| i; i+1; i+2; i+3; i+4 |] } + ExpectedSeq = iseq <| seq { for i in 1..6 do yield [| i; i+1; i+2; i+3; i+4 |] } Exception = None } |> testWindowed { - InputSeq = seq [1..10] + InputSeq = iseq [1..10] WindowSize = 10 - ExpectedSeq = seq { yield [| 1 .. 10 |] } + ExpectedSeq = iseq <| seq { yield [| 1 .. 10 |] } Exception = None } |> testWindowed { - InputSeq = seq [1..10] + InputSeq = iseq [1..10] WindowSize = 25 ExpectedSeq = ISeq.empty Exception = None } |> testWindowed { - InputSeq = seq ["str1";"str2";"str3";"str4"] + InputSeq = iseq ["str1";"str2";"str3";"str4"] WindowSize = 2 - ExpectedSeq = seq [ [|"str1";"str2"|];[|"str2";"str3"|];[|"str3";"str4"|]] + ExpectedSeq = iseq [ [|"str1";"str2"|];[|"str2";"str3"|];[|"str3";"str4"|]] Exception = None } |> testWindowed { @@ -1724,14 +1726,14 @@ type ISeqModule2() = ExpectedSeq = ISeq.empty Exception = None } |> testWindowed + //{ + // InputSeq = null + // WindowSize = 2 + // ExpectedSeq = ISeq.empty + // Exception = Some typeof + //} |> testWindowed { - InputSeq = null - WindowSize = 2 - ExpectedSeq = ISeq.empty - Exception = Some typeof - } |> testWindowed - { - InputSeq = seq [1..10] + InputSeq = iseq [1..10] WindowSize = 0 ExpectedSeq = ISeq.empty Exception = Some typeof @@ -1743,15 +1745,15 @@ type ISeqModule2() = member this.Zip() = // integer ISeq - let resultInt = ISeq.zip (seq [1..7] |> ISeq.ofSeq) (seq [11..17] |> ISeq.ofSeq) + let resultInt = ISeq.zip (iseq [1..7]) (iseq [11..17]) let expectedInt = - seq { for i in 1..7 do - yield i, i+10 } + iseq <| seq { for i in 1..7 do + yield i, i+10 } VerifySeqsEqual expectedInt resultInt // string ISeq - let resultStr =ISeq.zip (seq ["str3";"str4"] |> ISeq.ofSeq) (seq ["str1";"str2"] |> ISeq.ofSeq) - let expectedStr = seq ["str3","str1";"str4","str2"] |> ISeq.ofSeq + let resultStr =ISeq.zip (iseq ["str3";"str4"]) (iseq ["str1";"str2"]) + let expectedStr = iseq ["str3","str1";"str4","str2"] VerifySeqsEqual expectedStr resultStr // empty ISeq @@ -1760,44 +1762,44 @@ type ISeqModule2() = //// null ISeq //CheckThrowsArgumentNullException(fun() -> ISeq.zip null null |> ignore) - //CheckThrowsArgumentNullException(fun() -> ISeq.zip null (seq [1..7]) |> ignore) - //CheckThrowsArgumentNullException(fun() -> ISeq.zip (seq [1..7]) null |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.zip null (iseq [1..7]) |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.zip (iseq [1..7]) null |> ignore) () [] member this.Zip3() = // integer ISeq - let resultInt = Seq.zip3 (seq [1..7]) (seq [11..17]) (seq [21..27]) + let resultInt = ISeq.zip3 (iseq [1..7]) (iseq [11..17]) (iseq [21..27]) let expectedInt = - seq { for i in 1..7 do - yield i, (i + 10), (i + 20) } + iseq <| seq { for i in 1..7 do + yield i, (i + 10), (i + 20) } VerifySeqsEqual expectedInt resultInt // string ISeq - let resultStr =Seq.zip3 (seq ["str1";"str2"]) (seq ["str11";"str12"]) (seq ["str21";"str22"]) - let expectedStr = seq ["str1","str11","str21";"str2","str12","str22" ] + let resultStr =ISeq.zip3 (iseq ["str1";"str2"]) (iseq ["str11";"str12"]) (iseq ["str21";"str22"]) + let expectedStr = iseq ["str1","str11","str21";"str2","str12","str22" ] VerifySeqsEqual expectedStr resultStr // empty ISeq - let resultEpt = Seq.zip3 ISeq.empty ISeq.empty ISeq.empty + let resultEpt = ISeq.zip3 ISeq.empty ISeq.empty ISeq.empty VerifySeqsEqual ISeq.empty resultEpt //// null ISeq - //CheckThrowsArgumentNullException(fun() -> Seq.zip3 null null null |> ignore) - //CheckThrowsArgumentNullException(fun() -> Seq.zip3 null (seq [1..7]) (seq [1..7]) |> ignore) - //CheckThrowsArgumentNullException(fun() -> Seq.zip3 (seq [1..7]) null (seq [1..7]) |> ignore) - //CheckThrowsArgumentNullException(fun() -> Seq.zip3 (seq [1..7]) (seq [1..7]) null |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.zip3 null null null |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.zip3 null (iseq [1..7]) (iseq [1..7]) |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.zip3 (iseq [1..7]) null (iseq [1..7]) |> ignore) + //CheckThrowsArgumentNullException(fun() -> ISeq.zip3 (iseq [1..7]) (iseq [1..7]) null |> ignore) () [] member this.tryPick() = // integer ISeq - let resultInt = ISeq.tryPick (fun x-> if x = 1 then Some("got") else None) (seq [1..5]|> ISeq.ofSeq) + let resultInt = ISeq.tryPick (fun x-> if x = 1 then Some("got") else None) (iseq [1..5]) Assert.AreEqual(Some("got"),resultInt) // string ISeq - let resultStr = ISeq.tryPick (fun x-> if x = "Are" then Some("got") else None) (seq ["Lists"; "Are"] |> ISeq.ofSeq) + let resultStr = ISeq.tryPick (fun x-> if x = "Are" then Some("got") else None) (iseq ["Lists"; "Are"]) Assert.AreEqual(Some("got"),resultStr) // empty ISeq @@ -1805,7 +1807,7 @@ type ISeqModule2() = Assert.IsNull(resultEpt) //// null ISeq - //let nullSeq : seq<'a> = null + //let nullSeq : iseq<'a> = null //let funcNull x = Some(1) //CheckThrowsArgumentNullException(fun () -> ISeq.tryPick funcNull nullSeq |> ignore) @@ -1815,11 +1817,11 @@ type ISeqModule2() = [] member this.tryItem() = // integer ISeq - let resultInt = ISeq.tryItem 3 ({ 10..20 }|> ISeq.ofSeq) + let resultInt = ISeq.tryItem 3 (iseq { 10..20 }) Assert.AreEqual(Some(13), resultInt) // string ISeq - let resultStr = ISeq.tryItem 2 (seq ["Lists"; "Are"; "Cool"; "List" ]|> ISeq.ofSeq) + let resultStr = ISeq.tryItem 2 (iseq ["Lists"; "Are"; "Cool"; "List" ]) Assert.AreEqual(Some("Cool"), resultStr) // empty ISeq @@ -1827,13 +1829,13 @@ type ISeqModule2() = Assert.AreEqual(None, resultEmpty) //// null ISeq - //let nullSeq:seq<'a> = null + //let nullSeq:iseq<'a> = null //CheckThrowsArgumentNullException (fun () -> ISeq.tryItem 3 nullSeq |> ignore) // Negative index - let resultNegativeIndex = ISeq.tryItem -1 ({ 10..20 }|> ISeq.ofSeq) + let resultNegativeIndex = ISeq.tryItem -1 (iseq { 10..20 }) Assert.AreEqual(None, resultNegativeIndex) // Index greater than length - let resultIndexGreater = ISeq.tryItem 31 ({ 10..20 }|> ISeq.ofSeq) + let resultIndexGreater = ISeq.tryItem 31 (iseq { 10..20 }) Assert.AreEqual(None, resultIndexGreater) From f1dd39b96f9fcf71862162a1d11b777da2db6277 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 20 Mar 2017 19:22:39 +1100 Subject: [PATCH 11/83] Derived AppendEnumerable from ConcatEnumerable --- src/fsharp/FSharp.Core/iseq.fs | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 9d446d2080..76002a57a0 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -478,15 +478,12 @@ namespace Microsoft.FSharp.Collections main.Dispose () active.Dispose () - and AppendEnumerable<'T> (sources:list>) = + and ConcatEnumerable<'T, 'Collection, 'Collections when 'Collection :> seq<'T> and 'Collections :> seq<'Collection>> (sources:'Collections, preEnumerate:'Collections->'Collections) = inherit EnumerableBase<'T>() interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - Upcast.enumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) - - override this.Append source = - Upcast.seq (AppendEnumerable (source::sources)) + Upcast.enumerator (new ConcatEnumerator<_,_> (preEnumerate sources)) interface ISeq<'T> with member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = @@ -495,19 +492,11 @@ namespace Microsoft.FSharp.Collections member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = Fold.executeThin f (Fold.enumerable this) - and ConcatEnumerable<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = - inherit EnumerableBase<'T>() - - interface IEnumerable<'T> with - member this.GetEnumerator () : IEnumerator<'T> = - Upcast.enumerator (new ConcatEnumerator<_,_> (sources)) - - interface ISeq<'T> with - member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable<'T,'V>(this, next, 1)) + and AppendEnumerable<'T> (sources:list>) = + inherit ConcatEnumerable<'T, ISeq<'T>, list>>(sources, List.rev) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - Fold.executeThin f (Fold.enumerable this) + override this.Append source = + Upcast.seq (AppendEnumerable (source::sources)) let create enumerable current = Upcast.seq (Enumerable (enumerable, current, 1)) @@ -1308,7 +1297,7 @@ namespace Microsoft.FSharp.Collections [] let concat (sources:ISeq<#ISeq<'T>>) : ISeq<'T> = - Upcast.seq (Enumerable.ConcatEnumerable sources) + Upcast.seq (Enumerable.ConcatEnumerable (sources, id)) [] let inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = From ee148bcc313ff909637d911b578a326247e4c53b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 20 Mar 2017 20:07:20 +1100 Subject: [PATCH 12/83] Made CachedSeq an ISeq --- src/fsharp/FSharp.Core/iseq.fs | 125 +++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 54 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 76002a57a0..a28c974058 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1739,18 +1739,8 @@ namespace Microsoft.FSharp.Collections | len -> foldArraySubRight f arr 0 (len - 2) arr.[len - 1] [] - 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() - - [] - let cache (source:ISeq<'T>) : ISeq<'T> = - checkNonNull "source" source + type CachedSeq<'T>(source:ISeq<'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. @@ -1760,49 +1750,76 @@ namespace Microsoft.FSharp.Collections // 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 prefix = ResizeArray () + + // Choice1Of3 () = Unstarted. + // Choice2Of3 e = Started. + // Choice3Of3 () = Finished. + let mutable enumeratorR = Choice1Of3 () : Choice, unit> + + // 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). - 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) |> ofSeq) + // 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 + | Choice1Of3 _ -> enumeratorR <- Choice2Of3 (source.GetEnumerator()) + | _ -> () + + match enumeratorR with + | Choice2Of3 enumerator when enumerator.MoveNext() -> + prefix.Add enumerator.Current + | Choice2Of3 enumerator -> + enumerator.Dispose () // Move failed, dispose enumerator, + enumeratorR <- Choice3Of3 () // drop it and record finished. + | _ -> () + + let cached = + 0 |> 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 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)) + + interface System.IDisposable with + member __.Dispose() = + lock sync (fun () -> + prefix.Clear() + + match enumeratorR with + | Choice2Of3 e -> IEnumerator.dispose e + | _ -> () + + enumeratorR <- Choice1Of3 ()) + + interface System.Collections.Generic.IEnumerable<'T> with + member __.GetEnumerator() = cached.GetEnumerator() + + interface System.Collections.IEnumerable with + member __.GetEnumerator() = (cached :> System.Collections.IEnumerable).GetEnumerator() + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new Enumerable.Enumerable<'T,'U>(cached, next, 1)) + + member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + Fold.executeThin f (Fold.enumerable cached) + + member this.Clear() = (this :> IDisposable).Dispose () + + [] + let cache (source:ISeq<'T>) : ISeq<'T> = + Upcast.seq (new CachedSeq<_> (source)) [] let collect f sources = map f sources |> concat From 2d3de545ed69214da6428ab7173a883242ab806d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 21 Mar 2017 17:57:22 +1100 Subject: [PATCH 13/83] Fix error message --- .../FSharp.Core/Microsoft.FSharp.Collections/ISeqModule2.fs | 4 ++-- src/fsharp/FSharp.Core/iseq.fs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule2.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule2.fs index 859a3a7f46..e6a1691149 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule2.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule2.fs @@ -927,13 +927,13 @@ type ISeqModule2() = ISeq.item 0 (iseq (Array.zeroCreate 0)) |> ignore failwith "error expected" with - | exn when exn.Message.Contains("iseq was short by 1 element") -> () + | exn when exn.Message.Contains("seq was short by 1 element") -> () try ISeq.item 2 (iseq (Array.zeroCreate 0)) |> ignore failwith "error expected" with - | exn when exn.Message.Contains("iseq was short by 3 elements") -> () + | exn when exn.Message.Contains("seq was short by 3 elements") -> () [] member this.Of_Array() = diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index a28c974058..1e240613d0 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1777,7 +1777,7 @@ namespace Microsoft.FSharp.Collections | _ -> () let cached = - 0 |> unfold (fun i -> + 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 @@ -1789,7 +1789,7 @@ namespace Microsoft.FSharp.Collections if i < prefix.Count then Some (prefix.[i], i+1) else - None)) + None)) 0 interface System.IDisposable with member __.Dispose() = From 7b2a50a7d5c0924a157e3415a43704ab5f246fcd Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 21 Mar 2017 19:23:38 +1100 Subject: [PATCH 14/83] implemented chunkBySize --- src/fsharp/FSharp.Core/iseq.fs | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 1e240613d0..9eda8c501d 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1856,21 +1856,25 @@ namespace Microsoft.FSharp.Collections 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() } |> ofSeq - raise (NotImplementedException ("TBD")) + + source.PushTransform { new TransformFactory<'T,'T[]>() with + member __.Compose outOfBand pipeIdx next = + upcast { + new TransformWithPostProcessing<'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 mkDelayedSeq (f: unit -> IEnumerable<'T>) = mkSeq (fun () -> f().GetEnumerator()) |> ofSeq From 21090881583a3844a203d42ff5bb0efcdf9d15fc Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 21 Mar 2017 19:24:59 +1100 Subject: [PATCH 15/83] Removed checkNonNull as ISeq can't be null --- src/fsharp/FSharp.Core/iseq.fs | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 9eda8c501d..8cda0f646b 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1842,18 +1842,15 @@ namespace Microsoft.FSharp.Collections [] let isEmpty (source : ISeq<'T>) = - checkNonNull "source" source use ie = source.GetEnumerator() not (ie.MoveNext()) [] let cast (source: IEnumerable) : ISeq<'T> = - checkNonNull "source" source mkSeq (fun () -> IEnumerator.cast (source.GetEnumerator())) |> ofSeq [] let chunkBySize chunkSize (source : ISeq<'T>) : ISeq<'T[]> = - checkNonNull "source" source if chunkSize <= 0 then invalidArgFmt "chunkSize" "{0}\nchunkSize = {1}" [|SR.GetString SR.inputMustBePositive; chunkSize|] @@ -1880,7 +1877,6 @@ namespace Microsoft.FSharp.Collections [] let splitInto count (source:ISeq<'T>) : ISeq<'T[]> = - checkNonNull "source" source if count <= 0 then invalidArgFmt "count" "{0}\ncount = {1}" [|SR.GetString SR.inputMustBePositive; count|] mkDelayedSeq (fun () -> @@ -1890,14 +1886,12 @@ namespace Microsoft.FSharp.Collections [] let find f source = - checkNonNull "source" source match tryFind f source with | None -> indexNotFound() | Some x -> x [] let findIndex p (source:ISeq<_>) = - checkNonNull "source" source use ie = source.GetEnumerator() let rec loop i = if ie.MoveNext() then @@ -1910,17 +1904,14 @@ namespace Microsoft.FSharp.Collections [] let findBack f source = - checkNonNull "source" source source |> toArray |> Array.findBack f [] let findIndexBack f source = - checkNonNull "source" source source |> toArray |> Array.findIndexBack f [] let pick f source = - checkNonNull "source" source match tryPick f source with | None -> indexNotFound() | Some x -> x @@ -1928,18 +1919,15 @@ namespace Microsoft.FSharp.Collections [] [] let readonly (source:seq<_>) = - checkNonNull "source" source mkSeq (fun () -> source.GetEnumerator()) |> ofSeq [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = - checkNonNull "source" source let arr,state = source |> toArray |> Array.mapFold f acc readonly arr, state [] let mapFoldBack<'T,'State,'Result> (f: 'T -> 'State -> 'Result * 'State) source acc = - checkNonNull "source" source let array = source |> toArray let arr,state = Array.mapFoldBack f array acc readonly arr, state @@ -1955,7 +1943,6 @@ namespace Microsoft.FSharp.Collections [] let item i (source : ISeq<'T>) = - checkNonNull "source" source if i < 0 then invalidArgInputMustBeNonNegative "index" i use e = source.GetEnumerator() nth i e @@ -1965,29 +1952,22 @@ namespace Microsoft.FSharp.Collections [] let inline sortDescending source = - checkNonNull "source" source let inline compareDescending a b = compare b a sortWith compareDescending source [] let inline sortByDescending keyf source = - checkNonNull "source" source let inline compareDescending a b = compare (keyf b) (keyf a) sortWith compareDescending source [] let tryFindBack f (source : ISeq<'T>) = - checkNonNull "source" source source |> toArray |> Array.tryFindBack f [] let tryFindIndexBack f (source : ISeq<'T>) = - checkNonNull "source" source source |> toArray |> Array.tryFindIndexBack f [] 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) From de6184d0823b6b9c6afea4a466df29cfb8711b6f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 21 Mar 2017 19:27:52 +1100 Subject: [PATCH 16/83] type checks for cast --- src/fsharp/FSharp.Core/iseq.fs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 8cda0f646b..782ceb6ba4 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1847,7 +1847,11 @@ namespace Microsoft.FSharp.Collections [] let cast (source: IEnumerable) : ISeq<'T> = - mkSeq (fun () -> IEnumerator.cast (source.GetEnumerator())) |> ofSeq + match source with + | :? ISeq<'T> as s -> s + | :? ISeq as s -> s |> map unbox // covariant on ref types + | _ -> + mkSeq (fun () -> IEnumerator.cast (source.GetEnumerator())) |> ofSeq [] let chunkBySize chunkSize (source : ISeq<'T>) : ISeq<'T[]> = From d30c447e05209ce6e44fe75231c1d94d73b39cb3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 22 Mar 2017 20:00:40 +1100 Subject: [PATCH 17/83] Removed type comparisons due to Choice<> --- src/fsharp/FSharp.Core/iseq.fs | 40 +++++++++++++++------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 782ceb6ba4..64b1b6204e 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1741,6 +1741,7 @@ namespace Microsoft.FSharp.Collections [] type CachedSeq<'T>(source:ISeq<'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. @@ -1753,10 +1754,8 @@ namespace Microsoft.FSharp.Collections let prefix = ResizeArray () - // Choice1Of3 () = Unstarted. - // Choice2Of3 e = Started. - // Choice3Of3 () = Finished. - let mutable enumeratorR = Choice1Of3 () : Choice, unit> + let mutable started = false + let mutable enumeratorR = None : option> // function should only be called from within the lock let oneStepTo i = @@ -1764,16 +1763,16 @@ namespace Microsoft.FSharp.Collections // 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 - | Choice1Of3 _ -> enumeratorR <- Choice2Of3 (source.GetEnumerator()) - | _ -> () + if not started then + started <- true + enumeratorR <- Some (source.GetEnumerator()) match enumeratorR with - | Choice2Of3 enumerator when enumerator.MoveNext() -> + | Some enumerator when enumerator.MoveNext() -> prefix.Add enumerator.Current - | Choice2Of3 enumerator -> - enumerator.Dispose () // Move failed, dispose enumerator, - enumeratorR <- Choice3Of3 () // drop it and record finished. + | Some enumerator -> + enumerator.Dispose () // Move failed, dispose enumerator, + enumeratorR <- None // drop it and record finished. | _ -> () let cached = @@ -1796,11 +1795,11 @@ namespace Microsoft.FSharp.Collections lock sync (fun () -> prefix.Clear() - match enumeratorR with - | Choice2Of3 e -> IEnumerator.dispose e - | _ -> () + enumeratorR + |> Option.iter IEnumerator.dispose - enumeratorR <- Choice1Of3 ()) + started <- false + enumeratorR <- None) interface System.Collections.Generic.IEnumerable<'T> with member __.GetEnumerator() = cached.GetEnumerator() @@ -1920,21 +1919,16 @@ namespace Microsoft.FSharp.Collections | None -> indexNotFound() | Some x -> x - [] - [] - let readonly (source:seq<_>) = - mkSeq (fun () -> source.GetEnumerator()) |> ofSeq - [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = let arr,state = source |> toArray |> Array.mapFold f acc - readonly arr, state + ofArray arr, state [] let mapFoldBack<'T,'State,'Result> (f: 'T -> 'State -> 'Result * 'State) source acc = let array = source |> toArray let arr,state = Array.mapFoldBack f array acc - readonly arr, state + ofArray arr, state let rec nth index (e : IEnumerator<'T>) = if not (e.MoveNext()) then @@ -1952,7 +1946,7 @@ namespace Microsoft.FSharp.Collections nth i e [] - let singleton x = mkSeq (fun () -> IEnumerator.Singleton x) |> ofSeq + let singleton x = ofArray [| x |] [] let inline sortDescending source = From d3714f39989ab0276e0504cc6f295afe033c4d4a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 23 Mar 2017 20:03:07 +1100 Subject: [PATCH 18/83] Restore somewhat dubious, I think, singleton The test suite has a test where it says that IEnumerator.Current shouldn't throw an exception after MoveNext has thrown an exception. I doubt if this is particularly valid behaviour. Will provide a "proper" ISeq singleton soon. --- src/fsharp/FSharp.Core/iseq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 64b1b6204e..3b8c615747 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1946,7 +1946,7 @@ namespace Microsoft.FSharp.Collections nth i e [] - let singleton x = ofArray [| x |] + let singleton x = mkSeq (fun () -> IEnumerator.Singleton x) |> ofSeq [] let inline sortDescending source = From a61366fae3fb14baa98d0f8f6754643d25ca054f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 26 Mar 2017 13:24:33 +1100 Subject: [PATCH 19/83] Removed tag --- src/fsharp/FSharp.Core/iseq.fsi | 34 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fsi b/src/fsharp/FSharp.Core/iseq.fsi index 7d3534ae76..b395fb7685 100644 --- a/src/fsharp/FSharp.Core/iseq.fsi +++ b/src/fsharp/FSharp.Core/iseq.fsi @@ -14,23 +14,23 @@ namespace Microsoft.FSharp.Collections [] type NoValue = struct end - /// Values is a mutable struct. It can be embedded within the folder type - /// if two values are required for the calculation. + /// Values is a mutable struct. It can be embedded within the folder type + /// if two values are required for the calculation. [] type 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. + /// 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. + /// Values is a mutable struct. It can be embedded within the folder type + /// if three values are required for the calculation. [] type Values<'a,'b,'c> = new : a:'a * b:'b * c:'c -> Values<'a,'b,'c> @@ -38,28 +38,28 @@ namespace Microsoft.FSharp.Collections val mutable _2: 'b val mutable _3: 'c - /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the - /// source of the chain. + /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the + /// source of the chain. type PipeIdx = int type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit - /// Activity is the root class for chains of activities. It is in a non-generic - /// form so that it can be used by subsequent activities + /// Activity 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 Activity = - /// OnComplete is used to determine if the object has been processed correctly, + /// 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. + /// being processed. abstract ChainComplete : stopTailCall:byref*PipeIdx -> unit - /// OnDispose is used to cleanup the stream. It is always called at the last operation - /// after the enumeration has completed. + /// OnDispose is used to cleanup the stream. It is always called at the last operation + /// after the enumeration has completed. abstract ChainDispose : stopTailCall:byref -> unit - /// Activity is the base class of all elements within the pipeline + /// Activity is the base class of all elements within the pipeline [] type Activity<'T,'U> = inherit Activity @@ -80,9 +80,9 @@ namespace Microsoft.FSharp.Collections abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit - /// Folder is a base class to assist with fold-like operations. It's intended usage + /// Folder 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. + /// the Fold function. [] type Folder<'T,'Result,'State> = inherit Activity<'T,'T> From ce235fb8d965f65abf5d80b23d60e781b9ce4664 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 26 Mar 2017 14:48:08 +1100 Subject: [PATCH 20/83] Provided some comments around public interface --- src/fsharp/FSharp.Core/iseq.fsi | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/fsharp/FSharp.Core/iseq.fsi b/src/fsharp/FSharp.Core/iseq.fsi index b395fb7685..69917c1064 100644 --- a/src/fsharp/FSharp.Core/iseq.fsi +++ b/src/fsharp/FSharp.Core/iseq.fsi @@ -42,7 +42,9 @@ namespace Microsoft.FSharp.Collections /// source of the chain. type PipeIdx = int + /// Used within the pipline to provide out of band communications type IOutOfBand = + /// Stop the processing of any further items down the pipeline abstract StopFurtherProcessing : PipeIdx -> unit /// Activity is the root class for chains of activities. It is in a non-generic @@ -66,6 +68,9 @@ namespace Microsoft.FSharp.Collections new : unit -> Activity<'T,'U> abstract member ProcessNext : input:'T -> bool + /// 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 TransformFactory's Compose function. [] type Transform<'T,'U,'State> = inherit Activity<'T,'U> @@ -73,6 +78,11 @@ namespace Microsoft.FSharp.Collections val mutable State : 'State val private Next : Activity + /// 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 TransformFactory's Compose function. [] type TransformWithPostProcessing<'T,'U,'State> = inherit Transform<'T,'U,'State> @@ -93,6 +103,11 @@ namespace Microsoft.FSharp.Collections val mutable HaltedIdx : int member StopFurtherProcessing : PipeIdx -> unit + /// Folder 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 FolderWithPostProcessing<'T,'Result,'State> = inherit Folder<'T,'Result,'State> @@ -100,11 +115,16 @@ namespace Microsoft.FSharp.Collections abstract OnDispose : unit -> unit abstract OnComplete : PipeIdx -> unit + /// TransformFactory provides composition of Activities. Its intended to have a specialization + /// for each type of ISeq Activity. ISeq's PushTransform method is used to build a stack + /// of Actvities that will be composed. [] type TransformFactory<'T,'U> = new : unit -> TransformFactory<'T,'U> abstract member Compose : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> + /// ISeq<'T> is an extension to seq<'T> that provides the avilty to compose Activities + /// as well as Fold the current Activity pipeline. type ISeq<'T> = inherit System.Collections.Generic.IEnumerable<'T> abstract member PushTransform : TransformFactory<'T,'U> -> ISeq<'U> @@ -112,6 +132,10 @@ namespace Microsoft.FSharp.Collections open Core + /// ofResizeArrayUnchecked creates an ISeq 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 ISeq exists. [] val ofResizeArrayUnchecked : ResizeArray<'T> -> ISeq<'T> From 0089b05659f7f6651418c6b6958c1ba97560af52 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 27 Mar 2017 08:01:18 +1100 Subject: [PATCH 21/83] Capitalized type names (of IIterate implementations) --- src/fsharp/FSharp.Core/iseq.fs | 46 +++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 3b8c615747..53928a7b3b 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -192,11 +192,18 @@ namespace Microsoft.FSharp.Collections true module Fold = + // The consumers of IIterate are the execute and exeuteThin methods. IIterate is passed + // as a generic argument. The types that implement IIterate are value types. This combination + // means that the runtime will "inline" the methods. The alternatives to this were that the + // code in execute/executeThin were duplicated for each of the Fold types, or we turned the + // types back into normal functions and curried them then we would be creating garbage + // each time one of these were called. This has been an optimization to minimize the impact + // on very small collections. type IIterate<'T> = abstract Iterate<'U,'Result,'State> : outOfBand:Folder<'U,'Result,'State> -> consumer:Activity<'T,'U> -> unit [] - type enumerable<'T> (enumerable:IEnumerable<'T>) = + type IterateEnumerable<'T> (enumerable:IEnumerable<'T>) = interface IIterate<'T> with member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = use enumerator = enumerable.GetEnumerator () @@ -208,7 +215,7 @@ namespace Microsoft.FSharp.Collections iterate () [] - type Array<'T> (array:array<'T>) = + type IterateArray<'T> (array:array<'T>) = interface IIterate<'T> with member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = let array = array @@ -220,7 +227,7 @@ namespace Microsoft.FSharp.Collections iterate 0 [] - type resizeArray<'T> (array:ResizeArray<'T>) = + type IterateResizeArray<'T> (array:ResizeArray<'T>) = interface IIterate<'T> with member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = let array = array @@ -232,7 +239,7 @@ namespace Microsoft.FSharp.Collections iterate 0 [] - type List<'T> (alist:list<'T>) = + type IterateList<'T> (alist:list<'T>) = interface IIterate<'T> with member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = let rec iterate lst = @@ -245,7 +252,7 @@ namespace Microsoft.FSharp.Collections iterate alist [] - type unfold<'S,'T> (generator:'S->option<'T*'S>, state:'S) = + type IterateUnfold<'S,'T> (generator:'S->option<'T*'S>, state:'S) = interface IIterate<'T> with member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = let generator = generator @@ -259,7 +266,7 @@ namespace Microsoft.FSharp.Collections iterate state [] - type init<'T> (f:int->'T, terminatingIdx:int) = + type IterateInit<'T> (f:int->'T, terminatingIdx:int) = interface IIterate<'T> with member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = let terminatingIdx = terminatingIdx @@ -292,6 +299,8 @@ namespace Microsoft.FSharp.Collections if outOfBand.HaltedIdx = 0 && finalIdx = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + // execute, and it's companion, executeThin, are hosting functions that ensure the correct sequence + // of creation, iteration and disposal for the pipeline let execute (createFolder:PipeIdx->Folder<'U,'Result,'State>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (executeOn:#IIterate<'T>) = let mutable stopTailCall = () let result = createFolder (pipeIdx+1) @@ -303,6 +312,9 @@ namespace Microsoft.FSharp.Collections finally consumer.ChainDispose (&stopTailCall) + // executeThin is a specialization of execute, provided as a performance optimization, that can + // be used when a sequence has been wrapped in an ISeq, but hasn't had an items added to its pipeline + // i.e. a container that has ISeq.ofSeq applied. let executeThin (createFolder:PipeIdx->Folder<'T,'Result,'State>) (executeOn:#IIterate<'T>) = let mutable stopTailCall = () let result = createFolder 1 @@ -412,7 +424,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next, pipeIdx+1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - Fold.execute f current pipeIdx (Fold.enumerable enumerable) + Fold.execute f current pipeIdx (Fold.IterateEnumerable enumerable) and EnumerableThin<'T>(enumerable:IEnumerable<'T>) = inherit EnumerableBase<'T>() @@ -425,7 +437,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (new Enumerable<'T,'U>(enumerable, next, 1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - Fold.executeThin f (Fold.enumerable enumerable) + Fold.executeThin f (Fold.IterateEnumerable enumerable) and SeqDelayed<'T>(delayed:unit->ISeq<'T>, pipeIdx:PipeIdx) = inherit EnumerableBase<'T>() @@ -490,7 +502,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (Enumerable<'T,'V>(this, next, 1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - Fold.executeThin f (Fold.enumerable this) + Fold.executeThin f (Fold.IterateEnumerable this) and AppendEnumerable<'T> (sources:list>) = inherit ConcatEnumerable<'T, ISeq<'T>, list>>(sources, List.rev) @@ -519,7 +531,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (Enumerable.Enumerable<'T,'V>(this, next, 1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - Fold.executeThin f (Fold.enumerable this) + Fold.executeThin f (Fold.IterateEnumerable this) module Array = type Enumerator<'T,'U>(array:array<'T>, activity:Activity<'T,'U>, result:Result<'U>) = @@ -558,7 +570,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (new Enumerable<'T,'V>(array, ComposedFactory.Combine transformFactory next, 1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - Fold.execute f transformFactory pipeIdx (Fold.Array array) + Fold.execute f transformFactory pipeIdx (Fold.IterateArray array) module ResizeArray = type Enumerator<'T,'U>(array:ResizeArray<'T>, activity:Activity<'T,'U>, result:Result<'U>) = @@ -597,7 +609,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (new Enumerable<'T,'V>(resizeArray, ComposedFactory.Combine transformFactory next, 1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - Fold.execute f transformFactory pipeIdx (Fold.resizeArray resizeArray) + Fold.execute f transformFactory pipeIdx (Fold.IterateResizeArray resizeArray) module List = type Enumerator<'T,'U>(alist:list<'T>, activity:Activity<'T,'U>, result:Result<'U>) = @@ -637,7 +649,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - Fold.execute f transformFactory pipeIdx (Fold.List alist) + Fold.execute f transformFactory pipeIdx (Fold.IterateList alist) let create alist current = Upcast.seq (Enumerable(alist, current, 1)) @@ -676,7 +688,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - Fold.execute f transformFactory pipeIdx (Fold.unfold (generator, state)) + Fold.execute f transformFactory pipeIdx (Fold.IterateUnfold (generator, state)) module Init = // The original implementation of "init" delayed the calculation of Current, and so it was possible @@ -754,7 +766,7 @@ namespace Microsoft.FSharp.Collections member this.Fold<'Result,'State> (createResult:PipeIdx->Folder<'U,'Result,'State>) = let terminatingIdx = getTerminatingIdx count - Fold.execute createResult transformFactory pipeIdx (Fold.init (f, terminatingIdx)) + Fold.execute createResult transformFactory pipeIdx (Fold.IterateInit (f, terminatingIdx)) let upto lastOption f = match lastOption with @@ -821,7 +833,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (Enumerable<'T,'V>(count, f, next, pipeIdx+1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - Fold.executeThin f (Fold.enumerable (Upcast.enumerable this)) + Fold.executeThin f (Fold.IterateEnumerable (Upcast.enumerable this)) [] let ofResizeArrayUnchecked (source:ResizeArray<'T>) : ISeq<'T> = @@ -1812,7 +1824,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (new Enumerable.Enumerable<'T,'U>(cached, next, 1)) member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - Fold.executeThin f (Fold.enumerable cached) + Fold.executeThin f (Fold.IterateEnumerable cached) member this.Clear() = (this :> IDisposable).Dispose () From d7b533a5d760e0e1093c7d4c089af515bbcbb324 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 27 Mar 2017 08:32:53 +1100 Subject: [PATCH 22/83] Removed wrapping on Append to Empty --- src/fsharp/FSharp.Core/iseq.fs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 53928a7b3b..8c11b98159 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -523,8 +523,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = IEnumerator.Empty<'T>() - override this.Append source = - Upcast.seq (Enumerable.EnumerableThin<'T> source) + override this.Append source = source interface ISeq<'T> with member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = From 94c4438c9f39522a9f08b3df80f5212e55c4efe0 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 27 Mar 2017 09:16:36 +1100 Subject: [PATCH 23/83] Collapsed all the wrap specific modules into one --- src/fsharp/FSharp.Core/iseq.fs | 378 ++++++++++++++++----------------- 1 file changed, 187 insertions(+), 191 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 8c11b98159..09c9edb4ea 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -325,8 +325,8 @@ namespace Microsoft.FSharp.Collections finally result.ChainDispose (&stopTailCall) - module Enumerable = - type Empty<'T>() = + module Wrap = + type EmptyEnumerator<'T>() = let current () = failwith "library implementation error: Current should never be called" interface IEnumerator<'T> with member __.Current = current () @@ -338,7 +338,7 @@ namespace Microsoft.FSharp.Collections member __.Dispose () = () type EmptyEnumerators<'T>() = - static let element : IEnumerator<'T> = upcast (new Empty<'T> ()) + static let element : IEnumerator<'T> = upcast (new EmptyEnumerator<'T> ()) static member Element = element [] @@ -362,28 +362,7 @@ namespace Microsoft.FSharp.Collections | SeqProcessNextStates.Finished -> alreadyFinished() | _ -> failwith "library implementation error: all states should have been handled" - and [] EnumerableBase<'T> () = - let derivedClassShouldImplement () = - failwith "library implementation error: derived class should implement (should be abstract)" - - abstract member Append : (ISeq<'T>) -> ISeq<'T> - - default this.Append source = Upcast.seq (AppendEnumerable [source; this]) - - interface IEnumerable with - member this.GetEnumerator () : IEnumerator = - let genericEnumerable = Upcast.enumerable this - let genericEnumerator = genericEnumerable.GetEnumerator () - Upcast.enumeratorNonGeneric genericEnumerator - - interface IEnumerable<'T> with - member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () - - interface ISeq<'T> with - member __.PushTransform _ = derivedClassShouldImplement () - member __.Fold _ = derivedClassShouldImplement () - - and Enumerator<'T,'U>(source:IEnumerator<'T>, activity:Activity<'T,'U>, result:Result<'U>) = + type VanillaEnumerator<'T,'U>(source:IEnumerator<'T>, activity:Activity<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, activity) let rec moveNext () = @@ -411,48 +390,7 @@ namespace Microsoft.FSharp.Collections let mutable stopTailCall = () activity.ChainDispose (&stopTailCall) - and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), createFold current result pipeIdx, result)) - - interface ISeq<'U> with - member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next, pipeIdx+1)) - - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - Fold.execute f current pipeIdx (Fold.IterateEnumerable enumerable) - - and EnumerableThin<'T>(enumerable:IEnumerable<'T>) = - inherit EnumerableBase<'T>() - - interface IEnumerable<'T> with - member this.GetEnumerator () = enumerable.GetEnumerator () - - interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new Enumerable<'T,'U>(enumerable, next, 1)) - - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - Fold.executeThin f (Fold.IterateEnumerable enumerable) - - and SeqDelayed<'T>(delayed:unit->ISeq<'T>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'T>() - - interface IEnumerable<'T> with - member this.GetEnumerator () : IEnumerator<'T> = (delayed()).GetEnumerator () - - interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new SeqDelayed<'U>((fun () -> (delayed()).PushTransform next), pipeIdx+1)) - - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - (delayed()).Fold f - - and ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = + type ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = let mutable state = SeqProcessNextStates.NotStarted let main = sources.GetEnumerator () @@ -490,6 +428,43 @@ namespace Microsoft.FSharp.Collections main.Dispose () active.Dispose () + [] + type EnumerableBase<'T> () = + let derivedClassShouldImplement () = + failwith "library implementation error: derived class should implement (should be abstract)" + + abstract member Append : (ISeq<'T>) -> ISeq<'T> + + default this.Append source = Upcast.seq (AppendEnumerable [source; this]) + + interface IEnumerable with + member this.GetEnumerator () : IEnumerator = + let genericEnumerable = Upcast.enumerable this + let genericEnumerator = genericEnumerable.GetEnumerator () + Upcast.enumeratorNonGeneric genericEnumerator + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () + + interface ISeq<'T> with + member __.PushTransform _ = derivedClassShouldImplement () + member __.Fold _ = derivedClassShouldImplement () + + and VanillaEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new VanillaEnumerator<'T,'U>(enumerable.GetEnumerator(), createFold current result pipeIdx, result)) + + interface ISeq<'U> with + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new VanillaEnumerable<'T,'V>(enumerable, ComposedFactory.Combine current next, pipeIdx+1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + Fold.execute f current pipeIdx (Fold.IterateEnumerable enumerable) + and ConcatEnumerable<'T, 'Collection, 'Collections when 'Collection :> seq<'T> and 'Collections :> seq<'Collection>> (sources:'Collections, preEnumerate:'Collections->'Collections) = inherit EnumerableBase<'T>() @@ -499,7 +474,7 @@ namespace Microsoft.FSharp.Collections interface ISeq<'T> with member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable<'T,'V>(this, next, 1)) + Upcast.seq (VanillaEnumerable<'T,'V>(this, next, 1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = Fold.executeThin f (Fold.IterateEnumerable this) @@ -510,14 +485,36 @@ namespace Microsoft.FSharp.Collections override this.Append source = Upcast.seq (AppendEnumerable (source::sources)) - let create enumerable current = - Upcast.seq (Enumerable (enumerable, current, 1)) + type ThinEnumerable<'T>(enumerable:IEnumerable<'T>) = + inherit EnumerableBase<'T>() - module EmptyEnumerable = - type Enumerable<'T> () = - inherit Enumerable.EnumerableBase<'T>() + interface IEnumerable<'T> with + member this.GetEnumerator () = enumerable.GetEnumerator () + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new VanillaEnumerable<'T,'U>(enumerable, next, 1)) - static let singleton = Enumerable<'T>() :> ISeq<'T> + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + Fold.executeThin f (Fold.IterateEnumerable enumerable) + + type DelayedEnumerable<'T>(delayed:unit->ISeq<'T>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'T>() + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = (delayed()).GetEnumerator () + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new DelayedEnumerable<'U>((fun () -> (delayed()).PushTransform next), pipeIdx+1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + (delayed()).Fold f + + type EmptyEnumerable<'T> () = + inherit EnumerableBase<'T>() + + static let singleton = EmptyEnumerable<'T>() :> ISeq<'T> static member Instance = singleton interface IEnumerable<'T> with @@ -527,14 +524,13 @@ namespace Microsoft.FSharp.Collections interface ISeq<'T> with member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable.Enumerable<'T,'V>(this, next, 1)) + Upcast.seq (VanillaEnumerable<'T,'V>(this, next, 1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = Fold.executeThin f (Fold.IterateEnumerable this) - module Array = - type Enumerator<'T,'U>(array:array<'T>, activity:Activity<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, activity) + type ArrayEnumerator<'T,'U>(array:array<'T>, activity:Activity<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, activity) let mutable idx = 0 @@ -556,24 +552,23 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U>(array:array<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit Enumerable.EnumerableBase<'U>() + type ArrayEnumerable<'T,'U>(array:array<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(array, createFold transformFactory result pipeIdx, result)) + Upcast.enumerator (new ArrayEnumerator<'T,'U>(array, createFold transformFactory result pipeIdx, result)) interface ISeq<'U> with member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(array, ComposedFactory.Combine transformFactory next, 1)) + Upcast.seq (new ArrayEnumerable<'T,'V>(array, ComposedFactory.Combine transformFactory next, 1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = Fold.execute f transformFactory pipeIdx (Fold.IterateArray array) - module ResizeArray = - type Enumerator<'T,'U>(array:ResizeArray<'T>, activity:Activity<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, activity) + type ResizeArrayEnumerator<'T,'U>(array:ResizeArray<'T>, activity:Activity<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, activity) let mutable idx = 0 @@ -595,24 +590,23 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U>(resizeArray:ResizeArray<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit Enumerable.EnumerableBase<'U>() + type ResizeArrayEnumerable<'T,'U>(resizeArray:ResizeArray<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(resizeArray, createFold transformFactory result pipeIdx, result)) + Upcast.enumerator (new ResizeArrayEnumerator<'T,'U>(resizeArray, createFold transformFactory result pipeIdx, result)) interface ISeq<'U> with member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(resizeArray, ComposedFactory.Combine transformFactory next, 1)) + Upcast.seq (new ResizeArrayEnumerable<'T,'V>(resizeArray, ComposedFactory.Combine transformFactory next, 1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = Fold.execute f transformFactory pipeIdx (Fold.IterateResizeArray resizeArray) - module List = - type Enumerator<'T,'U>(alist:list<'T>, activity:Activity<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, activity) + type ListEnumerator<'T,'U>(alist:list<'T>, activity:Activity<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, activity) let mutable list = alist @@ -635,27 +629,23 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext list - type Enumerable<'T,'U>(alist:list<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit Enumerable.EnumerableBase<'U>() + type ListEnumerable<'T,'U>(alist:list<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(alist, createFold transformFactory result pipeIdx, result)) + Upcast.enumerator (new ListEnumerator<'T,'U>(alist, createFold transformFactory result pipeIdx, result)) interface ISeq<'U> with member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + Upcast.seq (new ListEnumerable<'T,'V>(alist, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = Fold.execute f transformFactory pipeIdx (Fold.IterateList alist) - let create alist current = - Upcast.seq (Enumerable(alist, current, 1)) - - module Unfold = - type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, activity:Activity<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, activity) + type UnfoldEnumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, activity:Activity<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, activity) let mutable current = state @@ -674,34 +664,22 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit Enumerable.EnumerableBase<'U>() + type UnfoldEnumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, createFold transformFactory result pipeIdx, result)) + Upcast.enumerator (new UnfoldEnumerator<'T,'U,'GeneratorState>(generator, state, createFold transformFactory result pipeIdx, result)) interface ISeq<'U> with member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + Upcast.seq (new UnfoldEnumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = Fold.execute f transformFactory pipeIdx (Fold.IterateUnfold (generator, state)) - module Init = - // 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. - - let getTerminatingIdx (count:Nullable) = + 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 @@ -709,8 +687,8 @@ namespace Microsoft.FSharp.Collections else System.Int32.MaxValue - type Enumerator<'T,'U>(count:Nullable, f:int->'T, activity:Activity<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, activity) + type InitEnumerator<'T,'U>(count:Nullable, f:int->'T, activity:Activity<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, activity) let isSkipping = match box activity with @@ -718,7 +696,7 @@ namespace Microsoft.FSharp.Collections | _ -> fun () -> false let terminatingIdx = - getTerminatingIdx count + getInitTerminatingIdx count let mutable maybeSkipping = true let mutable idx = -1 @@ -751,74 +729,87 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U>(count:Nullable, f:int->'T, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit Enumerable.EnumerableBase<'U>() + type InitEnumerable<'T,'U>(count:Nullable, f:int->'T, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(count, f, createFold transformFactory result pipeIdx, result)) + Upcast.enumerator (new InitEnumerator<'T,'U>(count, f, createFold transformFactory result pipeIdx, result)) interface ISeq<'U> with member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + Upcast.seq (new InitEnumerable<'T,'V>(count, f, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member this.Fold<'Result,'State> (createResult:PipeIdx->Folder<'U,'Result,'State>) = - let terminatingIdx = getTerminatingIdx count + let terminatingIdx = getInitTerminatingIdx count Fold.execute createResult transformFactory pipeIdx (Fold.IterateInit (f, terminatingIdx)) - 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 + // 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 - else - setIndex (!index + 1) + elif !index = unstarted then + setIndex 0 true - ) - member this.Reset() = noReset() - interface System.IDisposable with - member x.Dispose () = () } - - type EnumerableDecider<'T>(count:Nullable, f:int->'T, pipeIdx:PipeIdx) = - inherit Enumerable.EnumerableBase<'T>() + 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 () = () } interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = @@ -829,23 +820,28 @@ namespace Microsoft.FSharp.Collections interface ISeq<'T> with member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable<'T,'V>(count, f, next, pipeIdx+1)) + Upcast.seq (InitEnumerable<'T,'V>(count, f, next, pipeIdx+1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = Fold.executeThin f (Fold.IterateEnumerable (Upcast.enumerable this)) + /// wraps a ResizeArray in the ISeq framework. Care must be taken that the underlying ResizeArray + /// is not modified whilst it can be accessed as the ISeq, 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 funcitonality, then use the ofSeq function instead. [] let ofResizeArrayUnchecked (source:ResizeArray<'T>) : ISeq<'T> = - Upcast.seq (ResizeArray.Enumerable (source, IdentityFactory.Instance, 1)) + Upcast.seq (Wrap.ResizeArrayEnumerable (source, IdentityFactory.Instance, 1)) [] let ofArray (source:array<'T>) : ISeq<'T> = checkNonNull "source" source - Upcast.seq (Array.Enumerable (source, IdentityFactory.Instance, 1)) + Upcast.seq (Wrap.ArrayEnumerable (source, IdentityFactory.Instance, 1)) [] let ofList (source:list<'T>) : ISeq<'T> = - Upcast.seq (List.Enumerable (source, IdentityFactory.Instance, 1)) + Upcast.seq (Wrap.ListEnumerable (source, IdentityFactory.Instance, 1)) [] let ofSeq (source:seq<'T>) : ISeq<'T> = @@ -854,7 +850,7 @@ namespace Microsoft.FSharp.Collections | :? array<'T> as array -> ofArray array | :? list<'T> as list -> ofList list | null -> nullArg "source" - | _ -> Upcast.seq (Enumerable.EnumerableThin<'T> source) + | _ -> Upcast.seq (Wrap.ThinEnumerable<'T> source) [] let inline average (source:ISeq<'T>) = @@ -887,7 +883,7 @@ namespace Microsoft.FSharp.Collections override this.OnDispose () = () }) [] - let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance + let empty<'T> = Wrap.EmptyEnumerable<'T>.Instance [] let exactlyOne (source:ISeq<'T>) : 'T = @@ -933,17 +929,17 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = - Upcast.seq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance, 1)) + Upcast.seq (new Wrap.UnfoldEnumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance, 1)) [] let initInfinite<'T> (f:int->'T) : ISeq<'T> = - Upcast.seq (new Init.EnumerableDecider<'T>(Nullable (), f, 1)) + Upcast.seq (new Wrap.InitEnumerableDecider<'T>(Nullable (), f, 1)) [] let init<'T> (count:int) (f:int->'T) : ISeq<'T> = if count < 0 then invalidArgInputMustBeNonNegative "count" count elif count = 0 then empty else - Upcast.seq (new Init.EnumerableDecider<'T>(Nullable count, f, 1)) + Upcast.seq (new Wrap.InitEnumerableDecider<'T>(Nullable count, f, 1)) [] let inline iter f (source:ISeq<'T>) = @@ -1308,7 +1304,7 @@ namespace Microsoft.FSharp.Collections [] let concat (sources:ISeq<#ISeq<'T>>) : ISeq<'T> = - Upcast.seq (Enumerable.ConcatEnumerable (sources, id)) + Upcast.seq (Wrap.ConcatEnumerable (sources, id)) [] let inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = @@ -1578,12 +1574,12 @@ namespace Microsoft.FSharp.Collections [] let append (source1:ISeq<'T>) (source2: ISeq<'T>) : ISeq<'T> = match source1 with - | :? Enumerable.EnumerableBase<'T> as s -> s.Append source2 - | _ -> Upcast.seq (new Enumerable.AppendEnumerable<_>([source2; source1])) + | :? Wrap.EnumerableBase<'T> as s -> s.Append source2 + | _ -> Upcast.seq (new Wrap.AppendEnumerable<_>([source2; source1])) [] let delay (delayed:unit->ISeq<'T>) = - Upcast.seq (Enumerable.SeqDelayed (delayed, 1)) + Upcast.seq (Wrap.DelayedEnumerable (delayed, 1)) module internal GroupBy = let inline private impl (comparer:IEqualityComparer<'SafeKey>) (keyf:'T->'SafeKey) (getKey:'SafeKey->'Key) (source:ISeq<'T>) = @@ -1820,7 +1816,7 @@ namespace Microsoft.FSharp.Collections interface ISeq<'T> with member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new Enumerable.Enumerable<'T,'U>(cached, next, 1)) + Upcast.seq (new Wrap.VanillaEnumerable<'T,'U>(cached, next, 1)) member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = Fold.executeThin f (Fold.IterateEnumerable cached) From 38f81b93d76b1a2439808020629303001b0e55d3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 27 Mar 2017 12:09:19 +1100 Subject: [PATCH 24/83] Add special handling for length --- src/fsharp/FSharp.Core/iseq.fs | 61 ++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 09c9edb4ea..93d2d34abe 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -428,14 +428,23 @@ namespace Microsoft.FSharp.Collections main.Dispose () active.Dispose () + let length (source:ISeq<_>) = + source.Fold (fun _ -> + upcast { new Folder<'T,int,NoValue>(0,Unchecked.defaultof<_>) with + override this.ProcessNext v = + this.Result <- this.Result + 1 + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + [] type EnumerableBase<'T> () = let derivedClassShouldImplement () = failwith "library implementation error: derived class should implement (should be abstract)" - abstract member Append : (ISeq<'T>) -> ISeq<'T> + abstract member Append : ISeq<'T> -> ISeq<'T> + abstract member Length : unit -> int default this.Append source = Upcast.seq (AppendEnumerable [source; this]) + default this.Length () = length this interface IEnumerable with member this.GetEnumerator () : IEnumerator = @@ -485,9 +494,20 @@ namespace Microsoft.FSharp.Collections override this.Append source = Upcast.seq (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 EnumerableBase<'T>() + override __.Length () = + match enumerable with + | :? ICollection<'T> as a -> a.Count + | _ -> + use e = enumerable.GetEnumerator () + let mutable count = 0 + while e.MoveNext () do + count <- count + 1 + count + interface IEnumerable<'T> with member this.GetEnumerator () = enumerable.GetEnumerator () @@ -501,6 +521,11 @@ namespace Microsoft.FSharp.Collections type DelayedEnumerable<'T>(delayed:unit->ISeq<'T>, pipeIdx:PipeIdx) = inherit EnumerableBase<'T>() + override __.Length () = + match delayed() with + | :? EnumerableBase<'T> as s -> s.Length () + | s -> length s + interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = (delayed()).GetEnumerator () @@ -517,6 +542,8 @@ namespace Microsoft.FSharp.Collections static let singleton = EmptyEnumerable<'T>() :> ISeq<'T> static member Instance = singleton + override __.Length () = 0 + interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = IEnumerator.Empty<'T>() @@ -555,6 +582,12 @@ namespace Microsoft.FSharp.Collections type ArrayEnumerable<'T,'U>(array:array<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() + override this.Length () = + if obj.ReferenceEquals (transformFactory, IdentityFactory<'U>.Instance) then + array.Length + else + length this + interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -593,6 +626,12 @@ namespace Microsoft.FSharp.Collections type ResizeArrayEnumerable<'T,'U>(resizeArray:ResizeArray<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() + override this.Length () = + if obj.ReferenceEquals (transformFactory, IdentityFactory<'U>.Instance) then + resizeArray.Count + else + length this + interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -632,6 +671,12 @@ namespace Microsoft.FSharp.Collections type ListEnumerable<'T,'U>(alist:list<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() + override this.Length () = + if obj.ReferenceEquals (transformFactory, IdentityFactory<'U>.Instance) then + alist.Length + else + length this + interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -811,6 +856,12 @@ namespace Microsoft.FSharp.Collections 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 @@ -1657,11 +1708,9 @@ namespace Microsoft.FSharp.Collections [] let length (source:ISeq<'T>) = - source.Fold (fun _ -> - upcast { new Folder<'T,int,NoValue>(0,Unchecked.defaultof<_>) with - override this.ProcessNext v = - this.Result <- this.Result + 1 - Unchecked.defaultof<_> (* return value unused in Fold context *) }) + match source with + | :? Wrap.EnumerableBase<'T> as s -> s.Length () + | _ -> Wrap.length source [] let toArray (source:ISeq<'T>) = From 8bbc3d1c3ef62ef991238937be25efd9d7cce4a0 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 27 Mar 2017 13:10:26 +1100 Subject: [PATCH 25/83] use UnfoldEnumerable directly in cache --- src/fsharp/FSharp.Core/iseq.fs | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 93d2d34abe..cf90d6f12f 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -144,6 +144,7 @@ namespace Microsoft.FSharp.Collections // is fixed with the compiler then these functions can be removed. let inline seq<'T,'seq when 'seq :> ISeq<'T> and 'seq : not struct> (t:'seq) : ISeq<'T> = (# "" t : ISeq<'T> #) let inline enumerable<'T,'enumerable when 'enumerable :> IEnumerable<'T> and 'enumerable : not struct> (t:'enumerable) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) + let inline enumerableNonGeneric<'enumerable when 'enumerable :> IEnumerable and 'enumerable : not struct> (t:'enumerable) : IEnumerable = (# "" t : IEnumerable #) let inline enumerator<'T,'enumerator when 'enumerator :> IEnumerator<'T> and 'enumerator : not struct> (t:'enumerator) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline enumeratorNonGeneric<'enumerator when 'enumerator :> IEnumerator and 'enumerator : not struct> (t:'enumerator) : IEnumerator = (# "" t : IEnumerator #) let inline outOfBand<'outOfBand when 'outOfBand :> IOutOfBand and 'outOfBand : not struct> (t:'outOfBand) : IOutOfBand = (# "" t : IOutOfBand #) @@ -1831,20 +1832,21 @@ namespace Microsoft.FSharp.Collections enumeratorR <- None // drop it and record finished. | _ -> () - let cached = - 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 sync (fun () -> + 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 - oneStepTo i - if i < prefix.Count then - Some (prefix.[i], i+1) - else - None)) 0 + None) + + let cached = Upcast.seq (new Wrap.UnfoldEnumerable<'T,'T,int>(unfolding, 0, IdentityFactory.Instance, 1)) interface System.IDisposable with member __.Dispose() = @@ -1861,14 +1863,11 @@ namespace Microsoft.FSharp.Collections member __.GetEnumerator() = cached.GetEnumerator() interface System.Collections.IEnumerable with - member __.GetEnumerator() = (cached :> System.Collections.IEnumerable).GetEnumerator() + member __.GetEnumerator() = (Upcast.enumerableNonGeneric cached).GetEnumerator() interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new Wrap.VanillaEnumerable<'T,'U>(cached, next, 1)) - - member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - Fold.executeThin f (Fold.IterateEnumerable cached) + member __.PushTransform next = cached.PushTransform next + member __.Fold f = cached.Fold f member this.Clear() = (this :> IDisposable).Dispose () From 180cbb41423fd5d8fd22a3269821bf9581843d0b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 27 Mar 2017 18:56:37 +1100 Subject: [PATCH 26/83] Added IReadOnlyCollection to length handling --- src/fsharp/FSharp.Core/iseq.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index cf90d6f12f..a10e67b770 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -502,6 +502,7 @@ namespace Microsoft.FSharp.Collections 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 From ad5c0f01afb2652c416537568284759680a41eeb Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 28 Mar 2017 13:13:52 +1100 Subject: [PATCH 27/83] On 'take 0' set halted; check HaltedIdx up front --- src/fsharp/FSharp.Core/iseq.fs | 53 ++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index a10e67b770..d5cfbbd3fd 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -209,10 +209,9 @@ namespace Microsoft.FSharp.Collections member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = use enumerator = enumerable.GetEnumerator () let rec iterate () = - if enumerator.MoveNext () then + if outOfBand.HaltedIdx = 0 && enumerator.MoveNext () then consumer.ProcessNext enumerator.Current |> ignore - if outOfBand.HaltedIdx = 0 then - iterate () + iterate () iterate () [] @@ -221,10 +220,9 @@ namespace Microsoft.FSharp.Collections member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = let array = array let rec iterate idx = - if idx < array.Length then + if outOfBand.HaltedIdx = 0 && idx < array.Length then consumer.ProcessNext array.[idx] |> ignore - if outOfBand.HaltedIdx = 0 then - iterate (idx+1) + iterate (idx+1) iterate 0 [] @@ -233,10 +231,9 @@ namespace Microsoft.FSharp.Collections member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = let array = array let rec iterate idx = - if idx < array.Count then + if outOfBand.HaltedIdx = 0 && idx < array.Count then consumer.ProcessNext array.[idx] |> ignore - if outOfBand.HaltedIdx = 0 then - iterate (idx+1) + iterate (idx+1) iterate 0 [] @@ -245,10 +242,9 @@ namespace Microsoft.FSharp.Collections member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = let rec iterate lst = match lst with - | hd :: tl -> + | hd :: tl when outOfBand.HaltedIdx = 0 -> consumer.ProcessNext hd |> ignore - if outOfBand.HaltedIdx = 0 then - iterate tl + iterate tl | _ -> () iterate alist @@ -258,12 +254,13 @@ namespace Microsoft.FSharp.Collections member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = let generator = generator let rec iterate current = - match generator current with - | Some (item, next) -> - consumer.ProcessNext item |> ignore - if outOfBand.HaltedIdx = 0 then + if outOfBand.HaltedIdx <> 0 then () + else + match generator current with + | Some (item, next) -> + consumer.ProcessNext item |> ignore iterate next - | _ -> () + | _ -> () iterate state [] @@ -697,14 +694,17 @@ namespace Microsoft.FSharp.Collections let mutable current = state let rec moveNext () = - match result.HaltedIdx, generator current with - | 0, Some (item, nextState) -> - current <- nextState - if activity.ProcessNext item then - true - else - moveNext () - | _ -> false + if result.HaltedIdx <> 0 then + false + else + match generator current with + | Some (item, nextState) -> + current <- nextState + if activity.ProcessNext item then + true + else + moveNext () + | _ -> false interface IEnumerator with member __.MoveNext () = @@ -1439,6 +1439,9 @@ namespace Microsoft.FSharp.Collections let take (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = source.PushTransform { new TransformFactory<'T,'T>() with member __.Compose outOfBand pipelineIdx next = + if takeCount = 0 then + outOfBand.StopFurtherProcessing pipelineIdx + upcast { new TransformWithPostProcessing<'T,'U,int>(next,(*count*)0) with // member this.count = this.State override this.ProcessNext (input:'T) : bool = From d971d6c43863c37cd590f74503907e3df3d82fe1 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 28 Mar 2017 14:30:29 +1100 Subject: [PATCH 28/83] Conditional around IReadOnlyCollection --- src/fsharp/FSharp.Core/iseq.fs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index d5cfbbd3fd..dcc9d1e1b5 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -499,7 +499,9 @@ namespace Microsoft.FSharp.Collections override __.Length () = match enumerable with | :? ICollection<'T> as a -> a.Count +#if !FSCORE_PORTABLE_OLD | :? IReadOnlyCollection<'T> as a -> a.Count +#endif | _ -> use e = enumerable.GetEnumerator () let mutable count = 0 From 1ea9e6d603f37f440763c07236dabecc3fc0c31a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 29 Mar 2017 18:19:10 +1100 Subject: [PATCH 29/83] Use InitEnumerable for replicate --- src/fsharp/FSharp.Core/iseq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index dcc9d1e1b5..266fefd877 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1898,7 +1898,7 @@ namespace Microsoft.FSharp.Collections [] let replicate count x = - System.Linq.Enumerable.Repeat(x,count) |> ofSeq + Upcast.seq (new Wrap.InitEnumerable<'T,'T>(Nullable count, (fun _ -> x), IdentityFactory.Instance, 1)) [] let isEmpty (source : ISeq<'T>) = From d97303a5d307464f8cb2c3e426dacc2216075543 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 29 Mar 2017 19:19:34 +1100 Subject: [PATCH 30/83] singleton --- src/fsharp/FSharp.Core/iseq.fs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 266fefd877..0c00212b71 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -248,6 +248,13 @@ namespace Microsoft.FSharp.Collections | _ -> () iterate alist + [] + type IterateSingleton<'T> (item:'T) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = + if outOfBand.HaltedIdx = 0 then + consumer.ProcessNext item |> ignore + [] type IterateUnfold<'S,'T> (generator:'S->option<'T*'S>, state:'S) = interface IIterate<'T> with @@ -601,6 +608,21 @@ namespace Microsoft.FSharp.Collections member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = Fold.execute f transformFactory pipeIdx (Fold.IterateArray array) + type SingletonEnumerable<'T>(item:'T) = + inherit EnumerableBase<'T>() + + override __.Length () = 1 + + interface IEnumerable<'T> with + member this.GetEnumerator () = Upcast.enumerator (new Singleton<'T>(item)) + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new ArrayEnumerable<'T,'U>([|item|], next, 1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + Fold.executeThin f (Fold.IterateSingleton item) + type ResizeArrayEnumerator<'T,'U>(array:ResizeArray<'T>, activity:Activity<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, activity) @@ -2007,7 +2029,7 @@ namespace Microsoft.FSharp.Collections nth i e [] - let singleton x = mkSeq (fun () -> IEnumerator.Singleton x) |> ofSeq + let singleton x = Upcast.seq (new Wrap.SingletonEnumerable<_>(x)) [] let inline sortDescending source = From c402022bbc2fc81e45267333ea9a07554a79412f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 29 Mar 2017 19:26:39 +1100 Subject: [PATCH 31/83] Add ArgumentOutOfRangeException for replicate --- src/fsharp/FSharp.Core/iseq.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 0c00212b71..651d6b70a4 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1920,6 +1920,7 @@ namespace Microsoft.FSharp.Collections [] let replicate count x = + if count < 0 then raise (ArgumentOutOfRangeException "count") Upcast.seq (new Wrap.InitEnumerable<'T,'T>(Nullable count, (fun _ -> x), IdentityFactory.Instance, 1)) [] From 2e4c42ab694a92b428fc95553e20bc01f91c19e9 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 1 Apr 2017 06:24:50 +1100 Subject: [PATCH 32/83] Added thin wrappers for array, list, ResizeArray --- src/fsharp/FSharp.Core/iseq.fs | 73 +++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 651d6b70a4..7592306086 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -590,12 +590,6 @@ namespace Microsoft.FSharp.Collections type ArrayEnumerable<'T,'U>(array:array<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() - override this.Length () = - if obj.ReferenceEquals (transformFactory, IdentityFactory<'U>.Instance) then - array.Length - else - length this - interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -603,11 +597,26 @@ namespace Microsoft.FSharp.Collections interface ISeq<'U> with member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new ArrayEnumerable<'T,'V>(array, ComposedFactory.Combine transformFactory next, 1)) + Upcast.seq (new ArrayEnumerable<'T,'V>(array, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = Fold.execute f transformFactory pipeIdx (Fold.IterateArray array) + type ThinArrayEnumerable<'T>(array:array<'T>) = + inherit EnumerableBase<'T>() + + override __.Length () = array.Length + + interface IEnumerable<'T> with + member this.GetEnumerator () = array.GetEnumerator () + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new ArrayEnumerable<'T,'U>(array, next, 1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + Fold.executeThin f (Fold.IterateArray array) + type SingletonEnumerable<'T>(item:'T) = inherit EnumerableBase<'T>() @@ -649,12 +658,6 @@ namespace Microsoft.FSharp.Collections type ResizeArrayEnumerable<'T,'U>(resizeArray:ResizeArray<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() - override this.Length () = - if obj.ReferenceEquals (transformFactory, IdentityFactory<'U>.Instance) then - resizeArray.Count - else - length this - interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -662,11 +665,26 @@ namespace Microsoft.FSharp.Collections interface ISeq<'U> with member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new ResizeArrayEnumerable<'T,'V>(resizeArray, ComposedFactory.Combine transformFactory next, 1)) + Upcast.seq (new ResizeArrayEnumerable<'T,'V>(resizeArray, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = Fold.execute f transformFactory pipeIdx (Fold.IterateResizeArray resizeArray) + type ThinResizeArrayEnumerable<'T>(resizeArray:ResizeArray<'T>) = + inherit EnumerableBase<'T>() + + override __.Length () = resizeArray.Count + + interface IEnumerable<'T> with + member this.GetEnumerator () = (Upcast.enumerable resizeArray).GetEnumerator () + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new ResizeArrayEnumerable<'T,'U>(resizeArray, next, 1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + Fold.executeThin f (Fold.IterateResizeArray resizeArray) + type ListEnumerator<'T,'U>(alist:list<'T>, activity:Activity<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, activity) @@ -694,12 +712,6 @@ namespace Microsoft.FSharp.Collections type ListEnumerable<'T,'U>(alist:list<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() - override this.Length () = - if obj.ReferenceEquals (transformFactory, IdentityFactory<'U>.Instance) then - alist.Length - else - length this - interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -712,6 +724,21 @@ namespace Microsoft.FSharp.Collections member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = Fold.execute f transformFactory pipeIdx (Fold.IterateList alist) + type ThinListEnumerable<'T>(alist:list<'T>) = + inherit EnumerableBase<'T>() + + override __.Length () = alist.Length + + interface IEnumerable<'T> with + member this.GetEnumerator () = (Upcast.enumerable alist).GetEnumerator () + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new ListEnumerable<'T,'U>(alist, next, 1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + Fold.executeThin f (Fold.IterateList alist) + type UnfoldEnumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, activity:Activity<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, activity) @@ -909,16 +936,16 @@ namespace Microsoft.FSharp.Collections /// performed in this case. If you want this funcitonality, then use the ofSeq function instead. [] let ofResizeArrayUnchecked (source:ResizeArray<'T>) : ISeq<'T> = - Upcast.seq (Wrap.ResizeArrayEnumerable (source, IdentityFactory.Instance, 1)) + Upcast.seq (Wrap.ThinResizeArrayEnumerable<'T> source) [] let ofArray (source:array<'T>) : ISeq<'T> = checkNonNull "source" source - Upcast.seq (Wrap.ArrayEnumerable (source, IdentityFactory.Instance, 1)) + Upcast.seq (Wrap.ThinArrayEnumerable<'T> source) [] let ofList (source:list<'T>) : ISeq<'T> = - Upcast.seq (Wrap.ListEnumerable (source, IdentityFactory.Instance, 1)) + Upcast.seq (Wrap.ThinListEnumerable<'T> source) [] let ofSeq (source:seq<'T>) : ISeq<'T> = From 26e663cfc6754ad3d805c7bb622dad6c080d7514 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 1 Apr 2017 10:59:48 +1100 Subject: [PATCH 33/83] call correct GetEnumerator on array --- src/fsharp/FSharp.Core/iseq.fs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 7592306086..2d2a4999cb 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -458,9 +458,11 @@ namespace Microsoft.FSharp.Collections Upcast.enumeratorNonGeneric genericEnumerator interface IEnumerable<'T> with + // fsharp doesn't allow abstract interface methods member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () interface ISeq<'T> with + // fsharp doesn't allow abstract interface methods member __.PushTransform _ = derivedClassShouldImplement () member __.Fold _ = derivedClassShouldImplement () @@ -517,13 +519,13 @@ namespace Microsoft.FSharp.Collections count interface IEnumerable<'T> with - member this.GetEnumerator () = enumerable.GetEnumerator () + member __.GetEnumerator () = enumerable.GetEnumerator () interface ISeq<'T> with member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new VanillaEnumerable<'T,'U>(enumerable, next, 1)) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = Fold.executeThin f (Fold.IterateEnumerable enumerable) type DelayedEnumerable<'T>(delayed:unit->ISeq<'T>, pipeIdx:PipeIdx) = @@ -541,7 +543,7 @@ namespace Microsoft.FSharp.Collections member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new DelayedEnumerable<'U>((fun () -> (delayed()).PushTransform next), pipeIdx+1)) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = (delayed()).Fold f type EmptyEnumerable<'T> () = @@ -591,7 +593,7 @@ namespace Microsoft.FSharp.Collections inherit EnumerableBase<'U>() interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = + member __.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () Upcast.enumerator (new ArrayEnumerator<'T,'U>(array, createFold transformFactory result pipeIdx, result)) @@ -599,7 +601,7 @@ namespace Microsoft.FSharp.Collections member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new ArrayEnumerable<'T,'V>(array, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + member __.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = Fold.execute f transformFactory pipeIdx (Fold.IterateArray array) type ThinArrayEnumerable<'T>(array:array<'T>) = @@ -608,13 +610,13 @@ namespace Microsoft.FSharp.Collections override __.Length () = array.Length interface IEnumerable<'T> with - member this.GetEnumerator () = array.GetEnumerator () + member __.GetEnumerator () = (Upcast.enumerable array).GetEnumerator () interface ISeq<'T> with member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new ArrayEnumerable<'T,'U>(array, next, 1)) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = Fold.executeThin f (Fold.IterateArray array) type SingletonEnumerable<'T>(item:'T) = @@ -667,7 +669,7 @@ namespace Microsoft.FSharp.Collections member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new ResizeArrayEnumerable<'T,'V>(resizeArray, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + member __.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = Fold.execute f transformFactory pipeIdx (Fold.IterateResizeArray resizeArray) type ThinResizeArrayEnumerable<'T>(resizeArray:ResizeArray<'T>) = @@ -676,13 +678,13 @@ namespace Microsoft.FSharp.Collections override __.Length () = resizeArray.Count interface IEnumerable<'T> with - member this.GetEnumerator () = (Upcast.enumerable resizeArray).GetEnumerator () + member __.GetEnumerator () = (Upcast.enumerable resizeArray).GetEnumerator () interface ISeq<'T> with member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new ResizeArrayEnumerable<'T,'U>(resizeArray, next, 1)) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = Fold.executeThin f (Fold.IterateResizeArray resizeArray) type ListEnumerator<'T,'U>(alist:list<'T>, activity:Activity<'T,'U>, result:Result<'U>) = @@ -730,13 +732,13 @@ namespace Microsoft.FSharp.Collections override __.Length () = alist.Length interface IEnumerable<'T> with - member this.GetEnumerator () = (Upcast.enumerable alist).GetEnumerator () + member __.GetEnumerator () = (Upcast.enumerable alist).GetEnumerator () interface ISeq<'T> with member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new ListEnumerable<'T,'U>(alist, next, 1)) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = Fold.executeThin f (Fold.IterateList alist) type UnfoldEnumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, activity:Activity<'T,'U>, result:Result<'U>) = From 2e178137ab421f939d620b6eb0b2c6ee16432870 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 1 Apr 2017 12:56:14 +1100 Subject: [PATCH 34/83] scan use singleton --- src/fsharp/FSharp.Core/iseq.fs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 2d2a4999cb..040ab0d144 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1412,9 +1412,12 @@ namespace Microsoft.FSharp.Collections let concat (sources:ISeq<#ISeq<'T>>) : ISeq<'T> = Upcast.seq (Wrap.ConcatEnumerable (sources, id)) + [] + let singleton x = Upcast.seq (new Wrap.SingletonEnumerable<_>(x)) + [] let inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = - let head = ofSeq [| initialState |] + let head = singleton initialState let tail = source.PushTransform { new TransformFactory<'T,'State>() with override __.Compose _ _ next = @@ -2058,9 +2061,6 @@ namespace Microsoft.FSharp.Collections use e = source.GetEnumerator() nth i e - [] - let singleton x = Upcast.seq (new Wrap.SingletonEnumerable<_>(x)) - [] let inline sortDescending source = let inline compareDescending a b = compare b a From ae10fd31c4d16ce507e89a943c5d026255545e4e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 1 Apr 2017 15:02:30 +1100 Subject: [PATCH 35/83] Created Fold for Concat --- src/fsharp/FSharp.Core/iseq.fs | 208 ++++++++++++++++++++------------- 1 file changed, 125 insertions(+), 83 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 040ab0d144..763284334b 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -330,6 +330,29 @@ namespace Microsoft.FSharp.Collections finally result.ChainDispose (&stopTailCall) + let executeConcat<'T,'U,'Result,'State,'Collection when 'Collection :> ISeq<'T>>(createFolder:PipeIdx->Folder<'U,'Result,'State>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (sources:ISeq<'Collection>) = + let mutable stopTailCall = () + let result = createFolder (pipeIdx+1) + let consumer = createFold transformFactory result pipeIdx + + try + let common = + { new Folder<'T,NoValue,NoValue>(Unchecked.defaultof<_>,Unchecked.defaultof<_>) with + override me.ProcessNext value = consumer.ProcessNext value } + + sources.Fold (fun _ -> + { new Folder<'Collection,NoValue,NoValue>(Unchecked.defaultof<_>,Unchecked.defaultof<_>) with + override me.ProcessNext value = + value.Fold (fun _ -> common) |> ignore + me.HaltedIdx <- common.HaltedIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) }) |> ignore + + consumer.ChainComplete (&stopTailCall, result.HaltedIdx) + result.Result + + finally + result.ChainDispose (&stopTailCall) + module Wrap = type EmptyEnumerator<'T>() = let current () = failwith "library implementation error: Current should never be called" @@ -395,43 +418,68 @@ namespace Microsoft.FSharp.Collections let mutable stopTailCall = () activity.ChainDispose (&stopTailCall) - type ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = - let mutable state = SeqProcessNextStates.NotStarted + type ConcatEnumerator<'T,'U,'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>, activity:Activity<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, activity) + let main = sources.GetEnumerator () let mutable active = EmptyEnumerators.Element let rec moveNext () = - if active.MoveNext () then - true - elif main.MoveNext () then - active.Dispose () - active <- main.Current.GetEnumerator () - moveNext () + if result.HaltedIdx <> 0 then false else - state <- SeqProcessNextStates.Finished - false - - interface IEnumerator<'T> with - member __.Current = - if state = SeqProcessNextStates.InProcess then active.Current + if active.MoveNext () then + if activity.ProcessNext active.Current then + true + else + moveNext () + elif main.MoveNext () then + active.Dispose () + active <- main.Current.GetEnumerator () + moveNext () else - match state with - | SeqProcessNextStates.NotStarted -> notStarted() - | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> failwith "library implementation error: all states should have been handled" + result.SeqState <- SeqProcessNextStates.Finished + let mutable stopTailCall = () + activity.ChainComplete (&stopTailCall, result.HaltedIdx) + false interface IEnumerator with - member this.Current = box ((Upcast.enumerator this)).Current member __.MoveNext () = - state <- SeqProcessNextStates.InProcess + result.SeqState <- SeqProcessNextStates.InProcess moveNext () - member __.Reset () = noReset () interface IDisposable with member __.Dispose () = - main.Dispose () - active.Dispose () + try + main.Dispose () + active.Dispose () + finally + let mutable stopTailCall = () + activity.ChainDispose (&stopTailCall) + + type ListEnumerator<'T,'U>(alist:list<'T>, activity:Activity<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, activity) + + 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 <- SeqProcessNextStates.Finished + let mutable stopTailCall = () + activity.ChainComplete (&stopTailCall, result.HaltedIdx) + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext list let length (source:ISeq<_>) = source.Fold (fun _ -> @@ -481,26 +529,74 @@ namespace Microsoft.FSharp.Collections member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = Fold.execute f current pipeIdx (Fold.IterateEnumerable enumerable) - and ConcatEnumerable<'T, 'Collection, 'Collections when 'Collection :> seq<'T> and 'Collections :> seq<'Collection>> (sources:'Collections, preEnumerate:'Collections->'Collections) = + and ConcatEnumerable<'T,'U,'Collection when 'Collection :> ISeq<'T>> (sources:ISeq<'Collection>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() + + interface IEnumerable<'U> with + member __.GetEnumerator () : IEnumerator<'U> = + System.Console.WriteLine "ThinConcatEnumerable.GetEnumerator" + let result = Result<'U> () + Upcast.enumerator (new ConcatEnumerator<'T,'U,'Collection>(sources, createFold current result pipeIdx, result)) + + interface ISeq<'U> with + member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new ConcatEnumerable<'T,'V,'Collection>(sources, ComposedFactory.Combine current next, pipeIdx+1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + Fold.executeConcat f current pipeIdx sources + + and ThinConcatEnumerable<'T, 'Sources, 'Collection when 'Collection :> ISeq<'T>> (sources:'Sources, preEnumerate:'Sources->ISeq<'Collection>) = inherit EnumerableBase<'T>() interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - Upcast.enumerator (new ConcatEnumerator<_,_> (preEnumerate sources)) + System.Console.WriteLine "ThinConcatEnumerable.GetEnumerator" + let result = Result<'T> () + Upcast.enumerator (new ConcatEnumerator<'T,'T,'Collection> (preEnumerate sources, createFold IdentityFactory.Instance result 1, result)) interface ISeq<'T> with member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (VanillaEnumerable<'T,'V>(this, next, 1)) + Upcast.seq (ConcatEnumerable<'T,'V,'Collection>(preEnumerate sources, next, 1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - Fold.executeThin f (Fold.IterateEnumerable this) + Fold.executeConcat f IdentityFactory.Instance 1 (preEnumerate sources) and AppendEnumerable<'T> (sources:list>) = - inherit ConcatEnumerable<'T, ISeq<'T>, list>>(sources, List.rev) + inherit ThinConcatEnumerable<'T, list>, ISeq<'T>>(sources, fun sources -> Upcast.seq (ThinListEnumerable>(List.rev sources))) override this.Append source = Upcast.seq (AppendEnumerable (source::sources)) + and ThinListEnumerable<'T>(alist:list<'T>) = + inherit EnumerableBase<'T>() + + override __.Length () = alist.Length + + interface IEnumerable<'T> with + member __.GetEnumerator () = (Upcast.enumerable alist).GetEnumerator () + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new ListEnumerable<'T,'U>(alist, next, 1)) + + member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + Fold.executeThin f (Fold.IterateList alist) + + and ListEnumerable<'T,'U>(alist:list<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new ListEnumerator<'T,'U>(alist, createFold transformFactory result pipeIdx, result)) + + interface ISeq<'U> with + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new ListEnumerable<'T,'V>(alist, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + Fold.execute f transformFactory pipeIdx (Fold.IterateList alist) + /// ThinEnumerable is used when the IEnumerable provided to ofSeq is neither an array or a list type ThinEnumerable<'T>(enumerable:IEnumerable<'T>) = inherit EnumerableBase<'T>() @@ -687,60 +783,6 @@ namespace Microsoft.FSharp.Collections member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = Fold.executeThin f (Fold.IterateResizeArray resizeArray) - type ListEnumerator<'T,'U>(alist:list<'T>, activity:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, activity) - - 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 <- SeqProcessNextStates.Finished - let mutable stopTailCall = () - activity.ChainComplete (&stopTailCall, result.HaltedIdx) - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext list - - type ListEnumerable<'T,'U>(alist:list<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Upcast.enumerator (new ListEnumerator<'T,'U>(alist, createFold transformFactory result pipeIdx, result)) - - interface ISeq<'U> with - member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new ListEnumerable<'T,'V>(alist, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - Fold.execute f transformFactory pipeIdx (Fold.IterateList alist) - - type ThinListEnumerable<'T>(alist:list<'T>) = - inherit EnumerableBase<'T>() - - override __.Length () = alist.Length - - interface IEnumerable<'T> with - member __.GetEnumerator () = (Upcast.enumerable alist).GetEnumerator () - - interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new ListEnumerable<'T,'U>(alist, next, 1)) - - member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - Fold.executeThin f (Fold.IterateList alist) - type UnfoldEnumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, activity:Activity<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, activity) @@ -1410,7 +1452,7 @@ namespace Microsoft.FSharp.Collections [] let concat (sources:ISeq<#ISeq<'T>>) : ISeq<'T> = - Upcast.seq (Wrap.ConcatEnumerable (sources, id)) + Upcast.seq (Wrap.ThinConcatEnumerable (sources, id)) [] let singleton x = Upcast.seq (new Wrap.SingletonEnumerable<_>(x)) From 760e1267aabf976464fbb6499dbe4956f5787b63 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 1 Apr 2017 18:00:15 +1100 Subject: [PATCH 36/83] Removed debugging WriteLines --- src/fsharp/FSharp.Core/iseq.fs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 763284334b..2395d8c67b 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -534,7 +534,6 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member __.GetEnumerator () : IEnumerator<'U> = - System.Console.WriteLine "ThinConcatEnumerable.GetEnumerator" let result = Result<'U> () Upcast.enumerator (new ConcatEnumerator<'T,'U,'Collection>(sources, createFold current result pipeIdx, result)) @@ -550,7 +549,6 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - System.Console.WriteLine "ThinConcatEnumerable.GetEnumerator" let result = Result<'T> () Upcast.enumerator (new ConcatEnumerator<'T,'T,'Collection> (preEnumerate sources, createFold IdentityFactory.Instance result 1, result)) From cb202031e5dc6610342a398c2e9a80e34172318a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 1 Apr 2017 18:29:43 +1100 Subject: [PATCH 37/83] Added executeConcatThin --- src/fsharp/FSharp.Core/iseq.fs | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 2395d8c67b..7b2ac0bece 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -330,11 +330,10 @@ namespace Microsoft.FSharp.Collections finally result.ChainDispose (&stopTailCall) - let executeConcat<'T,'U,'Result,'State,'Collection when 'Collection :> ISeq<'T>>(createFolder:PipeIdx->Folder<'U,'Result,'State>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (sources:ISeq<'Collection>) = + let executeConcat<'T,'U,'Result,'State,'Collection when 'Collection :> ISeq<'T>> (createFolder:PipeIdx->Folder<'U,'Result,'State>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (sources:ISeq<'Collection>) = let mutable stopTailCall = () let result = createFolder (pipeIdx+1) let consumer = createFold transformFactory result pipeIdx - try let common = { new Folder<'T,NoValue,NoValue>(Unchecked.defaultof<_>,Unchecked.defaultof<_>) with @@ -349,7 +348,26 @@ namespace Microsoft.FSharp.Collections consumer.ChainComplete (&stopTailCall, result.HaltedIdx) result.Result + finally + result.ChainDispose (&stopTailCall) + + let executeConcatThin<'T,'Result,'State,'Collection when 'Collection :> ISeq<'T>> (createFolder:PipeIdx->Folder<'T,'Result,'State>) (sources:ISeq<'Collection>) = + let mutable stopTailCall = () + let result = createFolder 1 + try + let common = + { new Folder<'T,NoValue,NoValue>(Unchecked.defaultof<_>,Unchecked.defaultof<_>) with + override me.ProcessNext value = result.ProcessNext value } + sources.Fold (fun _ -> + { new Folder<'Collection,NoValue,NoValue>(Unchecked.defaultof<_>,Unchecked.defaultof<_>) with + override me.ProcessNext value = + value.Fold (fun _ -> common) |> ignore + me.HaltedIdx <- common.HaltedIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) }) |> ignore + + result.ChainComplete (&stopTailCall, result.HaltedIdx) + result.Result finally result.ChainDispose (&stopTailCall) @@ -557,7 +575,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (ConcatEnumerable<'T,'V,'Collection>(preEnumerate sources, next, 1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - Fold.executeConcat f IdentityFactory.Instance 1 (preEnumerate sources) + Fold.executeConcatThin f (preEnumerate sources) and AppendEnumerable<'T> (sources:list>) = inherit ThinConcatEnumerable<'T, list>, ISeq<'T>>(sources, fun sources -> Upcast.seq (ThinListEnumerable>(List.rev sources))) From ca933694ec5ec2ab23b2bca81b4ee8de604402a0 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 5 Apr 2017 19:00:18 +1000 Subject: [PATCH 38/83] Cleaning API surface; removed stopTailCall --- .../SurfaceArea.net40.fs | 24 +++--- src/fsharp/FSharp.Core/iseq.fs | 75 ++++++++----------- src/fsharp/FSharp.Core/iseq.fsi | 4 +- 3 files changed, 45 insertions(+), 58 deletions(-) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs index 116f99f99f..a7bf1b985d 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs @@ -284,16 +284,16 @@ Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Boolean Equals(System.Obj Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule+Core+Activity: System.String ToString() Microsoft.FSharp.Collections.ISeqModule+Core+Activity: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainDispose() Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Boolean ProcessNext(T) Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: System.String ToString() Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void .ctor() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainDispose() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() @@ -303,8 +303,8 @@ Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResul Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TResult Result Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TState State Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void .ctor(TResult, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnDispose() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) @@ -317,8 +317,8 @@ Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: System. Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: TResult Result Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: TState State Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void .ctor(TResult, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainDispose() Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+IOutOfBand: Void StopFurtherProcessing(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]: ISeq`1 PushTransform[TResult](TransformFactory`2) @@ -340,8 +340,8 @@ Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TRe Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: TState State Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void .ctor(Activity, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnDispose() Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Boolean Equals(System.Object) @@ -351,8 +351,8 @@ Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Syst Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: TState State Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void .ctor(Activity, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainDispose() Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: System.String ToString() diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 7b2ac0bece..4432ac481e 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -48,8 +48,8 @@ namespace Microsoft.FSharp.Collections [] type Activity() = - abstract ChainComplete : stopTailCall:byref * PipeIdx -> unit - abstract ChainDispose : stopTailCall:byref -> unit + abstract ChainComplete : PipeIdx -> unit + abstract ChainDispose : unit -> unit [] type Activity<'T,'U> () = @@ -69,10 +69,10 @@ namespace Microsoft.FSharp.Collections val mutable State : 'State val Next : Activity - override this.ChainComplete (stopTailCall, terminatingIdx) = - this.Next.ChainComplete (&stopTailCall, terminatingIdx) - override this.ChainDispose stopTailCall = - this.Next.ChainDispose (&stopTailCall) + override this.ChainComplete terminatingIdx = + this.Next.ChainComplete terminatingIdx + override this.ChainDispose () = + this.Next.ChainDispose () [] type TransformWithPostProcessing<'T,'U,'State>(next:Activity, initState:'State) = @@ -81,12 +81,12 @@ namespace Microsoft.FSharp.Collections abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit - override this.ChainComplete (stopTailCall, terminatingIdx) = + override this.ChainComplete terminatingIdx = this.OnComplete terminatingIdx - this.Next.ChainComplete (&stopTailCall, terminatingIdx) - override this.ChainDispose stopTailCall = + this.Next.ChainComplete terminatingIdx + override this.ChainDispose () = try this.OnDispose () - finally this.Next.ChainDispose (&stopTailCall) + finally this.Next.ChainDispose () [] type Folder<'T,'Result,'State> = @@ -107,8 +107,8 @@ namespace Microsoft.FSharp.Collections Result = initalResult } - override this.ChainComplete (_,_) = () - override this.ChainDispose _ = () + override this.ChainComplete _ = () + override this.ChainDispose () = () [] type FolderWithPostProcessing<'T,'Result,'State>(initResult,initState) = @@ -117,9 +117,9 @@ namespace Microsoft.FSharp.Collections abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit - override this.ChainComplete (stopTailCall, terminatingIdx) = + override this.ChainComplete terminatingIdx = this.OnComplete terminatingIdx - override this.ChainDispose _ = + override this.ChainDispose () = this.OnDispose () [] @@ -307,31 +307,28 @@ namespace Microsoft.FSharp.Collections // execute, and it's companion, executeThin, are hosting functions that ensure the correct sequence // of creation, iteration and disposal for the pipeline let execute (createFolder:PipeIdx->Folder<'U,'Result,'State>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (executeOn:#IIterate<'T>) = - let mutable stopTailCall = () let result = createFolder (pipeIdx+1) let consumer = createFold transformFactory result pipeIdx try executeOn.Iterate result consumer - consumer.ChainComplete (&stopTailCall, result.HaltedIdx) + consumer.ChainComplete result.HaltedIdx result.Result finally - consumer.ChainDispose (&stopTailCall) + consumer.ChainDispose () // executeThin is a specialization of execute, provided as a performance optimization, that can // be used when a sequence has been wrapped in an ISeq, but hasn't had an items added to its pipeline // i.e. a container that has ISeq.ofSeq applied. let executeThin (createFolder:PipeIdx->Folder<'T,'Result,'State>) (executeOn:#IIterate<'T>) = - let mutable stopTailCall = () let result = createFolder 1 try executeOn.Iterate result result - result.ChainComplete (&stopTailCall, result.HaltedIdx) + result.ChainComplete result.HaltedIdx result.Result finally - result.ChainDispose (&stopTailCall) + result.ChainDispose () let executeConcat<'T,'U,'Result,'State,'Collection when 'Collection :> ISeq<'T>> (createFolder:PipeIdx->Folder<'U,'Result,'State>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (sources:ISeq<'Collection>) = - let mutable stopTailCall = () let result = createFolder (pipeIdx+1) let consumer = createFold transformFactory result pipeIdx try @@ -346,13 +343,12 @@ namespace Microsoft.FSharp.Collections me.HaltedIdx <- common.HaltedIdx Unchecked.defaultof<_> (* return value unused in Fold context *) }) |> ignore - consumer.ChainComplete (&stopTailCall, result.HaltedIdx) + consumer.ChainComplete result.HaltedIdx result.Result finally - result.ChainDispose (&stopTailCall) + result.ChainDispose () let executeConcatThin<'T,'Result,'State,'Collection when 'Collection :> ISeq<'T>> (createFolder:PipeIdx->Folder<'T,'Result,'State>) (sources:ISeq<'Collection>) = - let mutable stopTailCall = () let result = createFolder 1 try let common = @@ -366,10 +362,10 @@ namespace Microsoft.FSharp.Collections me.HaltedIdx <- common.HaltedIdx Unchecked.defaultof<_> (* return value unused in Fold context *) }) |> ignore - result.ChainComplete (&stopTailCall, result.HaltedIdx) + result.ChainComplete result.HaltedIdx result.Result finally - result.ChainDispose (&stopTailCall) + result.ChainDispose () module Wrap = type EmptyEnumerator<'T>() = @@ -391,8 +387,7 @@ namespace Microsoft.FSharp.Collections type EnumeratorBase<'T>(result:Result<'T>, activity:Activity) = interface IDisposable with member __.Dispose () : unit = - let mutable stopTailCall = () - activity.ChainDispose (&stopTailCall) + activity.ChainDispose () interface IEnumerator with member this.Current : obj = box ((Upcast.enumerator this)).Current @@ -419,8 +414,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - let mutable stopTailCall = () - activity.ChainComplete (&stopTailCall, result.HaltedIdx) + activity.ChainComplete result.HaltedIdx false interface IEnumerator with @@ -433,8 +427,7 @@ namespace Microsoft.FSharp.Collections try source.Dispose () finally - let mutable stopTailCall = () - activity.ChainDispose (&stopTailCall) + activity.ChainDispose () type ConcatEnumerator<'T,'U,'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>, activity:Activity<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, activity) @@ -457,8 +450,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - let mutable stopTailCall = () - activity.ChainComplete (&stopTailCall, result.HaltedIdx) + activity.ChainComplete result.HaltedIdx false interface IEnumerator with @@ -472,8 +464,7 @@ namespace Microsoft.FSharp.Collections main.Dispose () active.Dispose () finally - let mutable stopTailCall = () - activity.ChainDispose (&stopTailCall) + activity.ChainDispose () type ListEnumerator<'T,'U>(alist:list<'T>, activity:Activity<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, activity) @@ -490,8 +481,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - let mutable stopTailCall = () - activity.ChainComplete (&stopTailCall, result.HaltedIdx) + activity.ChainComplete result.HaltedIdx false interface IEnumerator with @@ -692,8 +682,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - let mutable stopTailCall = () - activity.ChainComplete (&stopTailCall, result.HaltedIdx) + activity.ChainComplete result.HaltedIdx false interface IEnumerator with @@ -760,8 +749,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - let mutable stopTailCall = () - activity.ChainComplete (&stopTailCall, result.HaltedIdx) + activity.ChainComplete result.HaltedIdx false interface IEnumerator with @@ -878,8 +866,7 @@ namespace Microsoft.FSharp.Collections raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else result.SeqState <- SeqProcessNextStates.Finished - let mutable stopTailCall = () - activity.ChainComplete (&stopTailCall, result.HaltedIdx) + activity.ChainComplete result.HaltedIdx false interface IEnumerator with diff --git a/src/fsharp/FSharp.Core/iseq.fsi b/src/fsharp/FSharp.Core/iseq.fsi index 69917c1064..a7f24719ea 100644 --- a/src/fsharp/FSharp.Core/iseq.fsi +++ b/src/fsharp/FSharp.Core/iseq.fsi @@ -56,10 +56,10 @@ namespace Microsoft.FSharp.Collections /// 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 : stopTailCall:byref*PipeIdx -> unit + abstract ChainComplete : PipeIdx -> unit /// OnDispose is used to cleanup the stream. It is always called at the last operation /// after the enumeration has completed. - abstract ChainDispose : stopTailCall:byref -> unit + abstract ChainDispose : unit -> unit /// Activity is the base class of all elements within the pipeline [] From 8c4fb65c2b6f851f53d4da2c107e3521718afa4e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 5 Apr 2017 20:01:24 +1000 Subject: [PATCH 39/83] Cleaning API surface; remove 'State from Fold --- src/fsharp/FSharp.Core/iseq.fs | 119 +++++++++++++++++--------------- src/fsharp/FSharp.Core/iseq.fsi | 18 +++-- 2 files changed, 77 insertions(+), 60 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 4432ac481e..8cd288a3bc 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -89,20 +89,18 @@ namespace Microsoft.FSharp.Collections finally this.Next.ChainDispose () [] - type Folder<'T,'Result,'State> = + type Folder<'T,'Result> = inherit Activity<'T,'T> val mutable Result : 'Result - val mutable State : 'State val mutable HaltedIdx : int member this.StopFurtherProcessing pipeIdx = this.HaltedIdx <- pipeIdx interface IOutOfBand with member this.StopFurtherProcessing pipeIdx = this.StopFurtherProcessing pipeIdx - new (initalResult,initState) = { + new (initalResult) = { inherit Activity<'T,'T>() - State = initState HaltedIdx = 0 Result = initalResult } @@ -110,9 +108,20 @@ namespace Microsoft.FSharp.Collections override this.ChainComplete _ = () override this.ChainDispose () = () + [] + type FolderWithState<'T,'Result,'State> = + inherit Folder<'T,'Result> + + val mutable State : 'State + + new (initalResult,initState) = { + inherit Folder<'T,'Result>(initalResult) + State = initState + } + [] type FolderWithPostProcessing<'T,'Result,'State>(initResult,initState) = - inherit Folder<'T,'Result,'State>(initResult,initState) + inherit FolderWithState<'T,'Result,'State>(initResult,initState) abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit @@ -129,7 +138,7 @@ namespace Microsoft.FSharp.Collections type ISeq<'T> = inherit IEnumerable<'T> abstract member PushTransform<'U> : TransformFactory<'T,'U> -> ISeq<'U> - abstract member Fold<'Result,'State> : f:(PipeIdx->Folder<'T,'Result,'State>) -> 'Result + abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result open Core @@ -149,7 +158,7 @@ namespace Microsoft.FSharp.Collections let inline enumeratorNonGeneric<'enumerator when 'enumerator :> IEnumerator and 'enumerator : not struct> (t:'enumerator) : IEnumerator = (# "" t : IEnumerator #) let inline outOfBand<'outOfBand when 'outOfBand :> IOutOfBand and 'outOfBand : not struct> (t:'outOfBand) : IOutOfBand = (# "" t : IOutOfBand #) - let createFold (factory:TransformFactory<_,_>) (folder:Folder<_,_,_>) pipeIdx = + let createFold (factory:TransformFactory<_,_>) (folder:Folder<_,_>) pipeIdx = factory.Compose (Upcast.outOfBand folder) pipeIdx folder let inline valueComparer<'T when 'T : equality> ()= @@ -184,7 +193,7 @@ namespace Microsoft.FSharp.Collections | Finished = 2 type Result<'T>() = - inherit Folder<'T,'T,NoValue>(Unchecked.defaultof<'T>,Unchecked.defaultof) + inherit Folder<'T,'T>(Unchecked.defaultof<'T>) member val SeqState = SeqProcessNextStates.NotStarted with get, set @@ -201,12 +210,12 @@ namespace Microsoft.FSharp.Collections // each time one of these were called. This has been an optimization to minimize the impact // on very small collections. type IIterate<'T> = - abstract Iterate<'U,'Result,'State> : outOfBand:Folder<'U,'Result,'State> -> consumer:Activity<'T,'U> -> unit + abstract Iterate<'U,'Result,'State> : outOfBand:Folder<'U,'Result> -> consumer:Activity<'T,'U> -> unit [] type IterateEnumerable<'T> (enumerable:IEnumerable<'T>) = interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = + member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = use enumerator = enumerable.GetEnumerator () let rec iterate () = if outOfBand.HaltedIdx = 0 && enumerator.MoveNext () then @@ -217,7 +226,7 @@ namespace Microsoft.FSharp.Collections [] type IterateArray<'T> (array:array<'T>) = interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = + member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = let array = array let rec iterate idx = if outOfBand.HaltedIdx = 0 && idx < array.Length then @@ -228,7 +237,7 @@ namespace Microsoft.FSharp.Collections [] type IterateResizeArray<'T> (array:ResizeArray<'T>) = interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = + member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = let array = array let rec iterate idx = if outOfBand.HaltedIdx = 0 && idx < array.Count then @@ -239,7 +248,7 @@ namespace Microsoft.FSharp.Collections [] type IterateList<'T> (alist:list<'T>) = interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = + member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = let rec iterate lst = match lst with | hd :: tl when outOfBand.HaltedIdx = 0 -> @@ -251,14 +260,14 @@ namespace Microsoft.FSharp.Collections [] type IterateSingleton<'T> (item:'T) = interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = + member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = if outOfBand.HaltedIdx = 0 then consumer.ProcessNext item |> ignore [] type IterateUnfold<'S,'T> (generator:'S->option<'T*'S>, state:'S) = interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = + member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = let generator = generator let rec iterate current = if outOfBand.HaltedIdx <> 0 then () @@ -273,7 +282,7 @@ namespace Microsoft.FSharp.Collections [] type IterateInit<'T> (f:int->'T, terminatingIdx:int) = interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = + member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = let terminatingIdx = terminatingIdx let f = f @@ -306,7 +315,7 @@ namespace Microsoft.FSharp.Collections // execute, and it's companion, executeThin, are hosting functions that ensure the correct sequence // of creation, iteration and disposal for the pipeline - let execute (createFolder:PipeIdx->Folder<'U,'Result,'State>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (executeOn:#IIterate<'T>) = + let execute (createFolder:PipeIdx->Folder<'U,'Result>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (executeOn:#IIterate<'T>) = let result = createFolder (pipeIdx+1) let consumer = createFold transformFactory result pipeIdx try @@ -319,7 +328,7 @@ namespace Microsoft.FSharp.Collections // executeThin is a specialization of execute, provided as a performance optimization, that can // be used when a sequence has been wrapped in an ISeq, but hasn't had an items added to its pipeline // i.e. a container that has ISeq.ofSeq applied. - let executeThin (createFolder:PipeIdx->Folder<'T,'Result,'State>) (executeOn:#IIterate<'T>) = + let executeThin (createFolder:PipeIdx->Folder<'T,'Result>) (executeOn:#IIterate<'T>) = let result = createFolder 1 try executeOn.Iterate result result @@ -328,16 +337,16 @@ namespace Microsoft.FSharp.Collections finally result.ChainDispose () - let executeConcat<'T,'U,'Result,'State,'Collection when 'Collection :> ISeq<'T>> (createFolder:PipeIdx->Folder<'U,'Result,'State>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (sources:ISeq<'Collection>) = + let executeConcat<'T,'U,'Result,'State,'Collection when 'Collection :> ISeq<'T>> (createFolder:PipeIdx->Folder<'U,'Result>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (sources:ISeq<'Collection>) = let result = createFolder (pipeIdx+1) let consumer = createFold transformFactory result pipeIdx try - let common = - { new Folder<'T,NoValue,NoValue>(Unchecked.defaultof<_>,Unchecked.defaultof<_>) with - override me.ProcessNext value = consumer.ProcessNext value } + let common = + { new Folder<'T,NoValue>(Unchecked.defaultof<_>) with + override me.ProcessNext value = consumer.ProcessNext value } sources.Fold (fun _ -> - { new Folder<'Collection,NoValue,NoValue>(Unchecked.defaultof<_>,Unchecked.defaultof<_>) with + { new Folder<'Collection,NoValue>(Unchecked.defaultof<_>) with override me.ProcessNext value = value.Fold (fun _ -> common) |> ignore me.HaltedIdx <- common.HaltedIdx @@ -348,15 +357,15 @@ namespace Microsoft.FSharp.Collections finally result.ChainDispose () - let executeConcatThin<'T,'Result,'State,'Collection when 'Collection :> ISeq<'T>> (createFolder:PipeIdx->Folder<'T,'Result,'State>) (sources:ISeq<'Collection>) = + let executeConcatThin<'T,'Result,'State,'Collection when 'Collection :> ISeq<'T>> (createFolder:PipeIdx->Folder<'T,'Result>) (sources:ISeq<'Collection>) = let result = createFolder 1 try let common = - { new Folder<'T,NoValue,NoValue>(Unchecked.defaultof<_>,Unchecked.defaultof<_>) with + { new Folder<'T,NoValue>(Unchecked.defaultof<_>) with override me.ProcessNext value = result.ProcessNext value } sources.Fold (fun _ -> - { new Folder<'Collection,NoValue,NoValue>(Unchecked.defaultof<_>,Unchecked.defaultof<_>) with + { new Folder<'Collection,NoValue>(Unchecked.defaultof<_>) with override me.ProcessNext value = value.Fold (fun _ -> common) |> ignore me.HaltedIdx <- common.HaltedIdx @@ -491,7 +500,7 @@ namespace Microsoft.FSharp.Collections let length (source:ISeq<_>) = source.Fold (fun _ -> - upcast { new Folder<'T,int,NoValue>(0,Unchecked.defaultof<_>) with + { new Folder<'T,int>(0) with override this.ProcessNext v = this.Result <- this.Result + 1 Unchecked.defaultof<_> (* return value unused in Fold context *) }) @@ -534,7 +543,7 @@ namespace Microsoft.FSharp.Collections member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new VanillaEnumerable<'T,'V>(enumerable, ComposedFactory.Combine current next, pipeIdx+1)) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = Fold.execute f current pipeIdx (Fold.IterateEnumerable enumerable) and ConcatEnumerable<'T,'U,'Collection when 'Collection :> ISeq<'T>> (sources:ISeq<'Collection>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = @@ -549,7 +558,7 @@ namespace Microsoft.FSharp.Collections member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new ConcatEnumerable<'T,'V,'Collection>(sources, ComposedFactory.Combine current next, pipeIdx+1)) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = Fold.executeConcat f current pipeIdx sources and ThinConcatEnumerable<'T, 'Sources, 'Collection when 'Collection :> ISeq<'T>> (sources:'Sources, preEnumerate:'Sources->ISeq<'Collection>) = @@ -564,7 +573,7 @@ namespace Microsoft.FSharp.Collections member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (ConcatEnumerable<'T,'V,'Collection>(preEnumerate sources, next, 1)) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = Fold.executeConcatThin f (preEnumerate sources) and AppendEnumerable<'T> (sources:list>) = @@ -585,7 +594,7 @@ namespace Microsoft.FSharp.Collections member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new ListEnumerable<'T,'U>(alist, next, 1)) - member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = Fold.executeThin f (Fold.IterateList alist) and ListEnumerable<'T,'U>(alist:list<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = @@ -600,7 +609,7 @@ namespace Microsoft.FSharp.Collections member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new ListEnumerable<'T,'V>(alist, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = Fold.execute f transformFactory pipeIdx (Fold.IterateList alist) /// ThinEnumerable is used when the IEnumerable provided to ofSeq is neither an array or a list @@ -627,7 +636,7 @@ namespace Microsoft.FSharp.Collections member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new VanillaEnumerable<'T,'U>(enumerable, next, 1)) - member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = Fold.executeThin f (Fold.IterateEnumerable enumerable) type DelayedEnumerable<'T>(delayed:unit->ISeq<'T>, pipeIdx:PipeIdx) = @@ -645,7 +654,7 @@ namespace Microsoft.FSharp.Collections member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new DelayedEnumerable<'U>((fun () -> (delayed()).PushTransform next), pipeIdx+1)) - member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = (delayed()).Fold f type EmptyEnumerable<'T> () = @@ -665,7 +674,7 @@ namespace Microsoft.FSharp.Collections member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (VanillaEnumerable<'T,'V>(this, next, 1)) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = Fold.executeThin f (Fold.IterateEnumerable this) type ArrayEnumerator<'T,'U>(array:array<'T>, activity:Activity<'T,'U>, result:Result<'U>) = @@ -702,7 +711,7 @@ namespace Microsoft.FSharp.Collections member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new ArrayEnumerable<'T,'V>(array, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - member __.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + member __.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = Fold.execute f transformFactory pipeIdx (Fold.IterateArray array) type ThinArrayEnumerable<'T>(array:array<'T>) = @@ -717,7 +726,7 @@ namespace Microsoft.FSharp.Collections member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new ArrayEnumerable<'T,'U>(array, next, 1)) - member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = Fold.executeThin f (Fold.IterateArray array) type SingletonEnumerable<'T>(item:'T) = @@ -732,7 +741,7 @@ namespace Microsoft.FSharp.Collections member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new ArrayEnumerable<'T,'U>([|item|], next, 1)) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = Fold.executeThin f (Fold.IterateSingleton item) type ResizeArrayEnumerator<'T,'U>(array:ResizeArray<'T>, activity:Activity<'T,'U>, result:Result<'U>) = @@ -769,7 +778,7 @@ namespace Microsoft.FSharp.Collections member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new ResizeArrayEnumerable<'T,'V>(resizeArray, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - member __.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + member __.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = Fold.execute f transformFactory pipeIdx (Fold.IterateResizeArray resizeArray) type ThinResizeArrayEnumerable<'T>(resizeArray:ResizeArray<'T>) = @@ -784,7 +793,7 @@ namespace Microsoft.FSharp.Collections member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new ResizeArrayEnumerable<'T,'U>(resizeArray, next, 1)) - member __.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = Fold.executeThin f (Fold.IterateResizeArray resizeArray) type UnfoldEnumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, activity:Activity<'T,'U>, result:Result<'U>) = @@ -822,7 +831,7 @@ namespace Microsoft.FSharp.Collections member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new UnfoldEnumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = Fold.execute f transformFactory pipeIdx (Fold.IterateUnfold (generator, state)) let getInitTerminatingIdx (count:Nullable) = @@ -886,7 +895,7 @@ namespace Microsoft.FSharp.Collections member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new InitEnumerable<'T,'V>(count, f, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - member this.Fold<'Result,'State> (createResult:PipeIdx->Folder<'U,'Result,'State>) = + member this.Fold<'Result> (createResult:PipeIdx->Folder<'U,'Result>) = let terminatingIdx = getInitTerminatingIdx count Fold.execute createResult transformFactory pipeIdx (Fold.IterateInit (f, terminatingIdx)) @@ -973,7 +982,7 @@ namespace Microsoft.FSharp.Collections member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (InitEnumerable<'T,'V>(count, f, next, pipeIdx+1)) - member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = Fold.executeThin f (Fold.IterateEnumerable (Upcast.enumerable this)) /// wraps a ResizeArray in the ISeq framework. Care must be taken that the underlying ResizeArray @@ -1059,7 +1068,7 @@ namespace Microsoft.FSharp.Collections [] let inline fold<'T,'State> (f:'State->'T->'State) (seed:'State) (source:ISeq<'T>) : 'State = source.Fold (fun _ -> - upcast { new Folder<'T,'State,NoValue>(seed,Unchecked.defaultof) with + { new Folder<'T,'State>(seed) with override this.ProcessNext value = this.Result <- f this.Result value Unchecked.defaultof<_> (* return value unused in Fold context *) }) @@ -1095,7 +1104,7 @@ namespace Microsoft.FSharp.Collections [] let inline iter f (source:ISeq<'T>) = source.Fold (fun _ -> - upcast { new Folder<'T,unit,NoValue> ((),Unchecked.defaultof) with + { new Folder<'T,unit> (()) with override this.ProcessNext value = f value Unchecked.defaultof<_> (* return value unused in Fold context *) }) @@ -1132,7 +1141,7 @@ namespace Microsoft.FSharp.Collections [] let tryHead (source:ISeq<'T>) = source.Fold (fun pipeIdx -> - upcast { new Folder<'T, Option<'T>,NoValue> (None,Unchecked.defaultof) with + { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = this.Result <- Some value this.StopFurtherProcessing pipeIdx @@ -1147,7 +1156,7 @@ namespace Microsoft.FSharp.Collections [] let inline iteri f (source:ISeq<'T>) = source.Fold (fun _ -> - { new Folder<'T,unit,int> ((),0) with + upcast { new FolderWithState<'T,unit,int> ((),0) with override this.ProcessNext value = f this.State value this.State <- this.State + 1 @@ -1164,7 +1173,7 @@ namespace Microsoft.FSharp.Collections [] let inline exists f (source:ISeq<'T>) = source.Fold (fun pipeIdx -> - upcast { new Folder<'T, bool,NoValue> (false,Unchecked.defaultof) with + { new Folder<'T, bool> (false) with override this.ProcessNext value = if f value then this.Result <- true @@ -1190,7 +1199,7 @@ namespace Microsoft.FSharp.Collections [] let inline contains element (source:ISeq<'T>) = source.Fold (fun pipeIdx -> - upcast { new Folder<'T, bool,NoValue> (false,Unchecked.defaultof) with + { new Folder<'T, bool> (false) with override this.ProcessNext value = if element = value then this.Result <- true @@ -1200,7 +1209,7 @@ namespace Microsoft.FSharp.Collections [] let inline forall predicate (source:ISeq<'T>) = source.Fold (fun pipeIdx -> - upcast { new Folder<'T, bool,NoValue> (true,Unchecked.defaultof) with + { new Folder<'T, bool> (true) with override this.ProcessNext value = if not (predicate value) then this.Result <- false @@ -1523,7 +1532,7 @@ namespace Microsoft.FSharp.Collections [] let inline sum (source:ISeq<'T>) = source.Fold (fun _ -> - upcast { new Folder<'T,'T,NoValue> (LanguagePrimitives.GenericZero,Unchecked.defaultof) with + { new Folder<'T,'T> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Result <- Checked.(+) this.Result value Unchecked.defaultof<_> (* return value unused in Fold context *) }) @@ -1531,7 +1540,7 @@ namespace Microsoft.FSharp.Collections [] let inline sumBy (f:'T->'U) (source:ISeq<'T>) = source.Fold (fun _ -> - upcast { new Folder<'T,'U,NoValue> (LanguagePrimitives.GenericZero<'U>,Unchecked.defaultof) with + { new Folder<'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 *) }) @@ -1641,7 +1650,7 @@ namespace Microsoft.FSharp.Collections [] let inline tryPick f (source:ISeq<'T>) = source.Fold (fun pipeIdx -> - upcast { new Folder<'T, Option<'U>,NoValue> (None,Unchecked.defaultof) with + { new Folder<'T, Option<'U>> (None) with override this.ProcessNext value = match f value with | (Some _) as some -> @@ -1653,7 +1662,7 @@ namespace Microsoft.FSharp.Collections [] let inline tryFind f (source:ISeq<'T>) = source.Fold (fun pipeIdx -> - upcast { new Folder<'T, Option<'T>,NoValue> (None,Unchecked.defaultof) with + { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = if f value then this.Result <- Some value @@ -1663,7 +1672,7 @@ namespace Microsoft.FSharp.Collections [] let inline tryFindIndex (predicate:'T->bool) (source:ISeq<'T>) : int option = source.Fold (fun pipeIdx -> - { new Folder<'T, Option, int>(None, 0) with + upcast { new FolderWithState<'T, Option, int>(None, 0) with // member this.index = this.State override this.ProcessNext value = if predicate value then diff --git a/src/fsharp/FSharp.Core/iseq.fsi b/src/fsharp/FSharp.Core/iseq.fsi index a7f24719ea..1b0957291a 100644 --- a/src/fsharp/FSharp.Core/iseq.fsi +++ b/src/fsharp/FSharp.Core/iseq.fsi @@ -94,15 +94,23 @@ namespace Microsoft.FSharp.Collections /// is as a base class for an object expression that will be used from within /// the Fold function. [] - type Folder<'T,'Result,'State> = + type Folder<'T,'Result> = inherit Activity<'T,'T> - new : 'Result*'State -> Folder<'T,'Result,'State> + new : 'Result -> Folder<'T,'Result> interface IOutOfBand - val mutable State : 'State val mutable Result : 'Result val mutable HaltedIdx : int member StopFurtherProcessing : PipeIdx -> unit + /// Folder 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 FolderWithState<'T,'Result,'State> = + inherit Folder<'T,'Result> + new : 'Result*'State -> FolderWithState<'T,'Result,'State> + val mutable State : 'State + /// Folder 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 @@ -110,7 +118,7 @@ namespace Microsoft.FSharp.Collections /// the Fold function. [] type FolderWithPostProcessing<'T,'Result,'State> = - inherit Folder<'T,'Result,'State> + inherit FolderWithState<'T,'Result,'State> new : 'Result*'State -> FolderWithPostProcessing<'T,'Result,'State> abstract OnDispose : unit -> unit abstract OnComplete : PipeIdx -> unit @@ -128,7 +136,7 @@ namespace Microsoft.FSharp.Collections type ISeq<'T> = inherit System.Collections.Generic.IEnumerable<'T> abstract member PushTransform : TransformFactory<'T,'U> -> ISeq<'U> - abstract member Fold<'Result,'State> : f:(PipeIdx->Folder<'T,'Result,'State>) -> 'Result + abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result open Core From 4b2f36bb00375162c9eb92ba99254fa84f49c462 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 6 Apr 2017 09:25:17 +1000 Subject: [PATCH 40/83] Moved minimal ISeq into seqcore.fsi --- .../ISeqModule.fs | 2 +- src/fsharp/FSharp.Core/iseq.fs | 44 +------------ src/fsharp/FSharp.Core/iseq.fsi | 56 +--------------- src/fsharp/FSharp.Core/seqcore.fs | 53 +++++++++++++++ src/fsharp/FSharp.Core/seqcore.fsi | 66 +++++++++++++++++++ 5 files changed, 122 insertions(+), 99 deletions(-) diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs index 873fd4274e..65531fdf07 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ISeqModule.fs @@ -19,7 +19,7 @@ Make sure each method works on: * Null ISeq (null) *) -type iseq<'a> = ISeq.Core.ISeq<'a> +type iseq<'a> = FSharp.Collections.SeqComposition.ISeq<'a> [] type ISeqModule() = diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 8cd288a3bc..c93d4ad1d9 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -14,6 +14,7 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Control open Microsoft.FSharp.Collections open Microsoft.FSharp.Primitives.Basics + open Microsoft.FSharp.Collections.SeqComposition [] module ISeq = @@ -41,21 +42,6 @@ namespace Microsoft.FSharp.Collections val mutable _3 : 'c new (a:'a, b:'b, c:'c) = { _1 = a; _2 = b; _3 = c } - type PipeIdx = int - - type IOutOfBand = - abstract StopFurtherProcessing : PipeIdx -> unit - - [] - type Activity() = - abstract ChainComplete : PipeIdx -> unit - abstract ChainDispose : unit -> unit - - [] - type Activity<'T,'U> () = - inherit Activity() - abstract ProcessNext : input:'T -> bool - [] type Transform<'T,'U,'State> = inherit Activity<'T,'U> @@ -88,26 +74,6 @@ namespace Microsoft.FSharp.Collections try this.OnDispose () finally this.Next.ChainDispose () - [] - type Folder<'T,'Result> = - inherit Activity<'T,'T> - - val mutable Result : 'Result - - val mutable HaltedIdx : int - member this.StopFurtherProcessing pipeIdx = this.HaltedIdx <- pipeIdx - interface IOutOfBand with - member this.StopFurtherProcessing pipeIdx = this.StopFurtherProcessing pipeIdx - - new (initalResult) = { - inherit Activity<'T,'T>() - HaltedIdx = 0 - Result = initalResult - } - - override this.ChainComplete _ = () - override this.ChainDispose () = () - [] type FolderWithState<'T,'Result,'State> = inherit Folder<'T,'Result> @@ -131,14 +97,6 @@ namespace Microsoft.FSharp.Collections override this.ChainDispose () = this.OnDispose () - [] - type TransformFactory<'T,'U> () = - abstract Compose<'V> : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> - - type ISeq<'T> = - inherit IEnumerable<'T> - abstract member PushTransform<'U> : TransformFactory<'T,'U> -> ISeq<'U> - abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result open Core diff --git a/src/fsharp/FSharp.Core/iseq.fsi b/src/fsharp/FSharp.Core/iseq.fsi index 1b0957291a..5beeaceb35 100644 --- a/src/fsharp/FSharp.Core/iseq.fsi +++ b/src/fsharp/FSharp.Core/iseq.fsi @@ -7,6 +7,7 @@ namespace Microsoft.FSharp.Collections open System.Collections.Generic open Microsoft.FSharp.Core open Microsoft.FSharp.Collections + open Microsoft.FSharp.Collections.SeqComposition [] module ISeq = @@ -38,35 +39,6 @@ namespace Microsoft.FSharp.Collections val mutable _2: 'b val mutable _3: 'c - /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the - /// source of the chain. - type PipeIdx = int - - /// Used within the pipline to provide out of band communications - type IOutOfBand = - /// Stop the processing of any further items down the pipeline - abstract StopFurtherProcessing : PipeIdx -> unit - - /// Activity 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 Activity = - /// 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 ChainComplete : PipeIdx -> unit - /// OnDispose is used to cleanup the stream. It is always called at the last operation - /// after the enumeration has completed. - abstract ChainDispose : unit -> unit - - /// Activity is the base class of all elements within the pipeline - [] - type Activity<'T,'U> = - inherit Activity - new : unit -> Activity<'T,'U> - abstract member ProcessNext : input:'T -> bool /// 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 @@ -90,17 +62,6 @@ namespace Microsoft.FSharp.Collections abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit - /// Folder 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 Folder<'T,'Result> = - inherit Activity<'T,'T> - new : 'Result -> Folder<'T,'Result> - interface IOutOfBand - val mutable Result : 'Result - val mutable HaltedIdx : int - member StopFurtherProcessing : PipeIdx -> unit /// Folder 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 @@ -123,21 +84,6 @@ namespace Microsoft.FSharp.Collections abstract OnDispose : unit -> unit abstract OnComplete : PipeIdx -> unit - /// TransformFactory provides composition of Activities. Its intended to have a specialization - /// for each type of ISeq Activity. ISeq's PushTransform method is used to build a stack - /// of Actvities that will be composed. - [] - type TransformFactory<'T,'U> = - new : unit -> TransformFactory<'T,'U> - abstract member Compose : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> - - /// ISeq<'T> is an extension to seq<'T> that provides the avilty to compose Activities - /// as well as Fold the current Activity pipeline. - type ISeq<'T> = - inherit System.Collections.Generic.IEnumerable<'T> - abstract member PushTransform : TransformFactory<'T,'U> -> ISeq<'U> - abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result - open Core /// ofResizeArrayUnchecked creates an ISeq over a ResizeArray that accesses the underlying diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index e733d7f9a2..63a932acde 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -135,6 +135,59 @@ 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 Microsoft.FSharp.Core + open Microsoft.FSharp.Collections + + type PipeIdx = int + + type IOutOfBand = + abstract StopFurtherProcessing : PipeIdx -> unit + + [] + type Activity() = + abstract ChainComplete : PipeIdx -> unit + abstract ChainDispose : unit -> unit + + [] + type Activity<'T,'U> () = + inherit Activity() + abstract ProcessNext : input:'T -> bool + + [] + type Folder<'T,'Result> = + inherit Activity<'T,'T> + + val mutable Result : 'Result + + val mutable HaltedIdx : int + member this.StopFurtherProcessing pipeIdx = this.HaltedIdx <- pipeIdx + interface IOutOfBand with + member this.StopFurtherProcessing pipeIdx = this.StopFurtherProcessing pipeIdx + + new (initalResult) = { + inherit Activity<'T,'T>() + HaltedIdx = 0 + Result = initalResult + } + + override this.ChainComplete _ = () + override this.ChainDispose () = () + + [] + type TransformFactory<'T,'U> () = + abstract Compose<'V> : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> + + type ISeq<'T> = + inherit IEnumerable<'T> + abstract member PushTransform<'U> : TransformFactory<'T,'U> -> ISeq<'U> + abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result + + namespace Microsoft.FSharp.Core.CompilerServices open System diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index ebd7accb8e..ab3ed7e2f4 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -55,6 +55,72 @@ namespace Microsoft.FSharp.Collections 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 + + /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the + /// source of the chain. + type PipeIdx = int + + /// Used within the pipline to provide out of band communications + type IOutOfBand = + /// Stop the processing of any further items down the pipeline + abstract StopFurtherProcessing : PipeIdx -> unit + + /// Activity 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 Activity = + /// 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 ChainComplete : PipeIdx -> unit + /// OnDispose is used to cleanup the stream. It is always called at the last operation + /// after the enumeration has completed. + abstract ChainDispose : unit -> unit + + /// Activity is the base class of all elements within the pipeline + [] + type Activity<'T,'U> = + inherit Activity + new : unit -> Activity<'T,'U> + abstract member ProcessNext : input:'T -> bool + + /// Folder 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 Folder<'T,'Result> = + inherit Activity<'T,'T> + new : 'Result -> Folder<'T,'Result> + interface IOutOfBand + val mutable Result : 'Result + val mutable HaltedIdx : int + member StopFurtherProcessing : PipeIdx -> unit + override ChainComplete : PipeIdx -> unit + override ChainDispose : unit -> unit + + /// TransformFactory provides composition of Activities. Its intended to have a specialization + /// for each type of ISeq Activity. ISeq's PushTransform method is used to build a stack + /// of Actvities that will be composed. + [] + type TransformFactory<'T,'U> = + new : unit -> TransformFactory<'T,'U> + abstract member Compose : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> + + /// ISeq<'T> is an extension to seq<'T> that provides the avilty to compose Activities + /// as well as Fold the current Activity pipeline. + type ISeq<'T> = + inherit System.Collections.Generic.IEnumerable<'T> + abstract member PushTransform : TransformFactory<'T,'U> -> ISeq<'U> + abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result + namespace Microsoft.FSharp.Core.CompilerServices open System From 77b32492baa0d895c1b63c6d99d8cd45f3cb310e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 6 Apr 2017 12:21:52 +1000 Subject: [PATCH 41/83] Moved internal parts of ISeq into seqcore --- .../SurfaceArea.net40.fs | 216 ----- src/fsharp/FSharp.Core/iseq.fs | 865 +---------------- src/fsharp/FSharp.Core/iseq.fsi | 3 - src/fsharp/FSharp.Core/seqcore.fs | 916 +++++++++++++++++- src/fsharp/FSharp.Core/seqcore.fsi | 96 ++ 5 files changed, 1028 insertions(+), 1068 deletions(-) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs index a7bf1b985d..0fdcc27abe 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs @@ -280,222 +280,6 @@ 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.ISeqModule+Core+Activity: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainComplete(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainDispose() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Boolean ProcessNext(T) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void .ctor() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainComplete(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainDispose() -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 HaltedIdx -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TResult Result -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TState State -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void .ctor(TResult, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnDispose() -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Boolean ProcessNext(T) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Int32 HaltedIdx -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: TResult Result -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: TState State -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void .ctor(TResult, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainComplete(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainDispose() -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+IOutOfBand: Void StopFurtherProcessing(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]: ISeq`1 PushTransform[TResult](TransformFactory`2) -Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]: TResult Fold[TResult,TState](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]]) -Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Activity`2 Compose[V](IOutOfBand, Int32, Activity`2) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Void .ctor() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: TState State -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void .ctor(Activity, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnDispose() -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Boolean ProcessNext(T) -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: TState State -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void .ctor(Activity, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainComplete(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainDispose() -Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Void .ctor(a) -Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: a _1 -Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: Void .ctor(a, b) -Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: a _1 -Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: b _2 -Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: Void .ctor(a, b, c) -Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: a _1 -Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: b _2 -Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: c _3 -Microsoft.FSharp.Collections.ISeqModule+Core: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Activity -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult] -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState] -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState] -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+IOutOfBand -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T] -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+NoValue -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult] -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState] -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState] -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a] -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b] -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c] -Microsoft.FSharp.Collections.ISeqModule+Core: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule: Boolean Contains[T](T, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule: Boolean Exists2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Boolean IsEmpty[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 AllPairs[T1,T2](ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Append[T](ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Cache[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Cast[T](System.Collections.IEnumerable) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Choose[a,b](Microsoft.FSharp.Core.FSharpFunc`2[a,Microsoft.FSharp.Core.FSharpOption`1[b]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 ChunkBySize[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Collect[T,TCollection,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TCollection], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Concat[TCollection,T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Delay[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 DistinctBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Distinct[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Empty[T]() -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Except[T](System.Collections.Generic.IEnumerable`1[T], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Filter[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 GroupByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 GroupByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Indexed[a](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 InitializeInfinite[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Initialize[T](Int32, Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map3[T,TResult,V,W](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[V,W]]], ISeq`1, ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 MapIndexed2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 MapIndexed[a,b](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[a,b]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfArray[T](T[]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfList[T](Microsoft.FSharp.Collections.FSharpList`1[T]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfResizeArrayUnchecked[T](System.Collections.Generic.List`1[T]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfSeq[T](System.Collections.Generic.IEnumerable`1[T]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Pairwise[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Permute[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Replicate[T](Int32, T) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Reverse[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], ISeq`1, TState) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Scan[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Singleton[T](T) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SkipWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Skip[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortByDescending[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortDescending[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Sort[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SplitInto[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Tail[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Take[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Truncate[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Unfold[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Windowed[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Zip3[T1,T2,T3](ISeq`1, ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Zip[T1,T2](ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule: Int32 Length[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.FSharpList`1[T] ToList[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.ISeqModule+Core -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[TResult] TryPick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFind[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryHead[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryItem[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[TResult],TState] MapFoldBack[T,TState,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,System.Tuple`2[TResult,TState]]], ISeq`1, TState) -Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`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, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule: T Average[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T ExactlyOne[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T FindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Find[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Head[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Item[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Last[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Max[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Min[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T ReduceBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Sum[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: TResult Pick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: 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, ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: TState FoldBack2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], ISeq`1, ISeq`1, TState) -Microsoft.FSharp.Collections.ISeqModule: TState FoldBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], ISeq`1, TState) -Microsoft.FSharp.Collections.ISeqModule: TState Fold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T[] ToArray[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Void Iterate2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.Unit]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: 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]]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Void IterateIndexed[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Void Iterate[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit], ISeq`1) 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]) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index c93d4ad1d9..ec01f198be 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1,7 +1,6 @@ // 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 @@ -15,15 +14,13 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Collections open Microsoft.FSharp.Primitives.Basics open Microsoft.FSharp.Collections.SeqComposition + open Microsoft.FSharp.Collections.SeqComposition.Internal [] module ISeq = open IEnumerator module Core = - [] - type NoValue = struct end - [] type Value<'a> = val mutable _1 : 'a @@ -97,7 +94,6 @@ namespace Microsoft.FSharp.Collections override this.ChainDispose () = this.OnDispose () - open Core module internal TailCall = @@ -110,14 +106,7 @@ namespace Microsoft.FSharp.Collections // The f# compiler outputs unnecessary unbox.any calls in upcasts. If this functionality // is fixed with the compiler then these functions can be removed. let inline seq<'T,'seq when 'seq :> ISeq<'T> and 'seq : not struct> (t:'seq) : ISeq<'T> = (# "" t : ISeq<'T> #) - let inline enumerable<'T,'enumerable when 'enumerable :> IEnumerable<'T> and 'enumerable : not struct> (t:'enumerable) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) let inline enumerableNonGeneric<'enumerable when 'enumerable :> IEnumerable and 'enumerable : not struct> (t:'enumerable) : IEnumerable = (# "" t : IEnumerable #) - let inline enumerator<'T,'enumerator when 'enumerator :> IEnumerator<'T> and 'enumerator : not struct> (t:'enumerator) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) - let inline enumeratorNonGeneric<'enumerator when 'enumerator :> IEnumerator and 'enumerator : not struct> (t:'enumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline outOfBand<'outOfBand when 'outOfBand :> IOutOfBand and 'outOfBand : not struct> (t:'outOfBand) : IOutOfBand = (# "" t : IOutOfBand #) - - let createFold (factory:TransformFactory<_,_>) (folder:Folder<_,_>) pipeIdx = - factory.Compose (Upcast.outOfBand folder) pipeIdx folder let inline valueComparer<'T when 'T : equality> ()= let c = HashIdentity.Structural<'T> @@ -125,824 +114,6 @@ namespace Microsoft.FSharp.Collections member __.GetHashCode o = c.GetHashCode o._1 member __.Equals (lhs,rhs) = c.Equals (lhs._1, rhs._1) } - type ComposedFactory<'T,'U,'V> private (first:TransformFactory<'T,'U>, second:TransformFactory<'U,'V>) = - inherit TransformFactory<'T,'V>() - - override this.Compose<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = - first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) - - static member Combine (first:TransformFactory<'T,'U>) (second:TransformFactory<'U,'V>) : TransformFactory<'T,'V> = - upcast ComposedFactory(first, second) - - and IdentityFactory<'T> private () = - inherit TransformFactory<'T,'T> () - static let singleton : TransformFactory<'T,'T> = upcast (IdentityFactory<'T>()) - override __.Compose<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next - static member Instance = singleton - - and ISkipable = - // Seq.init(Infinite)? lazily uses Current. The only ISeq 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 Result<'T>() = - inherit Folder<'T,'T>(Unchecked.defaultof<'T>) - - member val SeqState = SeqProcessNextStates.NotStarted with get, set - - override this.ProcessNext (input:'T) : bool = - this.Result <- input - true - - module Fold = - // The consumers of IIterate are the execute and exeuteThin methods. IIterate is passed - // as a generic argument. The types that implement IIterate are value types. This combination - // means that the runtime will "inline" the methods. The alternatives to this were that the - // code in execute/executeThin were duplicated for each of the Fold types, or we turned the - // types back into normal functions and curried them then we would be creating garbage - // each time one of these were called. This has been an optimization to minimize the impact - // on very small collections. - type IIterate<'T> = - abstract Iterate<'U,'Result,'State> : outOfBand:Folder<'U,'Result> -> consumer:Activity<'T,'U> -> unit - - [] - type IterateEnumerable<'T> (enumerable:IEnumerable<'T>) = - interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = - use enumerator = enumerable.GetEnumerator () - let rec iterate () = - if outOfBand.HaltedIdx = 0 && enumerator.MoveNext () then - consumer.ProcessNext enumerator.Current |> ignore - iterate () - iterate () - - [] - type IterateArray<'T> (array:array<'T>) = - interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = - let array = array - let rec iterate idx = - if outOfBand.HaltedIdx = 0 && idx < array.Length then - consumer.ProcessNext array.[idx] |> ignore - iterate (idx+1) - iterate 0 - - [] - type IterateResizeArray<'T> (array:ResizeArray<'T>) = - interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = - let array = array - let rec iterate idx = - if outOfBand.HaltedIdx = 0 && idx < array.Count then - consumer.ProcessNext array.[idx] |> ignore - iterate (idx+1) - iterate 0 - - [] - type IterateList<'T> (alist:list<'T>) = - interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = - let rec iterate lst = - match lst with - | hd :: tl when outOfBand.HaltedIdx = 0 -> - consumer.ProcessNext hd |> ignore - iterate tl - | _ -> () - iterate alist - - [] - type IterateSingleton<'T> (item:'T) = - interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = - if outOfBand.HaltedIdx = 0 then - consumer.ProcessNext item |> ignore - - [] - type IterateUnfold<'S,'T> (generator:'S->option<'T*'S>, state:'S) = - interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = - let generator = generator - let rec iterate current = - if outOfBand.HaltedIdx <> 0 then () - else - match generator current with - | Some (item, next) -> - consumer.ProcessNext item |> ignore - iterate next - | _ -> () - iterate state - - [] - type IterateInit<'T> (f:int->'T, terminatingIdx:int) = - interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = - let terminatingIdx = terminatingIdx - let f = f - - let firstIdx = - match box consumer with - | :? ISkipable as skipping -> - let rec skip idx = - if idx = terminatingIdx || outOfBand.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 outOfBand.HaltedIdx = 0 then - iterate (idx+1) - else - idx - else - idx - - let finalIdx = iterate firstIdx - if outOfBand.HaltedIdx = 0 && finalIdx = System.Int32.MaxValue then - raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) - - // execute, and it's companion, executeThin, are hosting functions that ensure the correct sequence - // of creation, iteration and disposal for the pipeline - let execute (createFolder:PipeIdx->Folder<'U,'Result>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (executeOn:#IIterate<'T>) = - let result = createFolder (pipeIdx+1) - let consumer = createFold transformFactory result pipeIdx - try - executeOn.Iterate result consumer - consumer.ChainComplete result.HaltedIdx - result.Result - finally - consumer.ChainDispose () - - // executeThin is a specialization of execute, provided as a performance optimization, that can - // be used when a sequence has been wrapped in an ISeq, but hasn't had an items added to its pipeline - // i.e. a container that has ISeq.ofSeq applied. - let executeThin (createFolder:PipeIdx->Folder<'T,'Result>) (executeOn:#IIterate<'T>) = - let result = createFolder 1 - try - executeOn.Iterate result result - result.ChainComplete result.HaltedIdx - result.Result - finally - result.ChainDispose () - - let executeConcat<'T,'U,'Result,'State,'Collection when 'Collection :> ISeq<'T>> (createFolder:PipeIdx->Folder<'U,'Result>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (sources:ISeq<'Collection>) = - let result = createFolder (pipeIdx+1) - let consumer = createFold transformFactory result pipeIdx - try - let common = - { new Folder<'T,NoValue>(Unchecked.defaultof<_>) with - override me.ProcessNext value = consumer.ProcessNext value } - - sources.Fold (fun _ -> - { new Folder<'Collection,NoValue>(Unchecked.defaultof<_>) with - override me.ProcessNext value = - value.Fold (fun _ -> common) |> ignore - me.HaltedIdx <- common.HaltedIdx - Unchecked.defaultof<_> (* return value unused in Fold context *) }) |> ignore - - consumer.ChainComplete result.HaltedIdx - result.Result - finally - result.ChainDispose () - - let executeConcatThin<'T,'Result,'State,'Collection when 'Collection :> ISeq<'T>> (createFolder:PipeIdx->Folder<'T,'Result>) (sources:ISeq<'Collection>) = - let result = createFolder 1 - try - let common = - { new Folder<'T,NoValue>(Unchecked.defaultof<_>) with - override me.ProcessNext value = result.ProcessNext value } - - sources.Fold (fun _ -> - { new Folder<'Collection,NoValue>(Unchecked.defaultof<_>) with - override me.ProcessNext value = - value.Fold (fun _ -> common) |> ignore - me.HaltedIdx <- common.HaltedIdx - Unchecked.defaultof<_> (* return value unused in Fold context *) }) |> ignore - - result.ChainComplete result.HaltedIdx - result.Result - finally - result.ChainDispose () - - module Wrap = - 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 EnumeratorBase<'T>(result:Result<'T>, activity:Activity) = - interface IDisposable with - member __.Dispose () : unit = - activity.ChainDispose () - - interface IEnumerator with - member this.Current : obj = box ((Upcast.enumerator this)).Current - member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)" - member __.Reset () : unit = noReset () - - interface IEnumerator<'T> with - member __.Current = - if result.SeqState = SeqProcessNextStates.InProcess then result.Result - else - match result.SeqState with - | SeqProcessNextStates.NotStarted -> notStarted() - | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> failwith "library implementation error: all states should have been handled" - - type VanillaEnumerator<'T,'U>(source:IEnumerator<'T>, activity:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, activity) - - let rec moveNext () = - if (result.HaltedIdx = 0) && source.MoveNext () then - if activity.ProcessNext source.Current then - true - else - moveNext () - else - result.SeqState <- SeqProcessNextStates.Finished - activity.ChainComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () - - interface IDisposable with - member __.Dispose () = - try - source.Dispose () - finally - activity.ChainDispose () - - type ConcatEnumerator<'T,'U,'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>, activity:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, activity) - - let main = sources.GetEnumerator () - - let mutable active = EmptyEnumerators.Element - - let rec moveNext () = - if result.HaltedIdx <> 0 then false - else - if active.MoveNext () then - if activity.ProcessNext active.Current then - true - else - moveNext () - elif main.MoveNext () then - active.Dispose () - active <- main.Current.GetEnumerator () - moveNext () - else - result.SeqState <- SeqProcessNextStates.Finished - activity.ChainComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () - - interface IDisposable with - member __.Dispose () = - try - main.Dispose () - active.Dispose () - finally - activity.ChainDispose () - - type ListEnumerator<'T,'U>(alist:list<'T>, activity:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, activity) - - 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 <- SeqProcessNextStates.Finished - activity.ChainComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext list - - let length (source:ISeq<_>) = - source.Fold (fun _ -> - { new Folder<'T,int>(0) with - override this.ProcessNext v = - this.Result <- this.Result + 1 - Unchecked.defaultof<_> (* return value unused in Fold context *) }) - - [] - type EnumerableBase<'T> () = - let derivedClassShouldImplement () = - failwith "library implementation error: derived class should implement (should be abstract)" - - abstract member Append : ISeq<'T> -> ISeq<'T> - abstract member Length : unit -> int - - default this.Append source = Upcast.seq (AppendEnumerable [source; this]) - default this.Length () = length this - - interface IEnumerable with - member this.GetEnumerator () : IEnumerator = - let genericEnumerable = Upcast.enumerable this - let genericEnumerator = genericEnumerable.GetEnumerator () - Upcast.enumeratorNonGeneric genericEnumerator - - interface IEnumerable<'T> with - // fsharp doesn't allow abstract interface methods - member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () - - interface ISeq<'T> with - // fsharp doesn't allow abstract interface methods - member __.PushTransform _ = derivedClassShouldImplement () - member __.Fold _ = derivedClassShouldImplement () - - and VanillaEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Upcast.enumerator (new VanillaEnumerator<'T,'U>(enumerable.GetEnumerator(), createFold current result pipeIdx, result)) - - interface ISeq<'U> with - member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new VanillaEnumerable<'T,'V>(enumerable, ComposedFactory.Combine current next, pipeIdx+1)) - - member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = - Fold.execute f current pipeIdx (Fold.IterateEnumerable enumerable) - - and ConcatEnumerable<'T,'U,'Collection when 'Collection :> ISeq<'T>> (sources:ISeq<'Collection>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() - - interface IEnumerable<'U> with - member __.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Upcast.enumerator (new ConcatEnumerator<'T,'U,'Collection>(sources, createFold current result pipeIdx, result)) - - interface ISeq<'U> with - member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new ConcatEnumerable<'T,'V,'Collection>(sources, ComposedFactory.Combine current next, pipeIdx+1)) - - member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = - Fold.executeConcat f current pipeIdx sources - - and ThinConcatEnumerable<'T, 'Sources, 'Collection when 'Collection :> ISeq<'T>> (sources:'Sources, preEnumerate:'Sources->ISeq<'Collection>) = - inherit EnumerableBase<'T>() - - interface IEnumerable<'T> with - member this.GetEnumerator () : IEnumerator<'T> = - let result = Result<'T> () - Upcast.enumerator (new ConcatEnumerator<'T,'T,'Collection> (preEnumerate sources, createFold IdentityFactory.Instance result 1, result)) - - interface ISeq<'T> with - member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (ConcatEnumerable<'T,'V,'Collection>(preEnumerate sources, next, 1)) - - member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeConcatThin f (preEnumerate sources) - - and AppendEnumerable<'T> (sources:list>) = - inherit ThinConcatEnumerable<'T, list>, ISeq<'T>>(sources, fun sources -> Upcast.seq (ThinListEnumerable>(List.rev sources))) - - override this.Append source = - Upcast.seq (AppendEnumerable (source::sources)) - - and ThinListEnumerable<'T>(alist:list<'T>) = - inherit EnumerableBase<'T>() - - override __.Length () = alist.Length - - interface IEnumerable<'T> with - member __.GetEnumerator () = (Upcast.enumerable alist).GetEnumerator () - - interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new ListEnumerable<'T,'U>(alist, next, 1)) - - member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeThin f (Fold.IterateList alist) - - and ListEnumerable<'T,'U>(alist:list<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Upcast.enumerator (new ListEnumerator<'T,'U>(alist, createFold transformFactory result pipeIdx, result)) - - interface ISeq<'U> with - member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new ListEnumerable<'T,'V>(alist, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - - member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = - Fold.execute f transformFactory pipeIdx (Fold.IterateList alist) - - /// ThinEnumerable is used when the IEnumerable provided to ofSeq is neither an array or a list - type ThinEnumerable<'T>(enumerable:IEnumerable<'T>) = - inherit EnumerableBase<'T>() - - override __.Length () = - match enumerable with - | :? ICollection<'T> as a -> a.Count -#if !FSCORE_PORTABLE_OLD - | :? IReadOnlyCollection<'T> as a -> a.Count -#endif - | _ -> - use e = enumerable.GetEnumerator () - let mutable count = 0 - while e.MoveNext () do - count <- count + 1 - count - - interface IEnumerable<'T> with - member __.GetEnumerator () = enumerable.GetEnumerator () - - interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new VanillaEnumerable<'T,'U>(enumerable, next, 1)) - - member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeThin f (Fold.IterateEnumerable enumerable) - - type DelayedEnumerable<'T>(delayed:unit->ISeq<'T>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'T>() - - override __.Length () = - match delayed() with - | :? EnumerableBase<'T> as s -> s.Length () - | s -> length s - - interface IEnumerable<'T> with - member this.GetEnumerator () : IEnumerator<'T> = (delayed()).GetEnumerator () - - interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new DelayedEnumerable<'U>((fun () -> (delayed()).PushTransform next), pipeIdx+1)) - - member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - (delayed()).Fold f - - type EmptyEnumerable<'T> () = - inherit EnumerableBase<'T>() - - static let singleton = EmptyEnumerable<'T>() :> ISeq<'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 ISeq<'T> with - member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (VanillaEnumerable<'T,'V>(this, next, 1)) - - member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeThin f (Fold.IterateEnumerable this) - - type ArrayEnumerator<'T,'U>(array:array<'T>, activity:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, activity) - - let mutable idx = 0 - - let rec moveNext () = - if (result.HaltedIdx = 0) && idx < array.Length then - idx <- idx+1 - if activity.ProcessNext array.[idx-1] then - true - else - moveNext () - else - result.SeqState <- SeqProcessNextStates.Finished - activity.ChainComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () - - type ArrayEnumerable<'T,'U>(array:array<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() - - interface IEnumerable<'U> with - member __.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Upcast.enumerator (new ArrayEnumerator<'T,'U>(array, createFold transformFactory result pipeIdx, result)) - - interface ISeq<'U> with - member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new ArrayEnumerable<'T,'V>(array, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - - member __.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = - Fold.execute f transformFactory pipeIdx (Fold.IterateArray array) - - type ThinArrayEnumerable<'T>(array:array<'T>) = - inherit EnumerableBase<'T>() - - override __.Length () = array.Length - - interface IEnumerable<'T> with - member __.GetEnumerator () = (Upcast.enumerable array).GetEnumerator () - - interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new ArrayEnumerable<'T,'U>(array, next, 1)) - - member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeThin f (Fold.IterateArray array) - - type SingletonEnumerable<'T>(item:'T) = - inherit EnumerableBase<'T>() - - override __.Length () = 1 - - interface IEnumerable<'T> with - member this.GetEnumerator () = Upcast.enumerator (new Singleton<'T>(item)) - - interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new ArrayEnumerable<'T,'U>([|item|], next, 1)) - - member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeThin f (Fold.IterateSingleton item) - - type ResizeArrayEnumerator<'T,'U>(array:ResizeArray<'T>, activity:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, activity) - - let mutable idx = 0 - - let rec moveNext () = - if (result.HaltedIdx = 0) && idx < array.Count then - idx <- idx+1 - if activity.ProcessNext array.[idx-1] then - true - else - moveNext () - else - result.SeqState <- SeqProcessNextStates.Finished - activity.ChainComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () - - type ResizeArrayEnumerable<'T,'U>(resizeArray:ResizeArray<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Upcast.enumerator (new ResizeArrayEnumerator<'T,'U>(resizeArray, createFold transformFactory result pipeIdx, result)) - - interface ISeq<'U> with - member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new ResizeArrayEnumerable<'T,'V>(resizeArray, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - - member __.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = - Fold.execute f transformFactory pipeIdx (Fold.IterateResizeArray resizeArray) - - type ThinResizeArrayEnumerable<'T>(resizeArray:ResizeArray<'T>) = - inherit EnumerableBase<'T>() - - override __.Length () = resizeArray.Count - - interface IEnumerable<'T> with - member __.GetEnumerator () = (Upcast.enumerable resizeArray).GetEnumerator () - - interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new ResizeArrayEnumerable<'T,'U>(resizeArray, next, 1)) - - member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeThin f (Fold.IterateResizeArray resizeArray) - - type UnfoldEnumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, activity:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, activity) - - let mutable current = state - - let rec moveNext () = - if result.HaltedIdx <> 0 then - false - else - match generator current with - | Some (item, nextState) -> - current <- nextState - if activity.ProcessNext item then - true - else - moveNext () - | _ -> false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () - - type UnfoldEnumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Upcast.enumerator (new UnfoldEnumerator<'T,'U,'GeneratorState>(generator, state, createFold transformFactory result pipeIdx, result)) - - interface ISeq<'U> with - member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new UnfoldEnumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - - member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = - Fold.execute f transformFactory pipeIdx (Fold.IterateUnfold (generator, state)) - - 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, activity:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, activity) - - let isSkipping = - match box activity with - | :? ISkipable as skip -> skip.CanSkip - | _ -> fun () -> false - - let terminatingIdx = - getInitTerminatingIdx count - - let mutable maybeSkipping = true - let mutable idx = -1 - - let rec moveNext () = - if result.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 - moveNext () - elif activity.ProcessNext (f idx) then - true - else - moveNext () - elif result.HaltedIdx = 0 && idx = System.Int32.MaxValue then - raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) - else - result.SeqState <- SeqProcessNextStates.Finished - activity.ChainComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () - - type InitEnumerable<'T,'U>(count:Nullable, f:int->'T, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Upcast.enumerator (new InitEnumerator<'T,'U>(count, f, createFold transformFactory result pipeIdx, result)) - - interface ISeq<'U> with - member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new InitEnumerable<'T,'V>(count, f, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - - member this.Fold<'Result> (createResult:PipeIdx->Folder<'U,'Result>) = - let terminatingIdx = getInitTerminatingIdx count - Fold.execute createResult transformFactory pipeIdx (Fold.IterateInit (f, terminatingIdx)) - - // 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 ISeq<'T> with - member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (InitEnumerable<'T,'V>(count, f, next, pipeIdx+1)) - - member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeThin f (Fold.IterateEnumerable (Upcast.enumerable this)) - /// wraps a ResizeArray in the ISeq framework. Care must be taken that the underlying ResizeArray /// is not modified whilst it can be accessed as the ISeq, so check on version is performed. /// i.e. usually iteration on calls the enumerator provied by GetEnumerator ensure that the @@ -950,16 +121,16 @@ namespace Microsoft.FSharp.Collections /// performed in this case. If you want this funcitonality, then use the ofSeq function instead. [] let ofResizeArrayUnchecked (source:ResizeArray<'T>) : ISeq<'T> = - Upcast.seq (Wrap.ThinResizeArrayEnumerable<'T> source) + Upcast.seq (ThinResizeArrayEnumerable<'T> source) [] let ofArray (source:array<'T>) : ISeq<'T> = checkNonNull "source" source - Upcast.seq (Wrap.ThinArrayEnumerable<'T> source) + Upcast.seq (ThinArrayEnumerable<'T> source) [] let ofList (source:list<'T>) : ISeq<'T> = - Upcast.seq (Wrap.ThinListEnumerable<'T> source) + Upcast.seq (ThinListEnumerable<'T> source) [] let ofSeq (source:seq<'T>) : ISeq<'T> = @@ -968,7 +139,7 @@ namespace Microsoft.FSharp.Collections | :? array<'T> as array -> ofArray array | :? list<'T> as list -> ofList list | null -> nullArg "source" - | _ -> Upcast.seq (Wrap.ThinEnumerable<'T> source) + | _ -> Upcast.seq (ThinEnumerable<'T> source) [] let inline average (source:ISeq<'T>) = @@ -1001,7 +172,7 @@ namespace Microsoft.FSharp.Collections override this.OnDispose () = () }) [] - let empty<'T> = Wrap.EmptyEnumerable<'T>.Instance + let empty<'T> = Microsoft.FSharp.Collections.SeqComposition.Internal.EmptyEnumerable<'T>.Instance [] let exactlyOne (source:ISeq<'T>) : 'T = @@ -1047,17 +218,17 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = - Upcast.seq (new Wrap.UnfoldEnumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance, 1)) + Upcast.seq (new UnfoldEnumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance, 1)) [] let initInfinite<'T> (f:int->'T) : ISeq<'T> = - Upcast.seq (new Wrap.InitEnumerableDecider<'T>(Nullable (), f, 1)) + Upcast.seq (new InitEnumerableDecider<'T>(Nullable (), f, 1)) [] let init<'T> (count:int) (f:int->'T) : ISeq<'T> = if count < 0 then invalidArgInputMustBeNonNegative "count" count elif count = 0 then empty else - Upcast.seq (new Wrap.InitEnumerableDecider<'T>(Nullable count, f, 1)) + Upcast.seq (new InitEnumerableDecider<'T>(Nullable count, f, 1)) [] let inline iter f (source:ISeq<'T>) = @@ -1422,10 +593,10 @@ namespace Microsoft.FSharp.Collections [] let concat (sources:ISeq<#ISeq<'T>>) : ISeq<'T> = - Upcast.seq (Wrap.ThinConcatEnumerable (sources, id)) + Upcast.seq (ThinConcatEnumerable (sources, id)) [] - let singleton x = Upcast.seq (new Wrap.SingletonEnumerable<_>(x)) + let singleton x = Upcast.seq (new SingletonEnumerable<_>(x)) [] let inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = @@ -1698,12 +869,12 @@ namespace Microsoft.FSharp.Collections [] let append (source1:ISeq<'T>) (source2: ISeq<'T>) : ISeq<'T> = match source1 with - | :? Wrap.EnumerableBase<'T> as s -> s.Append source2 - | _ -> Upcast.seq (new Wrap.AppendEnumerable<_>([source2; source1])) + | :? EnumerableBase<'T> as s -> s.Append source2 + | _ -> Upcast.seq (new AppendEnumerable<_>([source2; source1])) [] let delay (delayed:unit->ISeq<'T>) = - Upcast.seq (Wrap.DelayedEnumerable (delayed, 1)) + Upcast.seq (DelayedEnumerable (delayed, 1)) module internal GroupBy = let inline private impl (comparer:IEqualityComparer<'SafeKey>) (keyf:'T->'SafeKey) (getKey:'SafeKey->'Key) (source:ISeq<'T>) = @@ -1782,8 +953,8 @@ namespace Microsoft.FSharp.Collections [] let length (source:ISeq<'T>) = match source with - | :? Wrap.EnumerableBase<'T> as s -> s.Length () - | _ -> Wrap.length source + | :? EnumerableBase<'T> as s -> s.Length () + | _ -> length source [] let toArray (source:ISeq<'T>) = @@ -1918,7 +1089,7 @@ namespace Microsoft.FSharp.Collections else None) - let cached = Upcast.seq (new Wrap.UnfoldEnumerable<'T,'T,int>(unfolding, 0, IdentityFactory.Instance, 1)) + let cached = Upcast.seq (new UnfoldEnumerable<'T,'T,int>(unfolding, 0, IdentityFactory.Instance, 1)) interface System.IDisposable with member __.Dispose() = @@ -1965,7 +1136,7 @@ namespace Microsoft.FSharp.Collections [] let replicate count x = if count < 0 then raise (ArgumentOutOfRangeException "count") - Upcast.seq (new Wrap.InitEnumerable<'T,'T>(Nullable count, (fun _ -> x), IdentityFactory.Instance, 1)) + Upcast.seq (new InitEnumerable<'T,'T>(Nullable count, (fun _ -> x), IdentityFactory.Instance, 1)) [] let isEmpty (source : ISeq<'T>) = diff --git a/src/fsharp/FSharp.Core/iseq.fsi b/src/fsharp/FSharp.Core/iseq.fsi index 5beeaceb35..076daafa4c 100644 --- a/src/fsharp/FSharp.Core/iseq.fsi +++ b/src/fsharp/FSharp.Core/iseq.fsi @@ -12,9 +12,6 @@ namespace Microsoft.FSharp.Collections [] module ISeq = module Core = - [] - type NoValue = struct end - /// Values is a mutable struct. It can be embedded within the folder type /// if two values are required for the calculation. [] diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index 63a932acde..fdf0973e69 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -136,7 +136,6 @@ namespace Microsoft.FSharp.Collections member x.GetEnumerator() = (f() :> IEnumerator) } namespace Microsoft.FSharp.Collections.SeqComposition - open System open System.Collections open System.Collections.Generic @@ -187,6 +186,857 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract member PushTransform<'U> : TransformFactory<'T,'U> -> ISeq<'U> abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result +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.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 Internal = + open Core + + module internal Upcast = + // The f# compiler outputs unnecessary unbox.any calls in upcasts. If this functionality + // is fixed with the compiler then these functions can be removed. + let inline seq<'T,'seq when 'seq :> ISeq<'T> and 'seq : not struct> (t:'seq) : ISeq<'T> = (# "" t : ISeq<'T> #) + let inline enumerable<'T,'enumerable when 'enumerable :> IEnumerable<'T> and 'enumerable : not struct> (t:'enumerable) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) + let inline enumerableNonGeneric<'enumerable when 'enumerable :> IEnumerable and 'enumerable : not struct> (t:'enumerable) : IEnumerable = (# "" t : IEnumerable #) + let inline enumerator<'T,'enumerator when 'enumerator :> IEnumerator<'T> and 'enumerator : not struct> (t:'enumerator) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) + let inline enumeratorNonGeneric<'enumerator when 'enumerator :> IEnumerator and 'enumerator : not struct> (t:'enumerator) : IEnumerator = (# "" t : IEnumerator #) + let inline outOfBand<'outOfBand when 'outOfBand :> IOutOfBand and 'outOfBand : not struct> (t:'outOfBand) : IOutOfBand = (# "" t : IOutOfBand #) + + type ComposedFactory<'T,'U,'V> private (first:TransformFactory<'T,'U>, second:TransformFactory<'U,'V>) = + inherit TransformFactory<'T,'V>() + + override this.Compose<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = + first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) + + static member Combine (first:TransformFactory<'T,'U>) (second:TransformFactory<'U,'V>) : TransformFactory<'T,'V> = + upcast ComposedFactory(first, second) + + type IdentityFactory<'T> private () = + inherit TransformFactory<'T,'T> () + static let singleton : TransformFactory<'T,'T> = upcast (IdentityFactory<'T>()) + override __.Compose<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next + static member Instance = singleton + + type ISkipable = + // Seq.init(Infinite)? lazily uses Current. The only ISeq component that can do that is Skip + // and it can only do it at the start of a sequence + abstract CanSkip : unit -> bool + + let createFold (factory:TransformFactory<_,_>) (folder:Folder<_,_>) pipeIdx = + factory.Compose (Upcast.outOfBand folder) pipeIdx folder + + module Fold = + // The consumers of IIterate are the execute and exeuteThin methods. IIterate is passed + // as a generic argument. The types that implement IIterate are value types. This combination + // means that the runtime will "inline" the methods. The alternatives to this were that the + // code in execute/executeThin were duplicated for each of the Fold types, or we turned the + // types back into normal functions and curried them then we would be creating garbage + // each time one of these were called. This has been an optimization to minimize the impact + // on very small collections. + type IIterate<'T> = + abstract Iterate<'U,'Result,'State> : outOfBand:Folder<'U,'Result> -> consumer:Activity<'T,'U> -> unit + + [] + type IterateEnumerable<'T> (enumerable:IEnumerable<'T>) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = + use enumerator = enumerable.GetEnumerator () + let rec iterate () = + if outOfBand.HaltedIdx = 0 && enumerator.MoveNext () then + consumer.ProcessNext enumerator.Current |> ignore + iterate () + iterate () + + [] + type IterateArray<'T> (array:array<'T>) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = + let array = array + let rec iterate idx = + if outOfBand.HaltedIdx = 0 && idx < array.Length then + consumer.ProcessNext array.[idx] |> ignore + iterate (idx+1) + iterate 0 + + [] + type IterateResizeArray<'T> (array:ResizeArray<'T>) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = + let array = array + let rec iterate idx = + if outOfBand.HaltedIdx = 0 && idx < array.Count then + consumer.ProcessNext array.[idx] |> ignore + iterate (idx+1) + iterate 0 + + [] + type IterateList<'T> (alist:list<'T>) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = + let rec iterate lst = + match lst with + | hd :: tl when outOfBand.HaltedIdx = 0 -> + consumer.ProcessNext hd |> ignore + iterate tl + | _ -> () + iterate alist + + [] + type IterateSingleton<'T> (item:'T) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = + if outOfBand.HaltedIdx = 0 then + consumer.ProcessNext item |> ignore + + [] + type IterateUnfold<'S,'T> (generator:'S->option<'T*'S>, state:'S) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = + let generator = generator + let rec iterate current = + if outOfBand.HaltedIdx <> 0 then () + else + match generator current with + | Some (item, next) -> + consumer.ProcessNext item |> ignore + iterate next + | _ -> () + iterate state + + [] + type IterateInit<'T> (f:int->'T, terminatingIdx:int) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = + let terminatingIdx = terminatingIdx + let f = f + + let firstIdx = + match box consumer with + | :? ISkipable as skipping -> + let rec skip idx = + if idx = terminatingIdx || outOfBand.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 outOfBand.HaltedIdx = 0 then + iterate (idx+1) + else + idx + else + idx + + let finalIdx = iterate firstIdx + if outOfBand.HaltedIdx = 0 && finalIdx = System.Int32.MaxValue then + raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + + // execute, and it's companion, executeThin, are hosting functions that ensure the correct sequence + // of creation, iteration and disposal for the pipeline + let execute (createFolder:PipeIdx->Folder<'U,'Result>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (executeOn:#IIterate<'T>) = + let result = createFolder (pipeIdx+1) + let consumer = createFold transformFactory result pipeIdx + try + executeOn.Iterate result consumer + consumer.ChainComplete result.HaltedIdx + result.Result + finally + consumer.ChainDispose () + + // executeThin is a specialization of execute, provided as a performance optimization, that can + // be used when a sequence has been wrapped in an ISeq, but hasn't had an items added to its pipeline + // i.e. a container that has ISeq.ofSeq applied. + let executeThin (createFolder:PipeIdx->Folder<'T,'Result>) (executeOn:#IIterate<'T>) = + let result = createFolder 1 + try + executeOn.Iterate result result + result.ChainComplete result.HaltedIdx + result.Result + finally + result.ChainDispose () + + let executeConcat<'T,'U,'Result,'State,'Collection when 'Collection :> ISeq<'T>> (createFolder:PipeIdx->Folder<'U,'Result>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (sources:ISeq<'Collection>) = + let result = createFolder (pipeIdx+1) + let consumer = createFold transformFactory result pipeIdx + try + let common = + { new Folder<'T,NoValue>(Unchecked.defaultof<_>) with + override me.ProcessNext value = consumer.ProcessNext value } + + sources.Fold (fun _ -> + { new Folder<'Collection,NoValue>(Unchecked.defaultof<_>) with + override me.ProcessNext value = + value.Fold (fun _ -> common) |> ignore + me.HaltedIdx <- common.HaltedIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) }) |> ignore + + consumer.ChainComplete result.HaltedIdx + result.Result + finally + result.ChainDispose () + + let executeConcatThin<'T,'Result,'State,'Collection when 'Collection :> ISeq<'T>> (createFolder:PipeIdx->Folder<'T,'Result>) (sources:ISeq<'Collection>) = + let result = createFolder 1 + try + let common = + { new Folder<'T,NoValue>(Unchecked.defaultof<_>) with + override me.ProcessNext value = result.ProcessNext value } + + sources.Fold (fun _ -> + { new Folder<'Collection,NoValue>(Unchecked.defaultof<_>) with + override me.ProcessNext value = + value.Fold (fun _ -> common) |> ignore + me.HaltedIdx <- common.HaltedIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) }) |> ignore + + result.ChainComplete result.HaltedIdx + result.Result + finally + result.ChainDispose () + + type SeqProcessNextStates = + | InProcess = 0 + | NotStarted = 1 + | Finished = 2 + + type Result<'T>() = + inherit Folder<'T,'T>(Unchecked.defaultof<'T>) + + member val SeqState = SeqProcessNextStates.NotStarted with get, set + + override this.ProcessNext (input:'T) : bool = + this.Result <- input + true + + 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 EnumeratorBase<'T>(result:Result<'T>, activity:Activity) = + interface IDisposable with + member __.Dispose () : unit = + activity.ChainDispose () + + interface IEnumerator with + member this.Current : obj = box ((Upcast.enumerator this)).Current + member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)" + member __.Reset () : unit = noReset () + + interface IEnumerator<'T> with + member __.Current = + if result.SeqState = SeqProcessNextStates.InProcess then result.Result + else + match result.SeqState with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> failwith "library implementation error: all states should have been handled" + + type VanillaEnumerator<'T,'U>(source:IEnumerator<'T>, activity:Activity<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, activity) + + let rec moveNext () = + if (result.HaltedIdx = 0) && source.MoveNext () then + if activity.ProcessNext source.Current then + true + else + moveNext () + else + result.SeqState <- SeqProcessNextStates.Finished + activity.ChainComplete result.HaltedIdx + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + interface IDisposable with + member __.Dispose () = + try + source.Dispose () + finally + activity.ChainDispose () + + type ConcatEnumerator<'T,'U,'Collection when 'Collection :> IEnumerable<'T>> (sources:IEnumerable<'Collection>, activity:Activity<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, activity) + + let main = sources.GetEnumerator () + + let mutable active = EmptyEnumerators.Element + + let rec moveNext () = + if result.HaltedIdx <> 0 then false + else + if active.MoveNext () then + if activity.ProcessNext active.Current then + true + else + moveNext () + elif main.MoveNext () then + active.Dispose () + active <- main.Current.GetEnumerator () + moveNext () + else + result.SeqState <- SeqProcessNextStates.Finished + activity.ChainComplete result.HaltedIdx + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + interface IDisposable with + member __.Dispose () = + try + main.Dispose () + active.Dispose () + finally + activity.ChainDispose () + + type ListEnumerator<'T,'U>(alist:list<'T>, activity:Activity<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, activity) + + 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 <- SeqProcessNextStates.Finished + activity.ChainComplete result.HaltedIdx + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext list + + let length (source:ISeq<_>) = + source.Fold (fun _ -> + { new Folder<'T,int>(0) with + override this.ProcessNext v = + this.Result <- this.Result + 1 + Unchecked.defaultof<_> (* return value unused in Fold context *) }) + + [] + type EnumerableBase<'T> () = + let derivedClassShouldImplement () = + failwith "library implementation error: derived class should implement (should be abstract)" + + abstract member Append : ISeq<'T> -> ISeq<'T> + abstract member Length : unit -> int + + default this.Append source = Upcast.seq (AppendEnumerable [source; this]) + default this.Length () = length this + + interface IEnumerable with + member this.GetEnumerator () : IEnumerator = + let genericEnumerable = Upcast.enumerable this + let genericEnumerator = genericEnumerable.GetEnumerator () + Upcast.enumeratorNonGeneric genericEnumerator + + interface IEnumerable<'T> with + // fsharp doesn't allow abstract interface methods + member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () + + interface ISeq<'T> with + // fsharp doesn't allow abstract interface methods + member __.PushTransform _ = derivedClassShouldImplement () + member __.Fold _ = derivedClassShouldImplement () + + and VanillaEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new VanillaEnumerator<'T,'U>(enumerable.GetEnumerator(), createFold current result pipeIdx, result)) + + interface ISeq<'U> with + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new VanillaEnumerable<'T,'V>(enumerable, ComposedFactory.Combine current next, pipeIdx+1)) + + member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = + Fold.execute f current pipeIdx (Fold.IterateEnumerable enumerable) + + and ConcatEnumerable<'T,'U,'Collection when 'Collection :> ISeq<'T>> (sources:ISeq<'Collection>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() + + interface IEnumerable<'U> with + member __.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new ConcatEnumerator<'T,'U,'Collection>(sources, createFold current result pipeIdx, result)) + + interface ISeq<'U> with + member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new ConcatEnumerable<'T,'V,'Collection>(sources, ComposedFactory.Combine current next, pipeIdx+1)) + + member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = + Fold.executeConcat f current pipeIdx sources + + and ThinConcatEnumerable<'T, 'Sources, 'Collection when 'Collection :> ISeq<'T>> (sources:'Sources, preEnumerate:'Sources->ISeq<'Collection>) = + inherit EnumerableBase<'T>() + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = + let result = Result<'T> () + Upcast.enumerator (new ConcatEnumerator<'T,'T,'Collection> (preEnumerate sources, createFold IdentityFactory.Instance result 1, result)) + + interface ISeq<'T> with + member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (ConcatEnumerable<'T,'V,'Collection>(preEnumerate sources, next, 1)) + + member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = + Fold.executeConcatThin f (preEnumerate sources) + + and AppendEnumerable<'T> (sources:list>) = + inherit ThinConcatEnumerable<'T, list>, ISeq<'T>>(sources, fun sources -> Upcast.seq (ThinListEnumerable>(List.rev sources))) + + override this.Append source = + Upcast.seq (AppendEnumerable (source::sources)) + + and ThinListEnumerable<'T>(alist:list<'T>) = + inherit EnumerableBase<'T>() + + override __.Length () = alist.Length + + interface IEnumerable<'T> with + member __.GetEnumerator () = (Upcast.enumerable alist).GetEnumerator () + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new ListEnumerable<'T,'U>(alist, next, 1)) + + member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = + Fold.executeThin f (Fold.IterateList alist) + + and ListEnumerable<'T,'U>(alist:list<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new ListEnumerator<'T,'U>(alist, createFold transformFactory result pipeIdx, result)) + + interface ISeq<'U> with + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new ListEnumerable<'T,'V>(alist, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + + member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = + Fold.execute f transformFactory pipeIdx (Fold.IterateList alist) + + /// ThinEnumerable is used when the IEnumerable provided to ofSeq is neither an array or a list + type ThinEnumerable<'T>(enumerable:IEnumerable<'T>) = + inherit EnumerableBase<'T>() + + override __.Length () = + match enumerable with + | :? ICollection<'T> as a -> a.Count +#if !FSCORE_PORTABLE_OLD + | :? IReadOnlyCollection<'T> as a -> a.Count +#endif + | _ -> + use e = enumerable.GetEnumerator () + let mutable count = 0 + while e.MoveNext () do + count <- count + 1 + count + + interface IEnumerable<'T> with + member __.GetEnumerator () = enumerable.GetEnumerator () + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new VanillaEnumerable<'T,'U>(enumerable, next, 1)) + + member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = + Fold.executeThin f (Fold.IterateEnumerable enumerable) + + type DelayedEnumerable<'T>(delayed:unit->ISeq<'T>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'T>() + + override __.Length () = + match delayed() with + | :? EnumerableBase<'T> as s -> s.Length () + | s -> length s + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = (delayed()).GetEnumerator () + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new DelayedEnumerable<'U>((fun () -> (delayed()).PushTransform next), pipeIdx+1)) + + member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = + (delayed()).Fold f + + type EmptyEnumerable<'T> private () = + inherit EnumerableBase<'T>() + + static let singleton = EmptyEnumerable<'T>() :> ISeq<'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 ISeq<'T> with + member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (VanillaEnumerable<'T,'V>(this, next, 1)) + + member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = + Fold.executeThin f (Fold.IterateEnumerable this) + + type ArrayEnumerator<'T,'U>(array:array<'T>, activity:Activity<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, activity) + + let mutable idx = 0 + + let rec moveNext () = + if (result.HaltedIdx = 0) && idx < array.Length then + idx <- idx+1 + if activity.ProcessNext array.[idx-1] then + true + else + moveNext () + else + result.SeqState <- SeqProcessNextStates.Finished + activity.ChainComplete result.HaltedIdx + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type ArrayEnumerable<'T,'U>(array:array<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() + + interface IEnumerable<'U> with + member __.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new ArrayEnumerator<'T,'U>(array, createFold transformFactory result pipeIdx, result)) + + interface ISeq<'U> with + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new ArrayEnumerable<'T,'V>(array, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + + member __.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = + Fold.execute f transformFactory pipeIdx (Fold.IterateArray array) + + type ThinArrayEnumerable<'T>(array:array<'T>) = + inherit EnumerableBase<'T>() + + override __.Length () = array.Length + + interface IEnumerable<'T> with + member __.GetEnumerator () = (Upcast.enumerable array).GetEnumerator () + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new ArrayEnumerable<'T,'U>(array, next, 1)) + + member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = + Fold.executeThin f (Fold.IterateArray array) + + type SingletonEnumerable<'T>(item:'T) = + inherit EnumerableBase<'T>() + + override __.Length () = 1 + + interface IEnumerable<'T> with + member this.GetEnumerator () = Upcast.enumerator (new Singleton<'T>(item)) + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new ArrayEnumerable<'T,'U>([|item|], next, 1)) + + member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = + Fold.executeThin f (Fold.IterateSingleton item) + + type ResizeArrayEnumerator<'T,'U>(array:ResizeArray<'T>, activity:Activity<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, activity) + + let mutable idx = 0 + + let rec moveNext () = + if (result.HaltedIdx = 0) && idx < array.Count then + idx <- idx+1 + if activity.ProcessNext array.[idx-1] then + true + else + moveNext () + else + result.SeqState <- SeqProcessNextStates.Finished + activity.ChainComplete result.HaltedIdx + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type ResizeArrayEnumerable<'T,'U>(resizeArray:ResizeArray<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new ResizeArrayEnumerator<'T,'U>(resizeArray, createFold transformFactory result pipeIdx, result)) + + interface ISeq<'U> with + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new ResizeArrayEnumerable<'T,'V>(resizeArray, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + + member __.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = + Fold.execute f transformFactory pipeIdx (Fold.IterateResizeArray resizeArray) + + type ThinResizeArrayEnumerable<'T>(resizeArray:ResizeArray<'T>) = + inherit EnumerableBase<'T>() + + override __.Length () = resizeArray.Count + + interface IEnumerable<'T> with + member __.GetEnumerator () = (Upcast.enumerable resizeArray).GetEnumerator () + + interface ISeq<'T> with + member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new ResizeArrayEnumerable<'T,'U>(resizeArray, next, 1)) + + member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = + Fold.executeThin f (Fold.IterateResizeArray resizeArray) + + type UnfoldEnumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, activity:Activity<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, activity) + + let mutable current = state + + let rec moveNext () = + if result.HaltedIdx <> 0 then + false + else + match generator current with + | Some (item, nextState) -> + current <- nextState + if activity.ProcessNext item then + true + else + moveNext () + | _ -> false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type UnfoldEnumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new UnfoldEnumerator<'T,'U,'GeneratorState>(generator, state, createFold transformFactory result pipeIdx, result)) + + interface ISeq<'U> with + member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new UnfoldEnumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + + member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = + Fold.execute f transformFactory pipeIdx (Fold.IterateUnfold (generator, state)) + + 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, activity:Activity<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, activity) + + let isSkipping = + match box activity with + | :? ISkipable as skip -> skip.CanSkip + | _ -> fun () -> false + + let terminatingIdx = + getInitTerminatingIdx count + + let mutable maybeSkipping = true + let mutable idx = -1 + + let rec moveNext () = + if result.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 + moveNext () + elif activity.ProcessNext (f idx) then + true + else + moveNext () + elif result.HaltedIdx = 0 && idx = System.Int32.MaxValue then + raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + else + result.SeqState <- SeqProcessNextStates.Finished + activity.ChainComplete result.HaltedIdx + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type InitEnumerable<'T,'U>(count:Nullable, f:int->'T, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new InitEnumerator<'T,'U>(count, f, createFold transformFactory result pipeIdx, result)) + + interface ISeq<'U> with + member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new InitEnumerable<'T,'V>(count, f, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + + member this.Fold<'Result> (createResult:PipeIdx->Folder<'U,'Result>) = + let terminatingIdx = getInitTerminatingIdx count + Fold.execute createResult transformFactory pipeIdx (Fold.IterateInit (f, terminatingIdx)) + + // 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 ISeq<'T> with + member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (InitEnumerable<'T,'V>(count, f, next, pipeIdx+1)) + + member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = + Fold.executeThin f (Fold.IterateEnumerable (Upcast.enumerable this)) namespace Microsoft.FSharp.Core.CompilerServices @@ -201,6 +1051,8 @@ 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.Internal module RuntimeHelpers = @@ -410,6 +1262,8 @@ namespace Microsoft.FSharp.Core.CompilerServices 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 : next:byref> -> int // 0 = Stop, 1 = Yield, 2 = Goto abstract Close: unit -> unit @@ -447,7 +1301,7 @@ namespace Microsoft.FSharp.Core.CompilerServices 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 () member x.Dispose() = if redirect then redirectTo.Close() else x.Close() interface IEnumerator with member x.Current = box (if redirect then redirectTo.LastGenerated else x.LastGenerated) @@ -456,3 +1310,61 @@ namespace Microsoft.FSharp.Core.CompilerServices member x.MoveNext() = x.MoveNextImpl() member x.Reset() = raise <| new System.NotSupportedException() + + interface ISeq<'T> with + member this.PushTransform<'U> (next:TransformFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new GeneratedSequenceBaseEnumerable<'T,'U>(this, next, 1)) + + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = + let result = createFolder 1 + try + use maybeGeneratedSequenceBase = this.GetFreshEnumerator () + match maybeGeneratedSequenceBase with + | :? GeneratedSequenceBase<'T> as optimized -> + // avoids two virtual function calls + // FUTURE OPTIMIZATION: Store Current element in this class so it can be accessed non-virtual + while result.HaltedIdx = 0 && optimized.MoveNextImpl () do + result.ProcessNext (optimized.GetCurrent ()) |> ignore + | standard -> + // this path shouldn't occur, as GetFreshEnumerator should return a GeneratedSequenceBase<'T> derived class + while result.HaltedIdx = 0 && standard.MoveNext () do + result.ProcessNext standard.Current |> ignore + + result.ChainComplete result.HaltedIdx + result.Result + finally + result.ChainDispose () + + and GeneratedSequenceBaseEnumerable<'T,'U>(generatedSequence:GeneratedSequenceBase<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new VanillaEnumerator<'T,'U>(generatedSequence.GetFreshEnumerator(), current.Compose (Upcast.outOfBand result) pipeIdx result, result)) + + interface ISeq<'U> with + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new GeneratedSequenceBaseEnumerable<'T,'V>(generatedSequence, ComposedFactory.Combine current next, pipeIdx+1)) + + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = + let result = createFolder (pipeIdx+1) + let consumer = current.Compose (Upcast.outOfBand result) pipeIdx result + try + use maybeGeneratedSequenceBase = generatedSequence.GetFreshEnumerator () + match maybeGeneratedSequenceBase with + | :? GeneratedSequenceBase<'T> as optimized -> + // avoids two virtual function calls + // FUTURE OPTIMIZATION: Store Current element in this class so it can be accessed non-virtual + while result.HaltedIdx = 0 && optimized.MoveNextImpl () do + consumer.ProcessNext (optimized.GetCurrent ()) |> ignore + | standard -> + // this path shouldn't occur, as GetFreshEnumerator should return a GeneratedSequenceBase<'T> derived class + while result.HaltedIdx = 0 && standard.MoveNext () do + consumer.ProcessNext standard.Current |> ignore + + consumer.ChainComplete result.HaltedIdx + result.Result + finally + consumer.ChainDispose () + diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index ab3ed7e2f4..e4dbfb14a9 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -121,6 +121,101 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract member PushTransform : TransformFactory<'T,'U> -> ISeq<'U> abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result +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 + + module internal Internal = + [] + type IdentityFactory<'T> = + inherit TransformFactory<'T,'T> + static member Instance : TransformFactory<'T,'T> + + type ISkipable = + // Seq.init(Infinite)? lazily uses Current. The only ISeq component that can do that is Skip + // and it can only do it at the start of a sequence + abstract CanSkip : unit -> bool + + val length : ISeq<'T> -> int + + [] + type EnumerableBase<'T> = + new : unit -> EnumerableBase<'T> + abstract member Append : ISeq<'T> -> ISeq<'T> + abstract member Length : unit -> int + interface IEnumerable + interface IEnumerable<'T> + interface ISeq<'T> + + type ThinConcatEnumerable<'T, 'Sources, 'Collection when 'Collection :> ISeq<'T>> = + inherit EnumerableBase<'T> + new : 'Sources * ('Sources->ISeq<'Collection>) -> ThinConcatEnumerable<'T, 'Sources, 'Collection> + interface ISeq<'T> + + type AppendEnumerable<'T> = + inherit ThinConcatEnumerable<'T, list>, ISeq<'T>> + new : list> -> AppendEnumerable<'T> + override Append : ISeq<'T> -> ISeq<'T> + + type ThinListEnumerable<'T> = + inherit EnumerableBase<'T> + new : list<'T> -> ThinListEnumerable<'T> + interface ISeq<'T> + + type ThinResizeArrayEnumerable<'T> = + inherit EnumerableBase<'T> + new : ResizeArray<'T> -> ThinResizeArrayEnumerable<'T> + interface ISeq<'T> + + type ThinArrayEnumerable<'T> = + inherit EnumerableBase<'T> + new : array<'T> -> ThinArrayEnumerable<'T> + interface ISeq<'T> + + type ThinEnumerable<'T> = + inherit EnumerableBase<'T> + new : IEnumerable<'T> -> ThinEnumerable<'T> + interface ISeq<'T> + + type UnfoldEnumerable<'T,'U,'GeneratorState> = + inherit EnumerableBase<'U> + new : ('GeneratorState->option<'T*'GeneratorState>)*'GeneratorState*TransformFactory<'T,'U>*PipeIdx -> UnfoldEnumerable<'T,'U,'GeneratorState> + interface ISeq<'U> + + type InitEnumerableDecider<'T> = + inherit EnumerableBase<'T> + new : Nullable* (int->'T) * PipeIdx -> InitEnumerableDecider<'T> + interface ISeq<'T> + + type SingletonEnumerable<'T> = + inherit EnumerableBase<'T> + new : 'T -> SingletonEnumerable<'T> + interface ISeq<'T> + + type InitEnumerable<'T,'U> = + inherit EnumerableBase<'U> + new : Nullable * (int->'T) * TransformFactory<'T,'U> * PipeIdx -> InitEnumerable<'T,'U> + interface ISeq<'U> + + type DelayedEnumerable<'T> = + inherit EnumerableBase<'T> + new : (unit->ISeq<'T>) * PipeIdx -> DelayedEnumerable<'T> + interface ISeq<'T> + + type EmptyEnumerable<'T> = + inherit EnumerableBase<'T> + private new : unit -> EmptyEnumerable<'T> + static member Instance : ISeq<'T> + interface ISeq<'T> + namespace Microsoft.FSharp.Core.CompilerServices open System @@ -214,3 +309,4 @@ namespace Microsoft.FSharp.Core.CompilerServices interface IEnumerable interface IEnumerator<'T> interface IEnumerator + interface SeqComposition.ISeq<'T> From 138f235f95497a4a935f4e7779fb06b66008c0b6 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 6 Apr 2017 16:30:16 +1000 Subject: [PATCH 42/83] GeneratedSequenceBase inherit EnumerableBase --- src/fsharp/FSharp.Core/iseq.fs | 4 +-- src/fsharp/FSharp.Core/seqcore.fs | 49 ++++++++++++++++-------------- src/fsharp/FSharp.Core/seqcore.fsi | 48 ++++++++++++++--------------- 3 files changed, 52 insertions(+), 49 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index ec01f198be..ea3374de3f 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -14,7 +14,7 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Collections open Microsoft.FSharp.Primitives.Basics open Microsoft.FSharp.Collections.SeqComposition - open Microsoft.FSharp.Collections.SeqComposition.Internal + open Microsoft.FSharp.Collections.SeqComposition.Core [] module ISeq = @@ -172,7 +172,7 @@ namespace Microsoft.FSharp.Collections override this.OnDispose () = () }) [] - let empty<'T> = Microsoft.FSharp.Collections.SeqComposition.Internal.EmptyEnumerable<'T>.Instance + let empty<'T> = Microsoft.FSharp.Collections.SeqComposition.Core.EmptyEnumerable<'T>.Instance [] let exactlyOne (source:ISeq<'T>) : 'T = diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index fdf0973e69..117afb742b 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -202,9 +202,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition [] type NoValue = struct end - module internal Internal = - open Core - module internal Upcast = // The f# compiler outputs unnecessary unbox.any calls in upcasts. If this functionality // is fixed with the compiler then these functions can be removed. @@ -1052,7 +1049,7 @@ namespace Microsoft.FSharp.Core.CompilerServices open System.Collections open System.Collections.Generic open Microsoft.FSharp.Collections.SeqComposition - open Microsoft.FSharp.Collections.SeqComposition.Internal + open Microsoft.FSharp.Collections.SeqComposition.Core module RuntimeHelpers = @@ -1259,6 +1256,8 @@ namespace Microsoft.FSharp.Core.CompilerServices [] type GeneratedSequenceBase<'T>() = + inherit EnumerableBase<'T>() + let mutable redirectTo : GeneratedSequenceBase<'T> = Unchecked.defaultof<_> let mutable redirect : bool = false @@ -1320,21 +1319,30 @@ namespace Microsoft.FSharp.Core.CompilerServices try use maybeGeneratedSequenceBase = this.GetFreshEnumerator () match maybeGeneratedSequenceBase with - | :? GeneratedSequenceBase<'T> as optimized -> - // avoids two virtual function calls - // FUTURE OPTIMIZATION: Store Current element in this class so it can be accessed non-virtual - while result.HaltedIdx = 0 && optimized.MoveNextImpl () do - result.ProcessNext (optimized.GetCurrent ()) |> ignore - | standard -> - // this path shouldn't occur, as GetFreshEnumerator should return a GeneratedSequenceBase<'T> derived class - while result.HaltedIdx = 0 && standard.MoveNext () do - result.ProcessNext standard.Current |> ignore + | :? GeneratedSequenceBase<'T> as e -> // avoids two virtual function calls + while result.HaltedIdx = 0 && e.MoveNextImpl () do + result.ProcessNext (e.GetCurrent ()) |> ignore + | e -> + while result.HaltedIdx = 0 && e.MoveNext () do + result.ProcessNext e.Current |> ignore result.ChainComplete result.HaltedIdx result.Result finally result.ChainDispose () + override this.Length () = + use maybeGeneratedSequenceBase = this.GetFreshEnumerator () + let mutable count = 0 + match maybeGeneratedSequenceBase with + | :? GeneratedSequenceBase<'T> as e -> + while e.MoveNextImpl () do + count <- count + 1 + | e -> + while e.MoveNext () do + count <- count + 1 + count + and GeneratedSequenceBaseEnumerable<'T,'U>(generatedSequence:GeneratedSequenceBase<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() @@ -1353,15 +1361,12 @@ namespace Microsoft.FSharp.Core.CompilerServices try use maybeGeneratedSequenceBase = generatedSequence.GetFreshEnumerator () match maybeGeneratedSequenceBase with - | :? GeneratedSequenceBase<'T> as optimized -> - // avoids two virtual function calls - // FUTURE OPTIMIZATION: Store Current element in this class so it can be accessed non-virtual - while result.HaltedIdx = 0 && optimized.MoveNextImpl () do - consumer.ProcessNext (optimized.GetCurrent ()) |> ignore - | standard -> - // this path shouldn't occur, as GetFreshEnumerator should return a GeneratedSequenceBase<'T> derived class - while result.HaltedIdx = 0 && standard.MoveNext () do - consumer.ProcessNext standard.Current |> ignore + | :? GeneratedSequenceBase<'T> as e -> + while result.HaltedIdx = 0 && e.MoveNextImpl () do + consumer.ProcessNext (e.GetCurrent ()) |> ignore + | e -> + while result.HaltedIdx = 0 && e.MoveNext () do + consumer.ProcessNext e.Current |> ignore consumer.ChainComplete result.HaltedIdx result.Result diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index e4dbfb14a9..9148f04d40 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -133,84 +133,81 @@ namespace Microsoft.FSharp.Collections.SeqComposition [] type NoValue = struct end - module internal Internal = + [] + type EnumerableBase<'T> = + new : unit -> EnumerableBase<'T> + abstract member Append : ISeq<'T> -> ISeq<'T> + abstract member Length : unit -> int + interface ISeq<'T> + [] - type IdentityFactory<'T> = + type internal IdentityFactory<'T> = inherit TransformFactory<'T,'T> static member Instance : TransformFactory<'T,'T> - type ISkipable = + type internal ISkipable = // Seq.init(Infinite)? lazily uses Current. The only ISeq component that can do that is Skip // and it can only do it at the start of a sequence abstract CanSkip : unit -> bool - val length : ISeq<'T> -> int - - [] - type EnumerableBase<'T> = - new : unit -> EnumerableBase<'T> - abstract member Append : ISeq<'T> -> ISeq<'T> - abstract member Length : unit -> int - interface IEnumerable - interface IEnumerable<'T> - interface ISeq<'T> + val internal length : ISeq<'T> -> int - type ThinConcatEnumerable<'T, 'Sources, 'Collection when 'Collection :> ISeq<'T>> = + type internal ThinConcatEnumerable<'T, 'Sources, 'Collection when 'Collection :> ISeq<'T>> = inherit EnumerableBase<'T> new : 'Sources * ('Sources->ISeq<'Collection>) -> ThinConcatEnumerable<'T, 'Sources, 'Collection> interface ISeq<'T> - type AppendEnumerable<'T> = + type internal AppendEnumerable<'T> = inherit ThinConcatEnumerable<'T, list>, ISeq<'T>> new : list> -> AppendEnumerable<'T> override Append : ISeq<'T> -> ISeq<'T> - type ThinListEnumerable<'T> = + type internal ThinListEnumerable<'T> = inherit EnumerableBase<'T> new : list<'T> -> ThinListEnumerable<'T> interface ISeq<'T> - type ThinResizeArrayEnumerable<'T> = + type internal ThinResizeArrayEnumerable<'T> = inherit EnumerableBase<'T> new : ResizeArray<'T> -> ThinResizeArrayEnumerable<'T> interface ISeq<'T> - type ThinArrayEnumerable<'T> = + type internal ThinArrayEnumerable<'T> = inherit EnumerableBase<'T> new : array<'T> -> ThinArrayEnumerable<'T> interface ISeq<'T> - type ThinEnumerable<'T> = + type internal ThinEnumerable<'T> = inherit EnumerableBase<'T> new : IEnumerable<'T> -> ThinEnumerable<'T> interface ISeq<'T> - type UnfoldEnumerable<'T,'U,'GeneratorState> = + type internal UnfoldEnumerable<'T,'U,'GeneratorState> = inherit EnumerableBase<'U> new : ('GeneratorState->option<'T*'GeneratorState>)*'GeneratorState*TransformFactory<'T,'U>*PipeIdx -> UnfoldEnumerable<'T,'U,'GeneratorState> interface ISeq<'U> - type InitEnumerableDecider<'T> = + type internal InitEnumerableDecider<'T> = inherit EnumerableBase<'T> new : Nullable* (int->'T) * PipeIdx -> InitEnumerableDecider<'T> interface ISeq<'T> - type SingletonEnumerable<'T> = + type internal SingletonEnumerable<'T> = inherit EnumerableBase<'T> new : 'T -> SingletonEnumerable<'T> interface ISeq<'T> - type InitEnumerable<'T,'U> = + type internal InitEnumerable<'T,'U> = inherit EnumerableBase<'U> new : Nullable * (int->'T) * TransformFactory<'T,'U> * PipeIdx -> InitEnumerable<'T,'U> interface ISeq<'U> - type DelayedEnumerable<'T> = + type internal DelayedEnumerable<'T> = inherit EnumerableBase<'T> new : (unit->ISeq<'T>) * PipeIdx -> DelayedEnumerable<'T> interface ISeq<'T> - type EmptyEnumerable<'T> = + type internal EmptyEnumerable<'T> = inherit EnumerableBase<'T> private new : unit -> EmptyEnumerable<'T> static member Instance : ISeq<'T> @@ -285,6 +282,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. From ca5a95f32001ec53f87c32b0f3fc5b2a2abf878f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 7 Apr 2017 12:46:27 +1000 Subject: [PATCH 43/83] Promoted ISeq to prim_types --- src/fsharp/FSharp.Core/prim-types.fs | 52 ++++++++++++++++++++- src/fsharp/FSharp.Core/prim-types.fsi | 65 +++++++++++++++++++++++++++ src/fsharp/FSharp.Core/seqcore.fs | 51 --------------------- src/fsharp/FSharp.Core/seqcore.fsi | 65 --------------------------- 4 files changed, 116 insertions(+), 117 deletions(-) diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 5927be7f51..a5a8a270b5 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3701,12 +3701,62 @@ namespace Microsoft.FSharp.Collections type seq<'T> = IEnumerable<'T> + +namespace Microsoft.FSharp.Collections.SeqComposition + open System + open System.Collections + open System.Collections.Generic + open Microsoft.FSharp.Core + open Microsoft.FSharp.Collections + + type PipeIdx = int + + type IOutOfBand = + abstract StopFurtherProcessing : PipeIdx -> unit + + [] + type Activity() = + abstract ChainComplete : PipeIdx -> unit + abstract ChainDispose : unit -> unit + + [] + type Activity<'T,'U> () = + inherit Activity() + abstract ProcessNext : input:'T -> bool + + [] + type Folder<'T,'Result> = + inherit Activity<'T,'T> + + val mutable Result : 'Result + + val mutable HaltedIdx : int + member this.StopFurtherProcessing pipeIdx = this.HaltedIdx <- pipeIdx + interface IOutOfBand with + member this.StopFurtherProcessing pipeIdx = this.StopFurtherProcessing pipeIdx + + new (initalResult) = { + inherit Activity<'T,'T>() + HaltedIdx = 0 + Result = initalResult + } + + override this.ChainComplete _ = () + override this.ChainDispose () = () + + [] + type TransformFactory<'T,'U> () = + abstract Compose<'V> : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> + + type ISeq<'T> = + inherit IEnumerable<'T> + abstract member PushTransform<'U> : TransformFactory<'T,'U> -> ISeq<'U> + abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result //------------------------------------------------------------------------- // Operators //------------------------------------------------------------------------- - namespace Microsoft.FSharp.Core open System diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index 1850180616..d371992df3 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -1846,6 +1846,71 @@ namespace Microsoft.FSharp.Collections /// An abbreviation for the CLI type System.Collections.Generic.IEnumerable<_> type seq<'T> = IEnumerable<'T> +namespace Microsoft.FSharp.Collections.SeqComposition + open System + open System.Collections + open System.Collections.Generic + open Microsoft.FSharp.Core + open Microsoft.FSharp.Collections + + /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the + /// source of the chain. + type PipeIdx = int + + /// Used within the pipline to provide out of band communications + type IOutOfBand = + /// Stop the processing of any further items down the pipeline + abstract StopFurtherProcessing : PipeIdx -> unit + + /// Activity 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 Activity = + /// 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 ChainComplete : PipeIdx -> unit + /// OnDispose is used to cleanup the stream. It is always called at the last operation + /// after the enumeration has completed. + abstract ChainDispose : unit -> unit + + /// Activity is the base class of all elements within the pipeline + [] + type Activity<'T,'U> = + inherit Activity + new : unit -> Activity<'T,'U> + abstract member ProcessNext : input:'T -> bool + + /// Folder 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 Folder<'T,'Result> = + inherit Activity<'T,'T> + new : 'Result -> Folder<'T,'Result> + interface IOutOfBand + val mutable Result : 'Result + val mutable HaltedIdx : int + member StopFurtherProcessing : PipeIdx -> unit + override ChainComplete : PipeIdx -> unit + override ChainDispose : unit -> unit + + /// TransformFactory provides composition of Activities. Its intended to have a specialization + /// for each type of ISeq Activity. ISeq's PushTransform method is used to build a stack + /// of Actvities that will be composed. + [] + type TransformFactory<'T,'U> = + new : unit -> TransformFactory<'T,'U> + abstract member Compose : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> + + /// ISeq<'T> is an extension to seq<'T> that provides the avilty to compose Activities + /// as well as Fold the current Activity pipeline. + type ISeq<'T> = + inherit System.Collections.Generic.IEnumerable<'T> + abstract member PushTransform : TransformFactory<'T,'U> -> ISeq<'U> + abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result namespace Microsoft.FSharp.Core diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index 117afb742b..6378da6c94 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -135,57 +135,6 @@ 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 Microsoft.FSharp.Core - open Microsoft.FSharp.Collections - - type PipeIdx = int - - type IOutOfBand = - abstract StopFurtherProcessing : PipeIdx -> unit - - [] - type Activity() = - abstract ChainComplete : PipeIdx -> unit - abstract ChainDispose : unit -> unit - - [] - type Activity<'T,'U> () = - inherit Activity() - abstract ProcessNext : input:'T -> bool - - [] - type Folder<'T,'Result> = - inherit Activity<'T,'T> - - val mutable Result : 'Result - - val mutable HaltedIdx : int - member this.StopFurtherProcessing pipeIdx = this.HaltedIdx <- pipeIdx - interface IOutOfBand with - member this.StopFurtherProcessing pipeIdx = this.StopFurtherProcessing pipeIdx - - new (initalResult) = { - inherit Activity<'T,'T>() - HaltedIdx = 0 - Result = initalResult - } - - override this.ChainComplete _ = () - override this.ChainDispose () = () - - [] - type TransformFactory<'T,'U> () = - abstract Compose<'V> : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> - - type ISeq<'T> = - inherit IEnumerable<'T> - abstract member PushTransform<'U> : TransformFactory<'T,'U> -> ISeq<'U> - abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result - namespace Microsoft.FSharp.Collections.SeqComposition open System open System.Collections diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index 9148f04d40..631d022434 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -55,71 +55,6 @@ namespace Microsoft.FSharp.Collections 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 - - /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the - /// source of the chain. - type PipeIdx = int - - /// Used within the pipline to provide out of band communications - type IOutOfBand = - /// Stop the processing of any further items down the pipeline - abstract StopFurtherProcessing : PipeIdx -> unit - - /// Activity 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 Activity = - /// 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 ChainComplete : PipeIdx -> unit - /// OnDispose is used to cleanup the stream. It is always called at the last operation - /// after the enumeration has completed. - abstract ChainDispose : unit -> unit - - /// Activity is the base class of all elements within the pipeline - [] - type Activity<'T,'U> = - inherit Activity - new : unit -> Activity<'T,'U> - abstract member ProcessNext : input:'T -> bool - - /// Folder 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 Folder<'T,'Result> = - inherit Activity<'T,'T> - new : 'Result -> Folder<'T,'Result> - interface IOutOfBand - val mutable Result : 'Result - val mutable HaltedIdx : int - member StopFurtherProcessing : PipeIdx -> unit - override ChainComplete : PipeIdx -> unit - override ChainDispose : unit -> unit - - /// TransformFactory provides composition of Activities. Its intended to have a specialization - /// for each type of ISeq Activity. ISeq's PushTransform method is used to build a stack - /// of Actvities that will be composed. - [] - type TransformFactory<'T,'U> = - new : unit -> TransformFactory<'T,'U> - abstract member Compose : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> - - /// ISeq<'T> is an extension to seq<'T> that provides the avilty to compose Activities - /// as well as Fold the current Activity pipeline. - type ISeq<'T> = - inherit System.Collections.Generic.IEnumerable<'T> - abstract member PushTransform : TransformFactory<'T,'U> -> ISeq<'U> - abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result namespace Microsoft.FSharp.Collections.SeqComposition open System From 0f27eb3146ce281fc92b7abde1959e6cf7388dc8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Apr 2017 05:53:37 +1000 Subject: [PATCH 44/83] Spread ISeq into simpleIntegralRange --- src/fsharp/FSharp.Core/iseq.fs | 1 + src/fsharp/FSharp.Core/prim-types.fs | 127 ++++++++++++++++++++++++-- src/fsharp/FSharp.Core/prim-types.fsi | 10 ++ src/fsharp/FSharp.Core/seqcore.fs | 17 +--- src/fsharp/FSharp.Core/seqcore.fsi | 5 - 5 files changed, 134 insertions(+), 26 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index ea3374de3f..8a3f88a1ea 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -14,6 +14,7 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Collections open Microsoft.FSharp.Primitives.Basics open Microsoft.FSharp.Collections.SeqComposition + open Microsoft.FSharp.Collections.SeqComposition.Factories open Microsoft.FSharp.Collections.SeqComposition.Core [] diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index a5a8a270b5..51e17cacb3 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3753,6 +3753,22 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract member PushTransform<'U> : TransformFactory<'T,'U> -> ISeq<'U> abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result + module Factories = + type ComposedFactory<'T,'U,'V> private (first:TransformFactory<'T,'U>, second:TransformFactory<'U,'V>) = + inherit TransformFactory<'T,'V>() + + override this.Compose<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = + first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) + + static member Combine (first:TransformFactory<'T,'U>) (second:TransformFactory<'U,'V>) : TransformFactory<'T,'V> = + upcast ComposedFactory(first, second) + + type IdentityFactory<'T> private () = + inherit TransformFactory<'T,'T> () + static let singleton : TransformFactory<'T,'T> = upcast (IdentityFactory<'T>()) + override __.Compose<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next + static member Instance = singleton + //------------------------------------------------------------------------- // Operators //------------------------------------------------------------------------- @@ -3769,12 +3785,20 @@ 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 = + // The f# compiler outputs unnecessary unbox.any calls in upcasts. If this functionality + // is fixed with the compiler then these functions can be removed. + module Upcast = + let inline seq<'T,'seq when 'seq :> ISeq<'T> and 'seq : not struct> (t:'seq) : ISeq<'T> = (# "" t : ISeq<'T> #) + let inline enumerable<'T,'enumerable when 'enumerable :> IEnumerable<'T> and 'enumerable : not struct> (t:'enumerable) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) + let inline enumerableNonGeneric<'enumerable when 'enumerable :> System.Collections.IEnumerable and 'enumerable : not struct> (t:'enumerable) : System.Collections.IEnumerable = (# "" t : System.Collections.IEnumerable #) + let inline enumerator<'T,'enumerator when 'enumerator :> IEnumerator<'T> and 'enumerator : not struct> (t:'enumerator) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) + let inline enumeratorNonGeneric<'enumerator when 'enumerator :> System.Collections.IEnumerator and 'enumerator : not struct> (t:'enumerator) : System.Collections.IEnumerator = (# "" t : System.Collections.IEnumerator #) + let inline outOfBand<'outOfBand when 'outOfBand :> IOutOfBand and 'outOfBand : not struct> (t:'outOfBand) : IOutOfBand = (# "" t : IOutOfBand #) #if MULTI_DIMENSIONAL_EXTENSION_PROPERTIES type ``[,]``<'T> with @@ -5172,6 +5196,85 @@ namespace Microsoft.FSharp.Core | Running = 1 | Finished = 2 + type SetResultToInput<'T>() = + inherit Folder<'T,'T>(Unchecked.defaultof<'T>) + override this.ProcessNext (input:'T) : bool = + this.Result <- input + true + + type SeqSourceEnumerator<'T,'U>(source:IEnumerator<'T>, activity:Activity<'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 ((Upcast.enumerator this)).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 ISeqSource<'T> = + abstract member GetEnumerator : unit -> IEnumerator<'T> + abstract member Fold<'Result,'U> : f:(PipeIdx->Folder<'U,'Result>) -> TransformFactory<'T,'U> -> PipeIdx -> 'Result + + type SeqSourceEnumerable<'T,'U>(source:ISeqSource<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + interface IEnumerable<'U> with + member __.GetEnumerator () = + let folder = SetResultToInput<'U>() + Upcast.enumerator (new SeqSourceEnumerator<'T,'U>(source.GetEnumerator (), current.Compose (Upcast.outOfBand folder) pipeIdx folder, folder)) + + interface IEnumerable with + member __.GetEnumerator () = + let folder = SetResultToInput<'U>() + Upcast.enumeratorNonGeneric (new SeqSourceEnumerator<'T,'U>(source.GetEnumerator (), current.Compose (Upcast.outOfBand folder) pipeIdx folder, folder)) + + interface ISeq<'U> with + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new SeqSourceEnumerable<'T,'V>(source, Factories.ComposedFactory.Combine current next, pipeIdx+1)) + + member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = + source.Fold f current pipeIdx + + type SeqSourceEnumerableThin<'U>(source:ISeqSource<'U>) = + interface IEnumerable<'U> with + member __.GetEnumerator () = source.GetEnumerator () + + interface IEnumerable with + member __.GetEnumerator () = Upcast.enumeratorNonGeneric (source.GetEnumerator ()) + + interface ISeq<'U> with + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new SeqSourceEnumerable<'U,'V>(source, next, 1)) + + member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = + source.Fold f Factories.IdentityFactory.Instance 1 + [] type BaseRangeEnumerator<'T>() = // Generate enumerator from mutable state "z". @@ -5383,11 +5486,23 @@ namespace Microsoft.FSharp.Core false else false } - { new IEnumerable<'T> with + let source = { new ISeqSource<'T> with member __.GetEnumerator () = singleStepRangeEnumerator () - - interface IEnumerable with - member __.GetEnumerator () = (singleStepRangeEnumerator ()) :> IEnumerator } + member __.Fold<'Result,'Output> (createFolder:PipeIdx->Folder<'Output,'Result>) (transformFactory:TransformFactory<'T,'Output>) pipeIdx : 'Result = + let result = createFolder (pipeIdx+1) + let consumer = transformFactory.Compose (Upcast.outOfBand result) 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.enumerable (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 d371992df3..213f68eb2e 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -1912,6 +1912,16 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract member PushTransform : TransformFactory<'T,'U> -> ISeq<'U> abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result + module Factories = + [] + type ComposedFactory<'T,'U,'V> = + inherit TransformFactory<'T,'V> + static member Combine : TransformFactory<'T,'U> -> TransformFactory<'U,'V> -> TransformFactory<'T,'V> + + [] + type IdentityFactory<'T> = + inherit TransformFactory<'T,'T> + static member Instance : TransformFactory<'T,'T> namespace Microsoft.FSharp.Core diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index 6378da6c94..c1c97a1053 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -143,6 +143,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition open Microsoft.FSharp.Collections open Microsoft.FSharp.Collections.IEnumerator open Microsoft.FSharp.Collections.SeqComposition + open Microsoft.FSharp.Collections.SeqComposition.Factories open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators open Microsoft.FSharp.Primitives.Basics open Microsoft.FSharp.Control @@ -161,21 +162,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition let inline enumeratorNonGeneric<'enumerator when 'enumerator :> IEnumerator and 'enumerator : not struct> (t:'enumerator) : IEnumerator = (# "" t : IEnumerator #) let inline outOfBand<'outOfBand when 'outOfBand :> IOutOfBand and 'outOfBand : not struct> (t:'outOfBand) : IOutOfBand = (# "" t : IOutOfBand #) - type ComposedFactory<'T,'U,'V> private (first:TransformFactory<'T,'U>, second:TransformFactory<'U,'V>) = - inherit TransformFactory<'T,'V>() - - override this.Compose<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = - first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) - - static member Combine (first:TransformFactory<'T,'U>) (second:TransformFactory<'U,'V>) : TransformFactory<'T,'V> = - upcast ComposedFactory(first, second) - - type IdentityFactory<'T> private () = - inherit TransformFactory<'T,'T> () - static let singleton : TransformFactory<'T,'T> = upcast (IdentityFactory<'T>()) - override __.Compose<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next - static member Instance = singleton - type ISkipable = // Seq.init(Infinite)? lazily uses Current. The only ISeq component that can do that is Skip // and it can only do it at the start of a sequence @@ -998,6 +984,7 @@ namespace Microsoft.FSharp.Core.CompilerServices open System.Collections open System.Collections.Generic open Microsoft.FSharp.Collections.SeqComposition + open Microsoft.FSharp.Collections.SeqComposition.Factories open Microsoft.FSharp.Collections.SeqComposition.Core module RuntimeHelpers = diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index 631d022434..16236ea93d 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -75,11 +75,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract member Length : unit -> int interface ISeq<'T> - [] - type internal IdentityFactory<'T> = - inherit TransformFactory<'T,'T> - static member Instance : TransformFactory<'T,'T> - type internal ISkipable = // Seq.init(Infinite)? lazily uses Current. The only ISeq component that can do that is Skip // and it can only do it at the start of a sequence From 8663c25574ef69a0939929f20a73d9e8bddf770a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Apr 2017 15:09:34 +1000 Subject: [PATCH 45/83] Composed/Identity in prim_types didn't work (??) --- src/fsharp/FSharp.Core/iseq.fs | 1 - src/fsharp/FSharp.Core/prim-types.fs | 35 +++++++++++++-------------- src/fsharp/FSharp.Core/prim-types.fsi | 11 --------- src/fsharp/FSharp.Core/seqcore.fs | 17 +++++++++++-- src/fsharp/FSharp.Core/seqcore.fsi | 5 ++++ 5 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 8a3f88a1ea..ea3374de3f 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -14,7 +14,6 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Collections open Microsoft.FSharp.Primitives.Basics open Microsoft.FSharp.Collections.SeqComposition - open Microsoft.FSharp.Collections.SeqComposition.Factories open Microsoft.FSharp.Collections.SeqComposition.Core [] diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 51e17cacb3..23834c4ac3 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3753,22 +3753,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract member PushTransform<'U> : TransformFactory<'T,'U> -> ISeq<'U> abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result - module Factories = - type ComposedFactory<'T,'U,'V> private (first:TransformFactory<'T,'U>, second:TransformFactory<'U,'V>) = - inherit TransformFactory<'T,'V>() - - override this.Compose<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = - first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) - - static member Combine (first:TransformFactory<'T,'U>) (second:TransformFactory<'U,'V>) : TransformFactory<'T,'V> = - upcast ComposedFactory(first, second) - - type IdentityFactory<'T> private () = - inherit TransformFactory<'T,'T> () - static let singleton : TransformFactory<'T,'T> = upcast (IdentityFactory<'T>()) - override __.Compose<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next - static member Instance = singleton - //------------------------------------------------------------------------- // Operators //------------------------------------------------------------------------- @@ -5196,6 +5180,21 @@ namespace Microsoft.FSharp.Core | Running = 1 | Finished = 2 + type ComposedFactory<'T,'U,'V> private (first:TransformFactory<'T,'U>, second:TransformFactory<'U,'V>) = + inherit TransformFactory<'T,'V>() + + override this.Compose<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = + first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) + + static member Combine (first:TransformFactory<'T,'U>) (second:TransformFactory<'U,'V>) : TransformFactory<'T,'V> = + upcast ComposedFactory(first, second) + + type IdentityFactory<'T> private () = + inherit TransformFactory<'T,'T> () + static let singleton : TransformFactory<'T,'T> = upcast (IdentityFactory<'T>()) + override __.Compose<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next + static member Instance = singleton + type SetResultToInput<'T>() = inherit Folder<'T,'T>(Unchecked.defaultof<'T>) override this.ProcessNext (input:'T) : bool = @@ -5256,7 +5255,7 @@ namespace Microsoft.FSharp.Core interface ISeq<'U> with member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new SeqSourceEnumerable<'T,'V>(source, Factories.ComposedFactory.Combine current next, pipeIdx+1)) + Upcast.seq (new SeqSourceEnumerable<'T,'V>(source, ComposedFactory.Combine current next, pipeIdx+1)) member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = source.Fold f current pipeIdx @@ -5273,7 +5272,7 @@ namespace Microsoft.FSharp.Core Upcast.seq (new SeqSourceEnumerable<'U,'V>(source, next, 1)) member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = - source.Fold f Factories.IdentityFactory.Instance 1 + source.Fold f IdentityFactory.Instance 1 [] type BaseRangeEnumerator<'T>() = diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index 213f68eb2e..9a13904f2a 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -1912,17 +1912,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract member PushTransform : TransformFactory<'T,'U> -> ISeq<'U> abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result - module Factories = - [] - type ComposedFactory<'T,'U,'V> = - inherit TransformFactory<'T,'V> - static member Combine : TransformFactory<'T,'U> -> TransformFactory<'U,'V> -> TransformFactory<'T,'V> - - [] - type IdentityFactory<'T> = - inherit TransformFactory<'T,'T> - static member Instance : TransformFactory<'T,'T> - namespace Microsoft.FSharp.Core open System diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index c1c97a1053..6378da6c94 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -143,7 +143,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition open Microsoft.FSharp.Collections open Microsoft.FSharp.Collections.IEnumerator open Microsoft.FSharp.Collections.SeqComposition - open Microsoft.FSharp.Collections.SeqComposition.Factories open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators open Microsoft.FSharp.Primitives.Basics open Microsoft.FSharp.Control @@ -162,6 +161,21 @@ namespace Microsoft.FSharp.Collections.SeqComposition let inline enumeratorNonGeneric<'enumerator when 'enumerator :> IEnumerator and 'enumerator : not struct> (t:'enumerator) : IEnumerator = (# "" t : IEnumerator #) let inline outOfBand<'outOfBand when 'outOfBand :> IOutOfBand and 'outOfBand : not struct> (t:'outOfBand) : IOutOfBand = (# "" t : IOutOfBand #) + type ComposedFactory<'T,'U,'V> private (first:TransformFactory<'T,'U>, second:TransformFactory<'U,'V>) = + inherit TransformFactory<'T,'V>() + + override this.Compose<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = + first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) + + static member Combine (first:TransformFactory<'T,'U>) (second:TransformFactory<'U,'V>) : TransformFactory<'T,'V> = + upcast ComposedFactory(first, second) + + type IdentityFactory<'T> private () = + inherit TransformFactory<'T,'T> () + static let singleton : TransformFactory<'T,'T> = upcast (IdentityFactory<'T>()) + override __.Compose<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next + static member Instance = singleton + type ISkipable = // Seq.init(Infinite)? lazily uses Current. The only ISeq component that can do that is Skip // and it can only do it at the start of a sequence @@ -984,7 +998,6 @@ namespace Microsoft.FSharp.Core.CompilerServices open System.Collections open System.Collections.Generic open Microsoft.FSharp.Collections.SeqComposition - open Microsoft.FSharp.Collections.SeqComposition.Factories open Microsoft.FSharp.Collections.SeqComposition.Core module RuntimeHelpers = diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index 16236ea93d..631d022434 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -75,6 +75,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract member Length : unit -> int interface ISeq<'T> + [] + type internal IdentityFactory<'T> = + inherit TransformFactory<'T,'T> + static member Instance : TransformFactory<'T,'T> + type internal ISkipable = // Seq.init(Infinite)? lazily uses Current. The only ISeq component that can do that is Skip // and it can only do it at the start of a sequence From 4c84d549ae204e40081be7515ad7414325453e67 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Apr 2017 19:42:15 +1000 Subject: [PATCH 46/83] internal List.ofISeq --- src/fsharp/FSharp.Core/iseq.fs | 2 +- src/fsharp/FSharp.Core/local.fs | 26 ++++++++++++++++++++++++++ src/fsharp/FSharp.Core/local.fsi | 2 ++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index ea3374de3f..9433342094 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1131,7 +1131,7 @@ namespace Microsoft.FSharp.Collections [] let toList (source : ISeq<'T>) = checkNonNull "source" source - Microsoft.FSharp.Primitives.Basics.List.ofSeq source + Microsoft.FSharp.Primitives.Basics.List.ofISeq source [] let replicate count x = diff --git a/src/fsharp/FSharp.Core/local.fs b/src/fsharp/FSharp.Core/local.fs index d632dd29df..3eac3119ca 100644 --- a/src/fsharp/FSharp.Core/local.fs +++ b/src/fsharp/FSharp.Core/local.fs @@ -86,6 +86,7 @@ open Microsoft.FSharp.Core.ICloneableExtensions module internal List = + open Microsoft.FSharp.Collections.SeqComposition let arrayZeroCreate (n:int) = (# "newarr !0" type ('T) n : 'T array #) @@ -544,10 +545,35 @@ module internal List = res <- arr.[i] :: res res + type FoldToList<'T> () = + inherit Folder<'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 ofISeq (s : ISeq<'T>) = + s.Fold (fun _ -> upcast FoldToList()) + let inline ofSeq (e : IEnumerable<'T>) = match e with | :? list<'T> as l -> l | :? ('T[]) as arr -> ofArray arr + | :? ISeq<'T> as s -> ofISeq s | _ -> use ie = e.GetEnumerator() if not (ie.MoveNext()) then [] diff --git a/src/fsharp/FSharp.Core/local.fsi b/src/fsharp/FSharp.Core/local.fsi index dcf8f2a6e1..56ee687843 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 ofISeq : ISeq<'T> -> 'T List val inline ofSeq : seq<'T> -> 'T List val splitAt : int -> 'T list -> ('T list * 'T list) val truncate : int -> 'T list -> 'T list From a77005557e69427766a93a684dfdf9fcd67005dd Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Apr 2017 06:26:19 +1000 Subject: [PATCH 47/83] Removed Fold.(execute|executeThin) --- src/fsharp/FSharp.Core/seqcore.fs | 441 +++++++++++++++--------------- 1 file changed, 224 insertions(+), 217 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index 6378da6c94..fa1f705813 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -161,6 +161,12 @@ namespace Microsoft.FSharp.Collections.SeqComposition let inline enumeratorNonGeneric<'enumerator when 'enumerator :> IEnumerator and 'enumerator : not struct> (t:'enumerator) : IEnumerator = (# "" t : IEnumerator #) let inline outOfBand<'outOfBand when 'outOfBand :> IOutOfBand and 'outOfBand : not struct> (t:'outOfBand) : IOutOfBand = (# "" t : IOutOfBand #) + type IdentityFactory<'T> private () = + inherit TransformFactory<'T,'T> () + static let singleton : TransformFactory<'T,'T> = upcast (IdentityFactory<'T>()) + override __.Compose<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next + static member Instance = singleton + type ComposedFactory<'T,'U,'V> private (first:TransformFactory<'T,'U>, second:TransformFactory<'U,'V>) = inherit TransformFactory<'T,'V>() @@ -170,12 +176,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition static member Combine (first:TransformFactory<'T,'U>) (second:TransformFactory<'U,'V>) : TransformFactory<'T,'V> = upcast ComposedFactory(first, second) - type IdentityFactory<'T> private () = - inherit TransformFactory<'T,'T> () - static let singleton : TransformFactory<'T,'T> = upcast (IdentityFactory<'T>()) - override __.Compose<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next - static member Instance = singleton - type ISkipable = // Seq.init(Infinite)? lazily uses Current. The only ISeq component that can do that is Skip // and it can only do it at the start of a sequence @@ -184,181 +184,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition let createFold (factory:TransformFactory<_,_>) (folder:Folder<_,_>) pipeIdx = factory.Compose (Upcast.outOfBand folder) pipeIdx folder - module Fold = - // The consumers of IIterate are the execute and exeuteThin methods. IIterate is passed - // as a generic argument. The types that implement IIterate are value types. This combination - // means that the runtime will "inline" the methods. The alternatives to this were that the - // code in execute/executeThin were duplicated for each of the Fold types, or we turned the - // types back into normal functions and curried them then we would be creating garbage - // each time one of these were called. This has been an optimization to minimize the impact - // on very small collections. - type IIterate<'T> = - abstract Iterate<'U,'Result,'State> : outOfBand:Folder<'U,'Result> -> consumer:Activity<'T,'U> -> unit - - [] - type IterateEnumerable<'T> (enumerable:IEnumerable<'T>) = - interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = - use enumerator = enumerable.GetEnumerator () - let rec iterate () = - if outOfBand.HaltedIdx = 0 && enumerator.MoveNext () then - consumer.ProcessNext enumerator.Current |> ignore - iterate () - iterate () - - [] - type IterateArray<'T> (array:array<'T>) = - interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = - let array = array - let rec iterate idx = - if outOfBand.HaltedIdx = 0 && idx < array.Length then - consumer.ProcessNext array.[idx] |> ignore - iterate (idx+1) - iterate 0 - - [] - type IterateResizeArray<'T> (array:ResizeArray<'T>) = - interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = - let array = array - let rec iterate idx = - if outOfBand.HaltedIdx = 0 && idx < array.Count then - consumer.ProcessNext array.[idx] |> ignore - iterate (idx+1) - iterate 0 - - [] - type IterateList<'T> (alist:list<'T>) = - interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = - let rec iterate lst = - match lst with - | hd :: tl when outOfBand.HaltedIdx = 0 -> - consumer.ProcessNext hd |> ignore - iterate tl - | _ -> () - iterate alist - - [] - type IterateSingleton<'T> (item:'T) = - interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = - if outOfBand.HaltedIdx = 0 then - consumer.ProcessNext item |> ignore - - [] - type IterateUnfold<'S,'T> (generator:'S->option<'T*'S>, state:'S) = - interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = - let generator = generator - let rec iterate current = - if outOfBand.HaltedIdx <> 0 then () - else - match generator current with - | Some (item, next) -> - consumer.ProcessNext item |> ignore - iterate next - | _ -> () - iterate state - - [] - type IterateInit<'T> (f:int->'T, terminatingIdx:int) = - interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result>) (consumer:Activity<'T,'U>) = - let terminatingIdx = terminatingIdx - let f = f - - let firstIdx = - match box consumer with - | :? ISkipable as skipping -> - let rec skip idx = - if idx = terminatingIdx || outOfBand.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 outOfBand.HaltedIdx = 0 then - iterate (idx+1) - else - idx - else - idx - - let finalIdx = iterate firstIdx - if outOfBand.HaltedIdx = 0 && finalIdx = System.Int32.MaxValue then - raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) - - // execute, and it's companion, executeThin, are hosting functions that ensure the correct sequence - // of creation, iteration and disposal for the pipeline - let execute (createFolder:PipeIdx->Folder<'U,'Result>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (executeOn:#IIterate<'T>) = - let result = createFolder (pipeIdx+1) - let consumer = createFold transformFactory result pipeIdx - try - executeOn.Iterate result consumer - consumer.ChainComplete result.HaltedIdx - result.Result - finally - consumer.ChainDispose () - - // executeThin is a specialization of execute, provided as a performance optimization, that can - // be used when a sequence has been wrapped in an ISeq, but hasn't had an items added to its pipeline - // i.e. a container that has ISeq.ofSeq applied. - let executeThin (createFolder:PipeIdx->Folder<'T,'Result>) (executeOn:#IIterate<'T>) = - let result = createFolder 1 - try - executeOn.Iterate result result - result.ChainComplete result.HaltedIdx - result.Result - finally - result.ChainDispose () - - let executeConcat<'T,'U,'Result,'State,'Collection when 'Collection :> ISeq<'T>> (createFolder:PipeIdx->Folder<'U,'Result>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (sources:ISeq<'Collection>) = - let result = createFolder (pipeIdx+1) - let consumer = createFold transformFactory result pipeIdx - try - let common = - { new Folder<'T,NoValue>(Unchecked.defaultof<_>) with - override me.ProcessNext value = consumer.ProcessNext value } - - sources.Fold (fun _ -> - { new Folder<'Collection,NoValue>(Unchecked.defaultof<_>) with - override me.ProcessNext value = - value.Fold (fun _ -> common) |> ignore - me.HaltedIdx <- common.HaltedIdx - Unchecked.defaultof<_> (* return value unused in Fold context *) }) |> ignore - - consumer.ChainComplete result.HaltedIdx - result.Result - finally - result.ChainDispose () - - let executeConcatThin<'T,'Result,'State,'Collection when 'Collection :> ISeq<'T>> (createFolder:PipeIdx->Folder<'T,'Result>) (sources:ISeq<'Collection>) = - let result = createFolder 1 - try - let common = - { new Folder<'T,NoValue>(Unchecked.defaultof<_>) with - override me.ProcessNext value = result.ProcessNext value } - - sources.Fold (fun _ -> - { new Folder<'Collection,NoValue>(Unchecked.defaultof<_>) with - override me.ProcessNext value = - value.Fold (fun _ -> common) |> ignore - me.HaltedIdx <- common.HaltedIdx - Unchecked.defaultof<_> (* return value unused in Fold context *) }) |> ignore - - result.ChainComplete result.HaltedIdx - result.Result - finally - result.ChainDispose () - type SeqProcessNextStates = | InProcess = 0 | NotStarted = 1 @@ -530,35 +355,62 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.PushTransform _ = derivedClassShouldImplement () member __.Fold _ = derivedClassShouldImplement () - and VanillaEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + and VanillaEnumerable<'T,'U>(enumerable:IEnumerable<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new VanillaEnumerator<'T,'U>(enumerable.GetEnumerator(), createFold current result pipeIdx, result)) + Upcast.enumerator (new VanillaEnumerator<'T,'U>(enumerable.GetEnumerator(), createFold transformFactory result pipeIdx, result)) interface ISeq<'U> with member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new VanillaEnumerable<'T,'V>(enumerable, ComposedFactory.Combine current next, pipeIdx+1)) + Upcast.seq (new VanillaEnumerable<'T,'V>(enumerable, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = + let result = createFolder (pipeIdx+1) + let consumer = createFold transformFactory result pipeIdx + try + use enumerator = enumerable.GetEnumerator () + while result.HaltedIdx = 0 && enumerator.MoveNext () do + consumer.ProcessNext enumerator.Current |> ignore - member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = - Fold.execute f current pipeIdx (Fold.IterateEnumerable enumerable) + consumer.ChainComplete result.HaltedIdx + result.Result + finally + consumer.ChainDispose () - and ConcatEnumerable<'T,'U,'Collection when 'Collection :> ISeq<'T>> (sources:ISeq<'Collection>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + and ConcatEnumerable<'T,'U,'Collection when 'Collection :> ISeq<'T>> (sources:ISeq<'Collection>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() interface IEnumerable<'U> with member __.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new ConcatEnumerator<'T,'U,'Collection>(sources, createFold current result pipeIdx, result)) + Upcast.enumerator (new ConcatEnumerator<'T,'U,'Collection>(sources, createFold transformFactory result pipeIdx, result)) interface ISeq<'U> with member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new ConcatEnumerable<'T,'V,'Collection>(sources, ComposedFactory.Combine current next, pipeIdx+1)) + Upcast.seq (new ConcatEnumerable<'T,'V,'Collection>(sources, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = + let result = createFolder (pipeIdx+1) + let consumer = createFold transformFactory result pipeIdx + try + let common = + { new Folder<'T,NoValue>(Unchecked.defaultof<_>) with + override me.ProcessNext value = consumer.ProcessNext value } + + sources.Fold (fun _ -> + { new Folder<'Collection,NoValue>(Unchecked.defaultof<_>) with + override me.ProcessNext value = + value.Fold (fun _ -> common) |> ignore + me.HaltedIdx <- common.HaltedIdx + Unchecked.defaultof<_> (* return value unused in Fold context *) }) |> ignore - member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = - Fold.executeConcat f current pipeIdx sources + consumer.ChainComplete result.HaltedIdx + result.Result + finally + result.ChainDispose () and ThinConcatEnumerable<'T, 'Sources, 'Collection when 'Collection :> ISeq<'T>> (sources:'Sources, preEnumerate:'Sources->ISeq<'Collection>) = inherit EnumerableBase<'T>() @@ -572,8 +424,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (ConcatEnumerable<'T,'V,'Collection>(preEnumerate sources, next, 1)) - member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeConcatThin f (preEnumerate sources) + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = + let fat = Upcast.seq (ConcatEnumerable<'T,'T,'Collection>(preEnumerate sources, IdentityFactory.Instance, 1)) + fat.Fold createFolder and AppendEnumerable<'T> (sources:list>) = inherit ThinConcatEnumerable<'T, list>, ISeq<'T>>(sources, fun sources -> Upcast.seq (ThinListEnumerable>(List.rev sources))) @@ -593,8 +446,21 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new ListEnumerable<'T,'U>(alist, next, 1)) - member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeThin f (Fold.IterateList alist) + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = + let result = createFolder 1 + try + let rec iterate lst = + match lst with + | hd :: tl when result.HaltedIdx = 0 -> + result.ProcessNext hd |> ignore + iterate tl + | _ -> () + iterate alist + + result.ChainComplete result.HaltedIdx + result.Result + finally + result.ChainDispose () and ListEnumerable<'T,'U>(alist:list<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() @@ -608,8 +474,22 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new ListEnumerable<'T,'V>(alist, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = - Fold.execute f transformFactory pipeIdx (Fold.IterateList alist) + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = + let result = createFolder (pipeIdx+1) + let consumer = createFold transformFactory result pipeIdx + try + let rec iterate lst = + match lst with + | hd :: tl when result.HaltedIdx = 0 -> + consumer.ProcessNext hd |> ignore + iterate tl + | _ -> () + iterate alist + + consumer.ChainComplete result.HaltedIdx + result.Result + finally + consumer.ChainDispose () /// ThinEnumerable is used when the IEnumerable provided to ofSeq is neither an array or a list type ThinEnumerable<'T>(enumerable:IEnumerable<'T>) = @@ -635,8 +515,17 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new VanillaEnumerable<'T,'U>(enumerable, next, 1)) - member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeThin f (Fold.IterateEnumerable enumerable) + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = + let result = createFolder 1 + try + use enumerator = enumerable.GetEnumerator () + while result.HaltedIdx = 0 && enumerator.MoveNext () do + result.ProcessNext enumerator.Current |> ignore + + result.ChainComplete result.HaltedIdx + result.Result + finally + result.ChainDispose () type DelayedEnumerable<'T>(delayed:unit->ISeq<'T>, pipeIdx:PipeIdx) = inherit EnumerableBase<'T>() @@ -673,8 +562,13 @@ namespace Microsoft.FSharp.Collections.SeqComposition member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (VanillaEnumerable<'T,'V>(this, next, 1)) - member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeThin f (Fold.IterateEnumerable this) + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = + let result = createFolder 1 + try + result.ChainComplete result.HaltedIdx + result.Result + finally + result.ChainDispose () type ArrayEnumerator<'T,'U>(array:array<'T>, activity:Activity<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, activity) @@ -710,8 +604,20 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new ArrayEnumerable<'T,'V>(array, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - member __.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = - Fold.execute f transformFactory pipeIdx (Fold.IterateArray array) + member __.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = + let result = createFolder (pipeIdx+1) + let consumer = createFold transformFactory result pipeIdx + 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 + result.Result + finally + consumer.ChainDispose () type ThinArrayEnumerable<'T>(array:array<'T>) = inherit EnumerableBase<'T>() @@ -725,8 +631,19 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new ArrayEnumerable<'T,'U>(array, next, 1)) - member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeThin f (Fold.IterateArray array) + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = + let result = createFolder 1 + try + let array = array + let mutable idx = 0 + while result.HaltedIdx = 0 && idx < array.Length do + result.ProcessNext array.[idx] |> ignore + idx <- idx + 1 + + result.ChainComplete result.HaltedIdx + result.Result + finally + result.ChainDispose () type SingletonEnumerable<'T>(item:'T) = inherit EnumerableBase<'T>() @@ -740,8 +657,16 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new ArrayEnumerable<'T,'U>([|item|], next, 1)) - member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeThin f (Fold.IterateSingleton item) + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = + let result = createFolder 1 + try + if result.HaltedIdx = 0 then + result.ProcessNext item |> ignore + + result.ChainComplete result.HaltedIdx + result.Result + finally + result.ChainDispose () type ResizeArrayEnumerator<'T,'U>(array:ResizeArray<'T>, activity:Activity<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, activity) @@ -777,8 +702,20 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new ResizeArrayEnumerable<'T,'V>(resizeArray, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - member __.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = - Fold.execute f transformFactory pipeIdx (Fold.IterateResizeArray resizeArray) + member __.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = + let result = createFolder (pipeIdx+1) + let consumer = createFold transformFactory result pipeIdx + 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 + result.Result + finally + consumer.ChainDispose () type ThinResizeArrayEnumerable<'T>(resizeArray:ResizeArray<'T>) = inherit EnumerableBase<'T>() @@ -792,8 +729,19 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new ResizeArrayEnumerable<'T,'U>(resizeArray, next, 1)) - member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeThin f (Fold.IterateResizeArray resizeArray) + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = + let result = createFolder 1 + try + let array = resizeArray + let mutable idx = 0 + while result.HaltedIdx = 0 && idx < array.Count do + result.ProcessNext array.[idx] |> ignore + idx <- idx + 1 + + result.ChainComplete result.HaltedIdx + result.Result + finally + result.ChainDispose () type UnfoldEnumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, activity:Activity<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, activity) @@ -830,8 +778,25 @@ namespace Microsoft.FSharp.Collections.SeqComposition member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new UnfoldEnumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = - Fold.execute f transformFactory pipeIdx (Fold.IterateUnfold (generator, state)) + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = + let result = createFolder (pipeIdx+1) + let consumer = createFold transformFactory result pipeIdx + 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 + result.Result + finally + consumer.ChainDispose () let getInitTerminatingIdx (count:Nullable) = // we are offset by 1 to allow for values going up to System.Int32.MaxValue @@ -894,9 +859,42 @@ namespace Microsoft.FSharp.Collections.SeqComposition member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new InitEnumerable<'T,'V>(count, f, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - member this.Fold<'Result> (createResult:PipeIdx->Folder<'U,'Result>) = + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = let terminatingIdx = getInitTerminatingIdx count - Fold.execute createResult transformFactory pipeIdx (Fold.IterateInit (f, terminatingIdx)) + let result = createFolder (pipeIdx+1) + let consumer = createFold transformFactory result pipeIdx + 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 + result.Result + finally + consumer.ChainDispose () // The original implementation of "init" delayed the calculation of Current, and so it was possible // to do MoveNext without it's value being calculated. @@ -981,8 +979,17 @@ namespace Microsoft.FSharp.Collections.SeqComposition member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = Upcast.seq (InitEnumerable<'T,'V>(count, f, next, pipeIdx+1)) - member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = - Fold.executeThin f (Fold.IterateEnumerable (Upcast.enumerable this)) + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = + let result = createFolder 1 + try + use enumerator = (Upcast.enumerable this).GetEnumerator () + while result.HaltedIdx = 0 && enumerator.MoveNext () do + result.ProcessNext enumerator.Current |> ignore + + result.ChainComplete result.HaltedIdx + result.Result + finally + result.ChainDispose () namespace Microsoft.FSharp.Core.CompilerServices From 7826ab19c5406b9be0ff40b576ce8bf7959f8511 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Apr 2017 09:15:00 +1000 Subject: [PATCH 48/83] Optimize nested concat --- src/fsharp/FSharp.Core/prim-types.fs | 6 +++++- src/fsharp/FSharp.Core/prim-types.fsi | 10 ++++++++-- src/fsharp/FSharp.Core/seqcore.fs | 18 +++++++++++++++--- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 23834c4ac3..723bf8c273 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3720,10 +3720,14 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract ChainDispose : unit -> unit [] - type Activity<'T,'U> () = + type Activity<'T> () = inherit Activity() abstract ProcessNext : input:'T -> bool + [] + type Activity<'T,'U> () = + inherit Activity<'T>() + [] type Folder<'T,'Result> = inherit Activity<'T,'T> diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index 9a13904f2a..e41f8b964e 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -1878,11 +1878,17 @@ namespace Microsoft.FSharp.Collections.SeqComposition /// Activity is the base class of all elements within the pipeline [] - type Activity<'T,'U> = + type Activity<'T> = inherit Activity - new : unit -> Activity<'T,'U> + new : unit -> Activity<'T> abstract member ProcessNext : input:'T -> bool + /// Activity is the base class of all elements within the pipeline, carrying result type + [] + type Activity<'T,'U> = + inherit Activity<'T> + new : unit -> Activity<'T,'U> + /// Folder 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. diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index fa1f705813..a72f706d5b 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -380,6 +380,10 @@ namespace Microsoft.FSharp.Collections.SeqComposition finally consumer.ChainDispose () + and ConcatCommon<'T>(consumer:Activity<'T>) = + inherit Folder<'T,NoValue>(Unchecked.defaultof<_>) + override me.ProcessNext value = consumer.ProcessNext value + and ConcatEnumerable<'T,'U,'Collection when 'Collection :> ISeq<'T>> (sources:ISeq<'Collection>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() @@ -396,9 +400,17 @@ namespace Microsoft.FSharp.Collections.SeqComposition let result = createFolder (pipeIdx+1) let consumer = createFold transformFactory result pipeIdx try - let common = - { new Folder<'T,NoValue>(Unchecked.defaultof<_>) with - override me.ProcessNext value = consumer.ProcessNext value } + let common : Folder<'T,NoValue> = + let concatCommon = + if not (obj.ReferenceEquals (result, consumer)) then ConcatCommon consumer + else + // (result = consumer) thus our transform is just the identity function, so check to see if + // we're nested, and can just use the deeper nested ConcatCommon object to avoid extra + // call in the chain + match box result with + | :? ConcatCommon<'T> as common -> common + | _ -> ConcatCommon consumer + upcast concatCommon sources.Fold (fun _ -> { new Folder<'Collection,NoValue>(Unchecked.defaultof<_>) with From b8d6d3357f12728663c68b0b2647507aa5973cc8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 12 Apr 2017 18:27:31 +1000 Subject: [PATCH 49/83] Fix nested concat --- src/fsharp/FSharp.Core/seqcore.fs | 84 ++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 25 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index a72f706d5b..2887629391 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -384,6 +384,47 @@ namespace Microsoft.FSharp.Collections.SeqComposition inherit Folder<'T,NoValue>(Unchecked.defaultof<_>) override me.ProcessNext value = consumer.ProcessNext value + and ConcatOutOfBand () = + let outOfBands = ResizeArray () + + interface IOutOfBand with + member this.StopFurtherProcessing pipeIdx = + for i = 0 to outOfBands.Count-1 do + outOfBands.[i].StopFurtherProcessing pipeIdx + + member this.Push outOfBand = + outOfBands.Add outOfBand + + member this.Pop n = + for i = 1 to n do + outOfBands.RemoveAt (outOfBands.Count-1) + + and IConcatGetOutOfBand = + abstract GetOutOfBand : unit -> ConcatOutOfBand + + and ConcatFold<'T,'U,'Collection,'Result when 'Collection :> ISeq<'T>>(outOfBand:ConcatOutOfBand, result:Folder<'U,'Result>, consumer:Activity<'T,'U>, common:Folder<'T,NoValue>) as this = + inherit Folder<'Collection, 'Result>(Unchecked.defaultof<_>) + + do + outOfBand.Push this + outOfBand.Push result + outOfBand.Push common + + override __.ProcessNext value = + value.Fold (fun _ -> common) |> ignore + Unchecked.defaultof<_> (* return value unused in Fold context *) + + override this.ChainComplete _ = + outOfBand.Pop 3 + consumer.ChainComplete result.HaltedIdx + this.Result <- result.Result + + override this.ChainDispose () = + consumer.ChainDispose () + + interface IConcatGetOutOfBand with + member __.GetOutOfBand () = outOfBand + and ConcatEnumerable<'T,'U,'Collection when 'Collection :> ISeq<'T>> (sources:ISeq<'Collection>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() @@ -397,32 +438,25 @@ namespace Microsoft.FSharp.Collections.SeqComposition Upcast.seq (new ConcatEnumerable<'T,'V,'Collection>(sources, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = - let result = createFolder (pipeIdx+1) - let consumer = createFold transformFactory result pipeIdx - try - let common : Folder<'T,NoValue> = - let concatCommon = - if not (obj.ReferenceEquals (result, consumer)) then ConcatCommon consumer - else - // (result = consumer) thus our transform is just the identity function, so check to see if - // we're nested, and can just use the deeper nested ConcatCommon object to avoid extra - // call in the chain - match box result with - | :? ConcatCommon<'T> as common -> common - | _ -> ConcatCommon consumer - upcast concatCommon - - sources.Fold (fun _ -> - { new Folder<'Collection,NoValue>(Unchecked.defaultof<_>) with - override me.ProcessNext value = - value.Fold (fun _ -> common) |> ignore - me.HaltedIdx <- common.HaltedIdx - Unchecked.defaultof<_> (* return value unused in Fold context *) }) |> ignore + sources.Fold (fun lowerPipeIdx -> + let thisPipeIdx = lowerPipeIdx + pipeIdx - consumer.ChainComplete result.HaltedIdx - result.Result - finally - result.ChainDispose () + let result = createFolder (thisPipeIdx+1) + + let outOfBand = + match box result with + | :? IConcatGetOutOfBand as get -> get.GetOutOfBand () + | _ -> ConcatOutOfBand () + + let consumer = + transformFactory.Compose (Upcast.outOfBand outOfBand) thisPipeIdx result + + let common = + match box consumer with + | :? ConcatCommon<'T> as common -> common + | _ -> upcast ConcatCommon consumer + + upcast ConcatFold (outOfBand, result, consumer, common)) and ThinConcatEnumerable<'T, 'Sources, 'Collection when 'Collection :> ISeq<'T>> (sources:'Sources, preEnumerate:'Sources->ISeq<'Collection>) = inherit EnumerableBase<'T>() From acb2a4ffa236fdc0d8afe310e71e73dac0030eb0 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 12 Apr 2017 19:45:11 +1000 Subject: [PATCH 50/83] Updated SurfaceArea files --- .../SurfaceArea.coreclr.fs | 336 +++++++++-------- .../SurfaceArea.net40.fs | 244 +++++++++++++ .../fsharpqa/Source/Misc/LongSourceFile01.fs | 337 ++++++++++-------- 3 files changed, 609 insertions(+), 308 deletions(-) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs index badb570823..630273ad73 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs @@ -293,20 +293,6 @@ 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.ISeqModule+Core+Activity: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Boolean ProcessNext(T) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void .ctor() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() @@ -316,45 +302,32 @@ Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResul Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TResult Result Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TState State Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void .ctor(TResult, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnDispose() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Boolean ProcessNext(T) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Int32 HaltedIdx -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: TResult Result -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: TState State -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void .ctor(TResult, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+IOutOfBand: Void StopFurtherProcessing(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]: ISeq`1 PushTransform[TResult](TransformFactory`2) -Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]: TResult Fold[TResult,TState](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]]) -Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Activity`2 Compose[V](IOutOfBand, Int32, Activity`2) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: System.String ToString() Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: TState State -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void .ctor(Activity, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void .ctor(Microsoft.FSharp.Collections.SeqComposition.Activity, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnDispose() Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Boolean Equals(System.Object) @@ -363,9 +336,9 @@ Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Int3 Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: System.String ToString() Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: TState State -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void .ctor(Activity, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void .ctor(Microsoft.FSharp.Collections.SeqComposition.Activity, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainDispose() Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: System.String ToString() @@ -389,14 +362,8 @@ Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: b _2 Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: c _3 Microsoft.FSharp.Collections.ISeqModule+Core: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Activity -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult] Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState] -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState] -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+IOutOfBand -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T] -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+NoValue -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState] Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState] Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState] Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a] @@ -404,111 +371,111 @@ Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqM Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c] Microsoft.FSharp.Collections.ISeqModule+Core: System.String ToString() Microsoft.FSharp.Collections.ISeqModule+Core: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule: Boolean Contains[T](T, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean Contains[T](T, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) Microsoft.FSharp.Collections.ISeqModule: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule: Boolean Exists2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Boolean IsEmpty[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 AllPairs[T1,T2](ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Append[T](ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Cache[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Cast[T](System.Collections.IEnumerable) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Choose[a,b](Microsoft.FSharp.Core.FSharpFunc`2[a,Microsoft.FSharp.Core.FSharpOption`1[b]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 ChunkBySize[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Collect[T,TCollection,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TCollection], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Concat[TCollection,T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Delay[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 DistinctBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Distinct[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Empty[T]() -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Except[T](System.Collections.Generic.IEnumerable`1[T], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Filter[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 GroupByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 GroupByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Indexed[a](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 InitializeInfinite[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Initialize[T](Int32, Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map3[T,TResult,V,W](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[V,W]]], ISeq`1, ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 MapIndexed2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 MapIndexed[a,b](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[a,b]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfArray[T](T[]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfList[T](Microsoft.FSharp.Collections.FSharpList`1[T]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfResizeArrayUnchecked[T](System.Collections.Generic.List`1[T]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfSeq[T](System.Collections.Generic.IEnumerable`1[T]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Pairwise[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Permute[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Replicate[T](Int32, T) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Reverse[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], ISeq`1, TState) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Scan[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Singleton[T](T) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SkipWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Skip[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortByDescending[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortDescending[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Sort[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SplitInto[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Tail[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Take[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Truncate[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Unfold[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Windowed[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Zip3[T1,T2,T3](ISeq`1, ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Zip[T1,T2](ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean Exists2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Boolean IsEmpty[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) Microsoft.FSharp.Collections.ISeqModule: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule: Int32 Length[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.FSharpList`1[T] ToList[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Int32 Length[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.FSharpList`1[T] ToList[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.ISeqModule+Core -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[TResult] TryPick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFind[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryHead[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryItem[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[System.Int32,a]] Indexed[a](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[a]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[T1,T2]] AllPairs[T1,T2](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T2]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[T1,T2]] Zip[T1,T2](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T2]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[TKey,Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]]] GroupByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[TKey,Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]]] GroupByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[TKey,System.Int32]] CountByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[TKey,System.Int32]] CountByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`3[T1,T2,T3]] Zip3[T1,T2,T3](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T2], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T3]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] Collect[T,TCollection,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TCollection], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TState] ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], TState) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TState] Scan[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T[]] ChunkBySize[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T[]] SplitInto[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T[]] Windowed[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Append[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Cache[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Cast[T](System.Collections.IEnumerable) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Concat[TCollection,T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TCollection]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Delay[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] DistinctBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Distinct[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Empty[T]() +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Except[T](System.Collections.Generic.IEnumerable`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Filter[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] InitializeInfinite[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Initialize[T](Int32, Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] OfArray[T](T[]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] OfList[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] OfResizeArrayUnchecked[T](System.Collections.Generic.List`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] OfSeq[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Permute[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Replicate[T](Int32, T) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Reverse[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Singleton[T](T) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] SkipWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Skip[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] SortByDescending[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] SortDescending[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Sort[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Tail[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Take[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Truncate[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`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.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[V] Map2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`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.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`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.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[V]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[b] Choose[a,b](Microsoft.FSharp.Core.FSharpFunc`2[a,Microsoft.FSharp.Core.FSharpOption`1[b]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[a]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[b] MapIndexed[a,b](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[a,b]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[a]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: 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.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFind[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryHead[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryItem[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) Microsoft.FSharp.Collections.ISeqModule: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[TResult],TState] MapFoldBack[T,TState,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,System.Tuple`2[TResult,TState]]], ISeq`1, TState) -Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`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, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.SeqComposition.ISeq`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.ISeq`1[T], TState) +Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.SeqComposition.ISeq`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.ISeq`1[T]) Microsoft.FSharp.Collections.ISeqModule: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule: T Average[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T ExactlyOne[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T FindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Find[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Head[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Item[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Last[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Max[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Min[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T ReduceBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Sum[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: TResult Pick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: 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, ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: TState FoldBack2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], ISeq`1, ISeq`1, TState) -Microsoft.FSharp.Collections.ISeqModule: TState FoldBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], ISeq`1, TState) -Microsoft.FSharp.Collections.ISeqModule: TState Fold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T[] ToArray[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Void Iterate2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.Unit]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: 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]]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Void IterateIndexed[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Void Iterate[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Average[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T ExactlyOne[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T FindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Find[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Head[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Item[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Last[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Max[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Min[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T ReduceBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Sum[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: TResult Pick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: 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.ISeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T2]) +Microsoft.FSharp.Collections.ISeqModule: 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.ISeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T2], TState) +Microsoft.FSharp.Collections.ISeqModule: TState FoldBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], TState) +Microsoft.FSharp.Collections.ISeqModule: TState Fold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T[] ToArray[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Void Iterate2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: 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.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: Void IterateIndexed[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Void Iterate[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Collections.SeqComposition.ISeq`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]) @@ -641,6 +608,65 @@ 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.Activity: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Activity: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Activity: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Activity: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Activity: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.Activity: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Void .ctor() +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Int32 Length() +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Append(Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Void .ctor() +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+EnumerableBase`1[T] +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]: 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]: 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 StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.SeqComposition.IOutOfBand: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] PushTransform[TResult](Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]) +Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: TResult Fold[TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]]) +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,V] Compose[V](Microsoft.FSharp.Collections.SeqComposition.IOutOfBand, Int32, Microsoft.FSharp.Collections.SeqComposition.Activity`2[TResult,V]) +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Void .ctor() 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]) @@ -1098,6 +1124,8 @@ 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.ISeq`1[T] Append(Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.Collections.Generic.IEnumerator`1[T] GetFreshEnumerator() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.String ToString() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.Type GetType() diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs index 0fdcc27abe..0814244875 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs @@ -280,6 +280,189 @@ 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.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnDispose() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void .ctor(Microsoft.FSharp.Collections.SeqComposition.Activity, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnDispose() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void .ctor(Microsoft.FSharp.Collections.SeqComposition.Activity, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Void .ctor(a) +Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: a _1 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: Void .ctor(a, b) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: a _1 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b]: b _2 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: Void .ctor(a, b, c) +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: a _1 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: b _2 +Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: c _3 +Microsoft.FSharp.Collections.ISeqModule+Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Values`2[a,b] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c] +Microsoft.FSharp.Collections.ISeqModule+Core: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule: Boolean Contains[T](T, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule: Boolean Exists2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Boolean IsEmpty[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule: Int32 Length[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.FSharpList`1[T] ToList[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.ISeqModule+Core +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[System.Int32,a]] Indexed[a](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[a]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[T1,T2]] AllPairs[T1,T2](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T2]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[T1,T2]] Zip[T1,T2](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T2]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[TKey,Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]]] GroupByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[TKey,Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]]] GroupByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[TKey,System.Int32]] CountByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[TKey,System.Int32]] CountByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`3[T1,T2,T3]] Zip3[T1,T2,T3](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T2], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T3]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] Collect[T,TCollection,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TCollection], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TState] ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], TState) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TState] Scan[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T[]] ChunkBySize[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T[]] SplitInto[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T[]] Windowed[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Append[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Cache[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Cast[T](System.Collections.IEnumerable) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Concat[TCollection,T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TCollection]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Delay[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] DistinctBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Distinct[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Empty[T]() +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Except[T](System.Collections.Generic.IEnumerable`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Filter[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] InitializeInfinite[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Initialize[T](Int32, Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] OfArray[T](T[]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] OfList[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] OfResizeArrayUnchecked[T](System.Collections.Generic.List`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] OfSeq[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Permute[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Replicate[T](Int32, T) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Reverse[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Singleton[T](T) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] SkipWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Skip[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] SortByDescending[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] SortDescending[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Sort[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Tail[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Take[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Truncate[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`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.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[V] Map2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`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.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`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.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[V]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[b] Choose[a,b](Microsoft.FSharp.Core.FSharpFunc`2[a,Microsoft.FSharp.Core.FSharpOption`1[b]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[a]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[b] MapIndexed[a,b](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[a,b]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[a]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: 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.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFind[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryHead[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryItem[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.SeqComposition.ISeq`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.ISeq`1[T], TState) +Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.SeqComposition.ISeq`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.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule: T Average[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T ExactlyOne[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T FindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Find[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Head[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Item[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Last[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Max[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Min[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T ReduceBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Sum[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: TResult Pick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: 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.ISeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T2]) +Microsoft.FSharp.Collections.ISeqModule: 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.ISeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T2], TState) +Microsoft.FSharp.Collections.ISeqModule: TState FoldBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], TState) +Microsoft.FSharp.Collections.ISeqModule: TState Fold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T[] ToArray[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Void Iterate2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: 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.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: Void IterateIndexed[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Void Iterate[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Collections.SeqComposition.ISeq`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]) @@ -412,6 +595,65 @@ 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.Activity: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Activity: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Activity: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Activity: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Activity: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.Activity: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Void .ctor() +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Int32 Length() +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Append(Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Void .ctor() +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+EnumerableBase`1[T] +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]: 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]: 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 StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.SeqComposition.IOutOfBand: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] PushTransform[TResult](Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]) +Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: TResult Fold[TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]]) +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,V] Compose[V](Microsoft.FSharp.Collections.SeqComposition.IOutOfBand, Int32, Microsoft.FSharp.Collections.SeqComposition.Activity`2[TResult,V]) +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Void .ctor() 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]) @@ -916,6 +1158,8 @@ 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.ISeq`1[T] Append(Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.Collections.Generic.IEnumerator`1[T] GetFreshEnumerator() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.String ToString() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.Type GetType() diff --git a/tests/fsharpqa/Source/Misc/LongSourceFile01.fs b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs index c144938159..f810267527 100644 --- a/tests/fsharpqa/Source/Misc/LongSourceFile01.fs +++ b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs @@ -247,20 +247,6 @@ 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.ISeqModule+Core+Activity: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Boolean ProcessNext(T) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void .ctor() -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() @@ -270,45 +256,32 @@ Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResul Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TResult Result Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TState State Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void .ctor(TResult, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnDispose() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Boolean ProcessNext(T) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Int32 HaltedIdx -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: TResult Result -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: TState State -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void .ctor(TResult, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) -Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+IOutOfBand: Void StopFurtherProcessing(Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]: ISeq`1 PushTransform[TResult](TransformFactory`2) -Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]: TResult Fold[TResult,TState](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState]]) -Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+NoValue: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Activity`2 Compose[V](IOutOfBand, Int32, Activity`2) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: System.String ToString() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: System.Type GetType() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: TState State +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void .ctor(TResult, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void ChainDispose() +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: System.String ToString() Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: TState State -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void .ctor(Activity, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void .ctor(Microsoft.FSharp.Collections.SeqComposition.Activity, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Void OnDispose() Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Boolean Equals(System.Object) @@ -317,9 +290,9 @@ Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Int3 Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: System.String ToString() Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: TState State -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void .ctor(Activity, TState) -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainComplete(Microsoft.FSharp.Core.Unit ByRef, Int32) -Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainDispose(Microsoft.FSharp.Core.Unit ByRef) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void .ctor(Microsoft.FSharp.Collections.SeqComposition.Activity, TState) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState]: Void ChainDispose() Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a]: System.String ToString() @@ -343,14 +316,8 @@ Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: b _2 Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c]: c _3 Microsoft.FSharp.Collections.ISeqModule+Core: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Activity -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Activity`2[T,TResult] Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState] -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Folder`3[T,TResult,TState] -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+IOutOfBand -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T] -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+NoValue -Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+TransformFactory`2[T,TResult] +Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState] Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState] Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Transform`3[T,TResult,TState] Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Value`1[a] @@ -358,111 +325,111 @@ Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqM Microsoft.FSharp.Collections.ISeqModule+Core: Microsoft.FSharp.Collections.ISeqModule+Core+Values`3[a,b,c] Microsoft.FSharp.Collections.ISeqModule+Core: System.String ToString() Microsoft.FSharp.Collections.ISeqModule+Core: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule: Boolean Contains[T](T, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean Contains[T](T, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) Microsoft.FSharp.Collections.ISeqModule: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.ISeqModule: Boolean Exists2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Boolean IsEmpty[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 AllPairs[T1,T2](ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Append[T](ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Cache[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Cast[T](System.Collections.IEnumerable) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Choose[a,b](Microsoft.FSharp.Core.FSharpFunc`2[a,Microsoft.FSharp.Core.FSharpOption`1[b]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 ChunkBySize[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Collect[T,TCollection,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TCollection], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Concat[TCollection,T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 CountByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Delay[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[T]]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 DistinctBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Distinct[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Empty[T]() -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Except[T](System.Collections.Generic.IEnumerable`1[T], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Filter[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 GroupByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 GroupByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Indexed[a](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 InitializeInfinite[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Initialize[T](Int32, Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map3[T,TResult,V,W](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[V,W]]], ISeq`1, ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 MapIndexed2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 MapIndexed[a,b](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[a,b]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfArray[T](T[]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfList[T](Microsoft.FSharp.Collections.FSharpList`1[T]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfResizeArrayUnchecked[T](System.Collections.Generic.List`1[T]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 OfSeq[T](System.Collections.Generic.IEnumerable`1[T]) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Pairwise[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Permute[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Replicate[T](Int32, T) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Reverse[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], ISeq`1, TState) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Scan[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Singleton[T](T) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SkipWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Skip[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortByDescending[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortDescending[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Sort[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 SplitInto[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Tail[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Take[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Truncate[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Unfold[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Windowed[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Zip3[T1,T2,T3](ISeq`1, ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: ISeq`1 Zip[T1,T2](ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Boolean Exists2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: Boolean ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Boolean IsEmpty[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) Microsoft.FSharp.Collections.ISeqModule: Int32 GetHashCode() -Microsoft.FSharp.Collections.ISeqModule: Int32 Length[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.FSharpList`1[T] ToList[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Int32 Length[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.FSharpList`1[T] ToList[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.ISeqModule+Core -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[TResult] TryPick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFind[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryHead[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryItem[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[System.Int32,a]] Indexed[a](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[a]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[T1,T2]] AllPairs[T1,T2](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T2]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[T1,T2]] Zip[T1,T2](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T2]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[TKey,Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]]] GroupByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[TKey,Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]]] GroupByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[TKey,System.Int32]] CountByRef[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`2[TKey,System.Int32]] CountByVal[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[System.Tuple`3[T1,T2,T3]] Zip3[T1,T2,T3](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T2], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T3]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] Collect[T,TCollection,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TCollection], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TState] ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], TState) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TState] Scan[TState,T](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T[]] ChunkBySize[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T[]] SplitInto[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T[]] Windowed[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Append[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Cache[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Cast[T](System.Collections.IEnumerable) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Concat[TCollection,T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TCollection]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Delay[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] DistinctBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Distinct[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Empty[T]() +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Except[T](System.Collections.Generic.IEnumerable`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Filter[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] InitializeInfinite[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Initialize[T](Int32, Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] OfArray[T](T[]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] OfList[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] OfResizeArrayUnchecked[T](System.Collections.Generic.List`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] OfSeq[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Permute[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Replicate[T](Int32, T) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Reverse[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Singleton[T](T) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] SkipWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Skip[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] SortByDescending[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] SortDescending[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Sort[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Tail[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Take[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Truncate[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`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.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[V] Map2[T,TResult,V](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,V]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`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.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`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.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[V]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[b] Choose[a,b](Microsoft.FSharp.Core.FSharpFunc`2[a,Microsoft.FSharp.Core.FSharpOption`1[b]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[a]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[b] MapIndexed[a,b](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[a,b]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[a]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: 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.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryFind[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryHead[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryItem[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) Microsoft.FSharp.Collections.ISeqModule: System.String ToString() -Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`1[TResult],TState] MapFoldBack[T,TState,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,System.Tuple`2[TResult,TState]]], ISeq`1, TState) -Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.ISeqModule+Core+ISeq`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, ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.SeqComposition.ISeq`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.ISeq`1[T], TState) +Microsoft.FSharp.Collections.ISeqModule: System.Tuple`2[Microsoft.FSharp.Collections.SeqComposition.ISeq`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.ISeq`1[T]) Microsoft.FSharp.Collections.ISeqModule: System.Type GetType() -Microsoft.FSharp.Collections.ISeqModule: T Average[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T ExactlyOne[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T FindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Find[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Head[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Item[T](Int32, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Last[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Max[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Min[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T ReduceBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T Sum[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: TResult Pick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: 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, ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: TState FoldBack2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], ISeq`1, ISeq`1, TState) -Microsoft.FSharp.Collections.ISeqModule: TState FoldBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], ISeq`1, TState) -Microsoft.FSharp.Collections.ISeqModule: TState Fold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: T[] ToArray[T](ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Void Iterate2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.Unit]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: 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]]], ISeq`1, ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Void IterateIndexed[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit]], ISeq`1) -Microsoft.FSharp.Collections.ISeqModule: Void Iterate[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit], ISeq`1) +Microsoft.FSharp.Collections.ISeqModule: T Average[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T ExactlyOne[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T FindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Find[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Head[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Item[T](Int32, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Last[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Max[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Min[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T ReduceBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T Sum[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: TResult Pick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: 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.ISeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T2]) +Microsoft.FSharp.Collections.ISeqModule: 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.ISeq`1[T1], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T2], TState) +Microsoft.FSharp.Collections.ISeqModule: TState FoldBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], TState) +Microsoft.FSharp.Collections.ISeqModule: TState Fold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: T[] ToArray[T](Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Void Iterate2[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: 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.ISeq`1[T], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult]) +Microsoft.FSharp.Collections.ISeqModule: Void IterateIndexed[T](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.ISeqModule: Void Iterate[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Collections.SeqComposition.ISeq`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]) @@ -559,6 +526,66 @@ 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.Activity: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Activity: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Activity: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Activity: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Activity: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.Activity: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Void .ctor() +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.Activity`1[T]: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void ChainComplete(Int32) +Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void ChainDispose() +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Int32 Length() +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Append(Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Void .ctor() +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+EnumerableBase`1[T] +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]: 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]: 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 StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.SeqComposition.IOutOfBand: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] PushTransform[TResult](Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]) +Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: TResult Fold[TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]]) +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,V] Compose[V](Microsoft.FSharp.Collections.SeqComposition.IOutOfBand, Int32, Microsoft.FSharp.Collections.SeqComposition.Activity`2[TResult,V]) +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Void .ctor() +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]) @@ -1004,6 +1031,8 @@ 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.ISeq`1[T] Append(Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.Collections.Generic.IEnumerator`1[T] GetFreshEnumerator() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.String ToString() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: System.Type GetType() From f4f0b28c7d49af9d20eaa75d6de37743d69498d6 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 17 Apr 2017 16:04:53 +1000 Subject: [PATCH 51/83] Save tmp copy of Result --- src/fsharp/FSharp.Core/seqcore.fs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index 2887629391..3ae7c1598c 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -376,9 +376,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition consumer.ProcessNext enumerator.Current |> ignore consumer.ChainComplete result.HaltedIdx - result.Result finally consumer.ChainDispose () + result.Result and ConcatCommon<'T>(consumer:Activity<'T>) = inherit Folder<'T,NoValue>(Unchecked.defaultof<_>) @@ -533,9 +533,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition iterate alist consumer.ChainComplete result.HaltedIdx - result.Result finally consumer.ChainDispose () + result.Result /// ThinEnumerable is used when the IEnumerable provided to ofSeq is neither an array or a list type ThinEnumerable<'T>(enumerable:IEnumerable<'T>) = @@ -661,9 +661,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition idx <- idx + 1 consumer.ChainComplete result.HaltedIdx - result.Result finally consumer.ChainDispose () + result.Result type ThinArrayEnumerable<'T>(array:array<'T>) = inherit EnumerableBase<'T>() @@ -759,9 +759,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition idx <- idx + 1 consumer.ChainComplete result.HaltedIdx - result.Result finally consumer.ChainDispose () + result.Result type ThinResizeArrayEnumerable<'T>(resizeArray:ResizeArray<'T>) = inherit EnumerableBase<'T>() @@ -840,9 +840,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition iterate state consumer.ChainComplete result.HaltedIdx - result.Result finally consumer.ChainDispose () + result.Result let getInitTerminatingIdx (count:Nullable) = // we are offset by 1 to allow for values going up to System.Int32.MaxValue @@ -938,9 +938,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) consumer.ChainComplete result.HaltedIdx - result.Result 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. @@ -1371,7 +1371,7 @@ namespace Microsoft.FSharp.Core.CompilerServices consumer.ProcessNext e.Current |> ignore consumer.ChainComplete result.HaltedIdx - result.Result finally consumer.ChainDispose () + result.Result From e5ced286a152fb21c81eae187f8ecb6e24cde45c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Apr 2017 19:23:49 +1000 Subject: [PATCH 52/83] Removed Folder.StopFurtherProcessing --- src/fsharp/FSharp.Core/iseq.fs | 35 ++++++++++++++------------- src/fsharp/FSharp.Core/prim-types.fs | 6 ++--- src/fsharp/FSharp.Core/prim-types.fsi | 1 - 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 9433342094..56b7636b74 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -107,6 +107,7 @@ namespace Microsoft.FSharp.Collections // is fixed with the compiler then these functions can be removed. let inline seq<'T,'seq when 'seq :> ISeq<'T> and 'seq : not struct> (t:'seq) : ISeq<'T> = (# "" t : ISeq<'T> #) let inline enumerableNonGeneric<'enumerable when 'enumerable :> IEnumerable and 'enumerable : not struct> (t:'enumerable) : IEnumerable = (# "" t : IEnumerable #) + let inline outOfBand<'outOfBand when 'outOfBand :> IOutOfBand and 'outOfBand : not struct> (t:'outOfBand) : IOutOfBand = (# "" t : IOutOfBand #) let inline valueComparer<'T when 'T : equality> ()= let c = HashIdentity.Structural<'T> @@ -184,7 +185,7 @@ namespace Microsoft.FSharp.Collections this.Result <- value else this.State._2 <- true - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = @@ -210,7 +211,7 @@ namespace Microsoft.FSharp.Collections if this.State.MoveNext() then this.Result <- folder this.Result value this.State.Current else - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = () @@ -246,7 +247,7 @@ namespace Microsoft.FSharp.Collections if this.State.MoveNext() then f value this.State.Current else - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = () @@ -262,7 +263,7 @@ namespace Microsoft.FSharp.Collections this.State._1 <- this.State._1 + 1 Unchecked.defaultof<_> else - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> override this.OnComplete _ = () override this.OnDispose () = this.State._2.Dispose () }) @@ -273,7 +274,7 @@ namespace Microsoft.FSharp.Collections { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = this.Result <- Some value - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] @@ -306,7 +307,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if f value then this.Result <- true - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] @@ -317,9 +318,9 @@ namespace Microsoft.FSharp.Collections if this.State.MoveNext() then if predicate value this.State.Current then this.Result <- true - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx else - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = () @@ -332,7 +333,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if element = value then this.Result <- true - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] @@ -342,7 +343,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if not (predicate value) then this.Result <- false - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] @@ -353,9 +354,9 @@ namespace Microsoft.FSharp.Collections if this.State.MoveNext() then if not (predicate value this.State.Current) then this.Result <- false - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx else - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = () @@ -443,12 +444,12 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if not (this.State.MoveNext()) then this.Result <- 1 - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx else let c = f value this.State.Current if c <> 0 then this.Result <- c - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = if this.Result = 0 && this.State.MoveNext() then @@ -784,7 +785,7 @@ namespace Microsoft.FSharp.Collections match f value with | (Some _) as some -> this.Result <- some - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx | None -> () Unchecked.defaultof<_> (* return value unused in Fold context *) }) @@ -795,7 +796,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if f value then this.Result <- Some value - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] @@ -806,7 +807,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if predicate value then this.Result <- Some this.State - this.StopFurtherProcessing pipeIdx + (Upcast.outOfBand this).StopFurtherProcessing pipeIdx else this.State <- this.State + 1 Unchecked.defaultof<_> (* return value unused in Fold context *) }) diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 723bf8c273..235c07d718 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3733,11 +3733,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition inherit Activity<'T,'T> val mutable Result : 'Result - val mutable HaltedIdx : int - member this.StopFurtherProcessing pipeIdx = this.HaltedIdx <- pipeIdx + interface IOutOfBand with - member this.StopFurtherProcessing pipeIdx = this.StopFurtherProcessing pipeIdx + member this.StopFurtherProcessing pipeIdx = + this.HaltedIdx <- pipeIdx new (initalResult) = { inherit Activity<'T,'T>() diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index e41f8b964e..4f8a773874 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -1899,7 +1899,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface IOutOfBand val mutable Result : 'Result val mutable HaltedIdx : int - member StopFurtherProcessing : PipeIdx -> unit override ChainComplete : PipeIdx -> unit override ChainDispose : unit -> unit From c3b50a4e31fe6030c212f281bf6b7e5d91fbb4fd Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Apr 2017 19:26:32 +1000 Subject: [PATCH 53/83] Changed Folder style; HaltedIdx read only --- src/fsharp/FSharp.Core/prim-types.fs | 19 ++++++++----------- src/fsharp/FSharp.Core/prim-types.fsi | 4 ++-- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 235c07d718..5ff399456f 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3729,21 +3729,18 @@ namespace Microsoft.FSharp.Collections.SeqComposition inherit Activity<'T>() [] - type Folder<'T,'Result> = - inherit Activity<'T,'T> + type Folder<'T,'Result>(initalResult:'Result) = + inherit Activity<'T,'T>() - val mutable Result : 'Result - val mutable HaltedIdx : int + let mutable result = initalResult + let mutable haltedIdx = 0 + + member __.Result with get () = result and set value = result <- value + member __.HaltedIdx with get () = haltedIdx interface IOutOfBand with member this.StopFurtherProcessing pipeIdx = - this.HaltedIdx <- pipeIdx - - new (initalResult) = { - inherit Activity<'T,'T>() - HaltedIdx = 0 - Result = initalResult - } + haltedIdx <- pipeIdx override this.ChainComplete _ = () override this.ChainDispose () = () diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index 4f8a773874..a872b64502 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -1897,8 +1897,8 @@ namespace Microsoft.FSharp.Collections.SeqComposition inherit Activity<'T,'T> new : 'Result -> Folder<'T,'Result> interface IOutOfBand - val mutable Result : 'Result - val mutable HaltedIdx : int + member Result : 'Result with get, set + member HaltedIdx : PipeIdx with get override ChainComplete : PipeIdx -> unit override ChainDispose : unit -> unit From 5f0acf98c57ab717616052a87b1b199edd51a59d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Apr 2017 19:35:14 +1000 Subject: [PATCH 54/83] Add listening for StopFurtherProcessing --- src/fsharp/FSharp.Core/prim-types.fs | 11 ++++++++++- src/fsharp/FSharp.Core/prim-types.fsi | 2 ++ src/fsharp/FSharp.Core/seqcore.fs | 17 +++++++++++++++-- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 5ff399456f..5c409d405d 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3713,6 +3713,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit + abstract ListenForStopFurtherProcessing : Action -> unit [] type Activity() = @@ -3732,6 +3733,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition type Folder<'T,'Result>(initalResult:'Result) = inherit Activity<'T,'T>() + let mutable listeners = BasicInlinedOperations.unsafeDefault> let mutable result = initalResult let mutable haltedIdx = 0 @@ -3740,7 +3742,14 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface IOutOfBand with member this.StopFurtherProcessing pipeIdx = - haltedIdx <- pipeIdx + if haltedIdx = 0 then + haltedIdx <- pipeIdx + match listeners with + | null -> () + | a -> a.Invoke pipeIdx + + member this.ListenForStopFurtherProcessing action = + listeners <- Delegate.Combine (listeners, action) :?> Action override this.ChainComplete _ = () override this.ChainDispose () = () diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index a872b64502..795fa62a9b 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -1861,6 +1861,8 @@ namespace Microsoft.FSharp.Collections.SeqComposition type IOutOfBand = /// 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 /// Activity is the root class for chains of activities. It is in a non-generic /// form so that it can be used by subsequent activities diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index 3ae7c1598c..76260fddc3 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -387,10 +387,21 @@ namespace Microsoft.FSharp.Collections.SeqComposition and ConcatOutOfBand () = let outOfBands = ResizeArray () + let mutable haltedIdx = 0 + let mutable listeners = Unchecked.defaultof> + interface IOutOfBand with member this.StopFurtherProcessing pipeIdx = - for i = 0 to outOfBands.Count-1 do - outOfBands.[i].StopFurtherProcessing pipeIdx + if haltedIdx = 0 then + haltedIdx <- pipeIdx + for i = 0 to outOfBands.Count-1 do + outOfBands.[i].StopFurtherProcessing pipeIdx + match listeners with + | null -> () + | a -> a.Invoke pipeIdx + + member this.ListenForStopFurtherProcessing action = + listeners <- Delegate.Combine (listeners, action) :?> Action member this.Push outOfBand = outOfBands.Add outOfBand @@ -408,7 +419,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition do outOfBand.Push this outOfBand.Push result + (Upcast.outOfBand result).ListenForStopFurtherProcessing (fun idx -> (Upcast.outOfBand outOfBand).StopFurtherProcessing idx) outOfBand.Push common + (Upcast.outOfBand common).ListenForStopFurtherProcessing (fun idx -> (Upcast.outOfBand outOfBand).StopFurtherProcessing idx) override __.ProcessNext value = value.Fold (fun _ -> common) |> ignore From 10c917927c13fee5944792238e96074a39e361f2 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 19 Apr 2017 19:47:04 +1000 Subject: [PATCH 55/83] Fixed concat (for good! ... hopefully) --- src/fsharp/FSharp.Core/prim-types.fs | 13 +++-- src/fsharp/FSharp.Core/seqcore.fs | 72 ++++++++++------------------ 2 files changed, 32 insertions(+), 53 deletions(-) diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 5c409d405d..43a1060583 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3708,6 +3708,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition open System.Collections.Generic open Microsoft.FSharp.Core open Microsoft.FSharp.Collections + open BasicInlinedOperations type PipeIdx = int @@ -3742,11 +3743,13 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface IOutOfBand with member this.StopFurtherProcessing pipeIdx = - if haltedIdx = 0 then - haltedIdx <- pipeIdx - match listeners with - | null -> () - | a -> a.Invoke pipeIdx + let currentIdx = haltedIdx + haltedIdx <- pipeIdx + if currentIdx = 0 then + if haltedIdx <> 0 then + match listeners with + | null -> () + | a -> a.Invoke pipeIdx member this.ListenForStopFurtherProcessing action = listeners <- Delegate.Combine (listeners, action) :?> Action diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index 76260fddc3..cbbfb0f04c 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -151,6 +151,12 @@ namespace Microsoft.FSharp.Collections.SeqComposition [] 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 Upcast = // The f# compiler outputs unnecessary unbox.any calls in upcasts. If this functionality // is fixed with the compiler then these functions can be removed. @@ -382,62 +388,36 @@ namespace Microsoft.FSharp.Collections.SeqComposition and ConcatCommon<'T>(consumer:Activity<'T>) = inherit Folder<'T,NoValue>(Unchecked.defaultof<_>) - override me.ProcessNext value = consumer.ProcessNext value - - and ConcatOutOfBand () = - let outOfBands = ResizeArray () - - let mutable haltedIdx = 0 - let mutable listeners = Unchecked.defaultof> - - interface IOutOfBand with - member this.StopFurtherProcessing pipeIdx = - if haltedIdx = 0 then - haltedIdx <- pipeIdx - for i = 0 to outOfBands.Count-1 do - outOfBands.[i].StopFurtherProcessing pipeIdx - match listeners with - | null -> () - | a -> a.Invoke pipeIdx - member this.ListenForStopFurtherProcessing action = - listeners <- Delegate.Combine (listeners, action) :?> Action + member __.Consumer = consumer - member this.Push outOfBand = - outOfBands.Add outOfBand + override me.ProcessNext value = TailCall.avoid (consumer.ProcessNext value) - member this.Pop n = - for i = 1 to n do - outOfBands.RemoveAt (outOfBands.Count-1) - - and IConcatGetOutOfBand = - abstract GetOutOfBand : unit -> ConcatOutOfBand - - and ConcatFold<'T,'U,'Collection,'Result when 'Collection :> ISeq<'T>>(outOfBand:ConcatOutOfBand, result:Folder<'U,'Result>, consumer:Activity<'T,'U>, common:Folder<'T,NoValue>) as this = + and ConcatFold<'T,'U,'Collection,'Result when 'Collection :> ISeq<'T>>(result:Folder<'U,'Result>, consumer:Activity<'T,'U>, common:Folder<'T,NoValue>) as this = inherit Folder<'Collection, 'Result>(Unchecked.defaultof<_>) do - outOfBand.Push this - outOfBand.Push result - (Upcast.outOfBand result).ListenForStopFurtherProcessing (fun idx -> (Upcast.outOfBand outOfBand).StopFurtherProcessing idx) - outOfBand.Push common - (Upcast.outOfBand common).ListenForStopFurtherProcessing (fun idx -> (Upcast.outOfBand outOfBand).StopFurtherProcessing idx) + (Upcast.outOfBand this).ListenForStopFurtherProcessing (fun idx -> + (Upcast.outOfBand result).StopFurtherProcessing idx + (Upcast.outOfBand common).StopFurtherProcessing PipeIdx.MinValue) + + (Upcast.outOfBand result).ListenForStopFurtherProcessing (fun idx -> + (Upcast.outOfBand this).StopFurtherProcessing idx + (Upcast.outOfBand common).StopFurtherProcessing PipeIdx.MaxValue) override __.ProcessNext value = - value.Fold (fun _ -> common) |> ignore + value.Fold (fun _ -> + (Upcast.outOfBand common).StopFurtherProcessing 0 + common) |> ignore Unchecked.defaultof<_> (* return value unused in Fold context *) override this.ChainComplete _ = - outOfBand.Pop 3 consumer.ChainComplete result.HaltedIdx this.Result <- result.Result override this.ChainDispose () = consumer.ChainDispose () - interface IConcatGetOutOfBand with - member __.GetOutOfBand () = outOfBand - and ConcatEnumerable<'T,'U,'Collection when 'Collection :> ISeq<'T>> (sources:ISeq<'Collection>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() @@ -456,20 +436,16 @@ namespace Microsoft.FSharp.Collections.SeqComposition let result = createFolder (thisPipeIdx+1) - let outOfBand = - match box result with - | :? IConcatGetOutOfBand as get -> get.GetOutOfBand () - | _ -> ConcatOutOfBand () + let outOfBand = Upcast.outOfBand result - let consumer = - transformFactory.Compose (Upcast.outOfBand outOfBand) thisPipeIdx result + let consumer = transformFactory.Compose outOfBand thisPipeIdx result let common = match box consumer with - | :? ConcatCommon<'T> as common -> common - | _ -> upcast ConcatCommon consumer + | :? ConcatCommon<'T> as c -> ConcatCommon c.Consumer + | _ -> ConcatCommon consumer - upcast ConcatFold (outOfBand, result, consumer, common)) + upcast ConcatFold (result, consumer, common)) and ThinConcatEnumerable<'T, 'Sources, 'Collection when 'Collection :> ISeq<'T>> (sources:'Sources, preEnumerate:'Sources->ISeq<'Collection>) = inherit EnumerableBase<'T>() From 6ddfc095eb7060705b3fd545a927b5da8f932866 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Apr 2017 17:55:02 +1000 Subject: [PATCH 56/83] Used LanguagePrimitives.IntrinsicOperators.(&&) --- src/fsharp/FSharp.Core/prim-types.fs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 43a1060583..b540ea4ffe 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3709,6 +3709,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition open Microsoft.FSharp.Core open Microsoft.FSharp.Collections open BasicInlinedOperations + open LanguagePrimitives.IntrinsicOperators type PipeIdx = int @@ -3745,11 +3746,10 @@ namespace Microsoft.FSharp.Collections.SeqComposition member this.StopFurtherProcessing pipeIdx = let currentIdx = haltedIdx haltedIdx <- pipeIdx - if currentIdx = 0 then - if haltedIdx <> 0 then - match listeners with - | null -> () - | a -> a.Invoke 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 From 2a617a994041e4855db5869980061d33a34c787f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Apr 2017 17:56:57 +1000 Subject: [PATCH 57/83] Remove temp copies of Folder.Result --- src/fsharp/FSharp.Core/seqcore.fs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index cbbfb0f04c..b3fcdea579 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -493,9 +493,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition iterate alist result.ChainComplete result.HaltedIdx - result.Result finally result.ChainDispose () + result.Result and ListEnumerable<'T,'U>(alist:list<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() @@ -558,9 +558,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition result.ProcessNext enumerator.Current |> ignore result.ChainComplete result.HaltedIdx - result.Result finally result.ChainDispose () + result.Result type DelayedEnumerable<'T>(delayed:unit->ISeq<'T>, pipeIdx:PipeIdx) = inherit EnumerableBase<'T>() @@ -601,9 +601,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition let result = createFolder 1 try result.ChainComplete result.HaltedIdx - result.Result finally result.ChainDispose () + result.Result type ArrayEnumerator<'T,'U>(array:array<'T>, activity:Activity<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, activity) @@ -676,9 +676,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition idx <- idx + 1 result.ChainComplete result.HaltedIdx - result.Result finally result.ChainDispose () + result.Result type SingletonEnumerable<'T>(item:'T) = inherit EnumerableBase<'T>() @@ -699,9 +699,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition result.ProcessNext item |> ignore result.ChainComplete result.HaltedIdx - result.Result finally result.ChainDispose () + result.Result type ResizeArrayEnumerator<'T,'U>(array:ResizeArray<'T>, activity:Activity<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, activity) @@ -774,9 +774,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition idx <- idx + 1 result.ChainComplete result.HaltedIdx - result.Result finally result.ChainDispose () + result.Result type UnfoldEnumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, activity:Activity<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, activity) @@ -1022,9 +1022,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition result.ProcessNext enumerator.Current |> ignore result.ChainComplete result.HaltedIdx - result.Result finally result.ChainDispose () + result.Result namespace Microsoft.FSharp.Core.CompilerServices @@ -1318,9 +1318,9 @@ namespace Microsoft.FSharp.Core.CompilerServices result.ProcessNext e.Current |> ignore result.ChainComplete result.HaltedIdx - result.Result finally result.ChainDispose () + result.Result override this.Length () = use maybeGeneratedSequenceBase = this.GetFreshEnumerator () From b0dfd6a3fdc9b8bf0cc25016e3cdd6ec559c55ac Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Apr 2017 18:00:20 +1000 Subject: [PATCH 58/83] Minimize stack usage for List Folds --- src/fsharp/FSharp.Core/seqcore.fs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index b3fcdea579..4d38727c39 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -484,13 +484,15 @@ namespace Microsoft.FSharp.Collections.SeqComposition member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = let result = createFolder 1 try - let rec iterate lst = - match lst with + let mutable lst = alist + while + ( match lst with | hd :: tl when result.HaltedIdx = 0 -> result.ProcessNext hd |> ignore - iterate tl - | _ -> () - iterate alist + lst <- tl + true + | _ -> false + ) do () result.ChainComplete result.HaltedIdx finally @@ -513,13 +515,15 @@ namespace Microsoft.FSharp.Collections.SeqComposition let result = createFolder (pipeIdx+1) let consumer = createFold transformFactory result pipeIdx try - let rec iterate lst = - match lst with + let mutable lst = alist + while + ( match lst with | hd :: tl when result.HaltedIdx = 0 -> consumer.ProcessNext hd |> ignore - iterate tl - | _ -> () - iterate alist + lst <- tl + true + | _ -> false + ) do () consumer.ChainComplete result.HaltedIdx finally From d899408efe1c23c0df345df16e6b5ad5ac184ace Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Apr 2017 18:24:32 +1000 Subject: [PATCH 59/83] Updated surface area files --- .../FSharp.Core.Unittests/SurfaceArea.coreclr.fs | 13 ++++++++++--- .../FSharp.Core.Unittests/SurfaceArea.net40.fs | 13 ++++++++++--- tests/fsharpqa/Source/Misc/LongSourceFile01.fs | 13 ++++++++++--- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs index 630273ad73..4c1ce59d5f 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs @@ -297,28 +297,32 @@ Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResul Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 get_HaltedIdx() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.String ToString() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TResult get_Result() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TState State Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void .ctor(TResult, TState) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnDispose() -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void set_Result(TResult) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Boolean ProcessNext(T) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Int32 get_HaltedIdx() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: System.String ToString() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: TResult get_Result() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: TState State Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void .ctor(TResult, TState) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void ChainComplete(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void ChainDispose() -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void set_Result(TResult) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() @@ -651,13 +655,16 @@ Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Boolean Equals( 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 StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Void set_Result(TResult) +Microsoft.FSharp.Collections.SeqComposition.IOutOfBand: Void ListenForStopFurtherProcessing(System.Action`1[System.Int32]) Microsoft.FSharp.Collections.SeqComposition.IOutOfBand: Void StopFurtherProcessing(Int32) Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] PushTransform[TResult](Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]) Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: TResult Fold[TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]]) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs index 0814244875..2f52c700e9 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs @@ -284,28 +284,32 @@ Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResul Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 get_HaltedIdx() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.String ToString() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TResult get_Result() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TState State Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void .ctor(TResult, TState) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnDispose() -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void set_Result(TResult) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Boolean ProcessNext(T) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Int32 get_HaltedIdx() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: System.String ToString() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: TResult get_Result() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: TState State Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void .ctor(TResult, TState) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void ChainComplete(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void ChainDispose() -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void set_Result(TResult) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() @@ -638,13 +642,16 @@ Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Boolean Equals( 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 StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Void set_Result(TResult) +Microsoft.FSharp.Collections.SeqComposition.IOutOfBand: Void ListenForStopFurtherProcessing(System.Action`1[System.Int32]) Microsoft.FSharp.Collections.SeqComposition.IOutOfBand: Void StopFurtherProcessing(Int32) Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] PushTransform[TResult](Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]) Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: TResult Fold[TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]]) diff --git a/tests/fsharpqa/Source/Misc/LongSourceFile01.fs b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs index f810267527..5484feda32 100644 --- a/tests/fsharpqa/Source/Misc/LongSourceFile01.fs +++ b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs @@ -251,28 +251,32 @@ Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResul Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Int32 get_HaltedIdx() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.String ToString() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TResult get_Result() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: TState State Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void .ctor(TResult, TState) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainComplete(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void ChainDispose() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnComplete(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void OnDispose() -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithPostProcessing`3[T,TResult,TState]: Void set_Result(TResult) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Boolean ProcessNext(T) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Int32 GetHashCode() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Int32 HaltedIdx +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Int32 get_HaltedIdx() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: System.String ToString() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: System.Type GetType() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: TResult Result +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: TResult get_Result() Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: TState State Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void .ctor(TResult, TState) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void ChainComplete(Int32) Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void ChainDispose() -Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ISeqModule+Core+FolderWithState`3[T,TResult,TState]: Void set_Result(TResult) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Boolean ProcessNext(T) Microsoft.FSharp.Collections.ISeqModule+Core+TransformWithPostProcessing`3[T,TResult,TState]: Int32 GetHashCode() @@ -569,13 +573,16 @@ Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Boolean Equals( 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 StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Void set_Result(TResult) +Microsoft.FSharp.Collections.SeqComposition.IOutOfBand: Void ListenForStopFurtherProcessing(System.Action`1[System.Int32]) Microsoft.FSharp.Collections.SeqComposition.IOutOfBand: Void StopFurtherProcessing(Int32) Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] PushTransform[TResult](Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]) Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: TResult Fold[TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]]) From ede593c9c1b4b68583361cf23f4d61e61f414146 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Apr 2017 18:30:39 +1000 Subject: [PATCH 60/83] Force capture of common folding closure --- src/fsharp/FSharp.Core/seqcore.fs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index 4d38727c39..d6021b0661 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -157,6 +157,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition // 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 funciton 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 #) + module internal Upcast = // The f# compiler outputs unnecessary unbox.any calls in upcasts. If this functionality // is fixed with the compiler then these functions can be removed. @@ -405,10 +410,12 @@ namespace Microsoft.FSharp.Collections.SeqComposition (Upcast.outOfBand this).StopFurtherProcessing idx (Upcast.outOfBand common).StopFurtherProcessing PipeIdx.MaxValue) + let getCommonFolder = Closure.forceCapture (fun (_:PipeIdx) -> + (Upcast.outOfBand common).StopFurtherProcessing 0 + common) + override __.ProcessNext value = - value.Fold (fun _ -> - (Upcast.outOfBand common).StopFurtherProcessing 0 - common) |> ignore + value.Fold getCommonFolder |> ignore Unchecked.defaultof<_> (* return value unused in Fold context *) override this.ChainComplete _ = From 53ae1648e8bfcf42dbc9608f45f4cd58dcd46cc4 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Apr 2017 16:27:35 +1000 Subject: [PATCH 61/83] throw away input on take 0 --- src/fsharp/FSharp.Core/iseq.fs | 42 ++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 56b7636b74..13e95988fb 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -677,29 +677,31 @@ namespace Microsoft.FSharp.Collections [] let take (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = - source.PushTransform { new TransformFactory<'T,'T>() with - member __.Compose outOfBand pipelineIdx next = - if takeCount = 0 then - outOfBand.StopFurtherProcessing pipelineIdx + if takeCount = 0 then empty + else + source.PushTransform { new TransformFactory<'T,'T>() with + member __.Compose outOfBand pipelineIdx next = + if takeCount = 0 then + outOfBand.StopFurtherProcessing pipelineIdx - upcast { new TransformWithPostProcessing<'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 + upcast { new TransformWithPostProcessing<'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 - TailCall.avoid (next.ProcessNext input) - else - outOfBand.StopFurtherProcessing pipelineIdx - false + 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 () = () }} + 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 takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = From 7be643093cb973dbc25189df93f9888814abd883 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Apr 2017 18:09:17 +1000 Subject: [PATCH 62/83] Added null check for except's itemsToExclude --- src/fsharp/FSharp.Core/iseq.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 13e95988fb..bde7b7fc3d 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -294,6 +294,7 @@ namespace Microsoft.FSharp.Collections [] let inline except (itemsToExclude: seq<'T>) (source:ISeq<'T>) : ISeq<'T> when 'T:equality = + checkNonNull "itemsToExclude" itemsToExclude source.PushTransform { new TransformFactory<'T,'T>() with override __.Compose _ _ next = upcast { new Transform<'T,'V,Lazy>>(next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with From 9941af4c363528c79fc1049ac49447ef8861aedd Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Apr 2017 19:22:10 +1000 Subject: [PATCH 63/83] Added check on negative input for take --- src/fsharp/FSharp.Core/iseq.fs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index bde7b7fc3d..aa3d6714d6 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -678,7 +678,8 @@ namespace Microsoft.FSharp.Collections [] let take (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = - if takeCount = 0 then empty + if takeCount < 0 then invalidArgInputMustBeNonNegative "count" takeCount + elif takeCount = 0 then empty else source.PushTransform { new TransformFactory<'T,'T>() with member __.Compose outOfBand pipelineIdx next = From aeeb0498b464c7b884f8e0af1352a68448486a03 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 25 Apr 2017 06:39:22 +1000 Subject: [PATCH 64/83] Natively support ISeq on list --- src/fsharp/FSharp.Core/iseq.fs | 3 +- src/fsharp/FSharp.Core/prim-types.fs | 253 +++++++++++++++++++------- src/fsharp/FSharp.Core/prim-types.fsi | 142 +++++++-------- src/fsharp/FSharp.Core/seqcore.fs | 86 +-------- src/fsharp/FSharp.Core/seqcore.fsi | 5 - 5 files changed, 261 insertions(+), 228 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index aa3d6714d6..460adbdf3c 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -131,14 +131,13 @@ namespace Microsoft.FSharp.Collections [] let ofList (source:list<'T>) : ISeq<'T> = - Upcast.seq (ThinListEnumerable<'T> source) + Upcast.seq source [] let ofSeq (source:seq<'T>) : ISeq<'T> = match source with | :? ISeq<'T> as seq -> seq | :? array<'T> as array -> ofArray array - | :? list<'T> as list -> ofList list | null -> nullArg "source" | _ -> Upcast.seq (ThinEnumerable<'T> source) diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index b540ea4ffe..c89841ef28 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3468,6 +3468,79 @@ namespace Microsoft.FSharp.Core //============================================================================ //============================================================================ +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 IOutOfBand = + abstract StopFurtherProcessing : PipeIdx -> unit + abstract ListenForStopFurtherProcessing : Action -> unit + + [] + type Activity() = + abstract ChainComplete : PipeIdx -> unit + abstract ChainDispose : unit -> unit + + [] + type Activity<'T> () = + inherit Activity() + abstract ProcessNext : input:'T -> bool + + [] + type Activity<'T,'U> () = + inherit Activity<'T>() + + [] + type Folder<'T,'Result>(initalResult:'Result) = + inherit Activity<'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 with get () = haltedIdx + + interface IOutOfBand 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 TransformFactory<'T,'U> () = + abstract Compose<'V> : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> + + type ISeq<'T> = + inherit IEnumerable<'T> + abstract member PushTransform<'U> : TransformFactory<'T,'U> -> ISeq<'U> + abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result + + module internal Upcast = + // The f# compiler outputs unnecessary unbox.any calls in upcasts. If this functionality + // is fixed with the compiler then these functions can be removed. + let inline seq<'T,'seq when 'seq :> ISeq<'T> and 'seq : not struct> (t:'seq) : ISeq<'T> = (# "" t : ISeq<'T> #) + let inline enumerable<'T,'enumerable when 'enumerable :> IEnumerable<'T> and 'enumerable : not struct> (t:'enumerable) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) + let inline enumerableNonGeneric<'enumerable when 'enumerable :> IEnumerable and 'enumerable : not struct> (t:'enumerable) : IEnumerable = (# "" t : IEnumerable #) + let inline enumerator<'T,'enumerator when 'enumerator :> IEnumerator<'T> and 'enumerator : not struct> (t:'enumerator) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) + let inline enumeratorNonGeneric<'enumerator when 'enumerator :> IEnumerator and 'enumerator : not struct> (t:'enumerator) : IEnumerator = (# "" t : IEnumerator #) + let inline outOfBand<'outOfBand when 'outOfBand :> IOutOfBand and 'outOfBand : not struct> (t:'outOfBand) : IOutOfBand = (# "" t : IOutOfBand #) + namespace Microsoft.FSharp.Collections //------------------------------------------------------------------------- @@ -3481,6 +3554,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 [] #if !FX_NO_DEBUG_PROXIES @@ -3495,6 +3569,7 @@ namespace Microsoft.FSharp.Collections type List<'T> = | ([]) : 'T list | (::) : Head: 'T * Tail: 'T list -> 'T list + interface Microsoft.FSharp.Collections.SeqComposition.ISeq<'T> interface System.Collections.Generic.IEnumerable<'T> interface System.Collections.IEnumerable @@ -3545,6 +3620,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 @@ -3640,6 +3716,95 @@ namespace Microsoft.FSharp.Collections | [] -> outOfRange() loop n l + module ListSeqImplementation = + type ComposedFactory<'T,'U,'V> private (first:TransformFactory<'T,'U>, second:TransformFactory<'U,'V>) = + inherit TransformFactory<'T,'V>() + + override this.Compose<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = + first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) + + static member Combine (first:TransformFactory<'T,'U>) (second:TransformFactory<'U,'V>) : TransformFactory<'T,'V> = + upcast ComposedFactory(first, second) + + type Result<'T>() = + inherit Folder<'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:Activity<'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 ((Upcast.enumerator this)).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>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + interface System.Collections.IEnumerable with + member this.GetEnumerator () : System.Collections.IEnumerator = + let genericEnumerable = Upcast.enumerable this + let genericEnumerator = genericEnumerable.GetEnumerator () + Upcast.enumeratorNonGeneric genericEnumerator + + interface System.Collections.Generic.IEnumerable<'U> with + member this.GetEnumerator () : System.Collections.Generic.IEnumerator<'U> = + let result = Result<'U> () + let activity = transformFactory.Compose (Upcast.outOfBand result) pipeIdx result + Upcast.enumerator (new ListEnumerator<'T,'U>(alist, activity, result)) + + interface ISeq<'U> with + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new ListEnumerable<'T,'V>(alist, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = + let result = createFolder (pipeIdx+1) + let consumer = transformFactory.Compose (Upcast.outOfBand result) 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 #if !FX_NO_DEBUG_DISPLAYS [] @@ -3688,6 +3853,28 @@ namespace Microsoft.FSharp.Collections if i > j then [] else PrivateListHelpers.sliceTake (j-i) (PrivateListHelpers.sliceSkip i l) + interface ISeq<'T> with + member this.PushTransform<'U> (next:TransformFactory<'T,'U>) = + Upcast.seq (new ListSeqImplementation.ListEnumerable<'T,'U>(this, next, 1)) + + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'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 @@ -3701,71 +3888,7 @@ namespace Microsoft.FSharp.Collections type seq<'T> = IEnumerable<'T> - -namespace Microsoft.FSharp.Collections.SeqComposition - open System - open System.Collections - open System.Collections.Generic - open Microsoft.FSharp.Core - open Microsoft.FSharp.Collections - open BasicInlinedOperations - open LanguagePrimitives.IntrinsicOperators - - type PipeIdx = int - - type IOutOfBand = - abstract StopFurtherProcessing : PipeIdx -> unit - abstract ListenForStopFurtherProcessing : Action -> unit - - [] - type Activity() = - abstract ChainComplete : PipeIdx -> unit - abstract ChainDispose : unit -> unit - - [] - type Activity<'T> () = - inherit Activity() - abstract ProcessNext : input:'T -> bool - - [] - type Activity<'T,'U> () = - inherit Activity<'T>() - - [] - type Folder<'T,'Result>(initalResult:'Result) = - inherit Activity<'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 with get () = haltedIdx - - interface IOutOfBand 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 TransformFactory<'T,'U> () = - abstract Compose<'V> : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> - - type ISeq<'T> = - inherit IEnumerable<'T> - abstract member PushTransform<'U> : TransformFactory<'T,'U> -> ISeq<'U> - abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result - + //------------------------------------------------------------------------- // Operators //------------------------------------------------------------------------- diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index 795fa62a9b..1a4423e15b 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -1776,82 +1776,11 @@ 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 - - open System - open System.Collections.Generic - open Microsoft.FSharp.Core - - /// The type of immutable singly-linked lists. - /// - /// Use the constructors [] and :: (infix) to create values of this type, or - /// the notation [1;2;3]. Use the values in the List module to manipulate - /// values of this type, or pattern match against the values directly. - [] - [] - [] - type List<'T> = - | ([]) : 'T list - | (::) : Head: 'T * Tail: 'T list -> 'T list - /// Returns an empty list of a particular type - static member Empty : 'T list - - /// Gets the number of items contained in the list - member Length : int - - /// Gets a value indicating if the list contains no entries - member IsEmpty : bool - - /// Gets the first element of the list - member Head : 'T - - /// Gets the tail of the list, which is a list containing all the elements of the list, excluding the first element - member Tail : 'T list - - /// Gets the element of the list at the given position. - /// Lists are represented as linked lists so this is an O(n) operation. - /// The index. - /// The value at the given index. - member Item : index:int -> 'T with get - - /// Gets a slice of the list, the elements of the list from the given start index to the given end index. - /// The start index. - /// The end index. - /// The sub list specified by the input indices. - member GetSlice : startIndex:int option * endIndex:int option -> 'T list - - /// Returns a list with head as its first element and tail as its subsequent elements - /// A new head value for the list. - /// The existing list. - /// The list with head appended to the front of tail. - static member Cons : head:'T * tail:'T list -> 'T list - - interface System.Collections.Generic.IEnumerable<'T> - interface System.Collections.IEnumerable - -#if !FSCORE_PORTABLE_OLD - interface System.Collections.Generic.IReadOnlyCollection<'T> -#endif - - /// An abbreviation for the type of immutable singly-linked lists. - /// - /// Use the constructors [] and :: (infix) to create values of this type, or - /// the notation [1;2;3]. Use the values in the List module to manipulate - /// values of this type, or pattern match against the values directly. - and 'T list = List<'T> - - /// An abbreviation for the CLI type System.Collections.Generic.List<_> - type ResizeArray<'T> = System.Collections.Generic.List<'T> - - /// An abbreviation for the CLI type System.Collections.Generic.IEnumerable<_> - type seq<'T> = IEnumerable<'T> - namespace Microsoft.FSharp.Collections.SeqComposition open System open System.Collections open System.Collections.Generic open Microsoft.FSharp.Core - open Microsoft.FSharp.Collections /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the /// source of the chain. @@ -1919,6 +1848,77 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract member PushTransform : TransformFactory<'T,'U> -> ISeq<'U> abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result +namespace Microsoft.FSharp.Collections + + open System + open System.Collections.Generic + open Microsoft.FSharp.Core + + /// The type of immutable singly-linked lists. + /// + /// Use the constructors [] and :: (infix) to create values of this type, or + /// the notation [1;2;3]. Use the values in the List module to manipulate + /// values of this type, or pattern match against the values directly. + [] + [] + [] + type List<'T> = + | ([]) : 'T list + | (::) : Head: 'T * Tail: 'T list -> 'T list + /// Returns an empty list of a particular type + static member Empty : 'T list + + /// Gets the number of items contained in the list + member Length : int + + /// Gets a value indicating if the list contains no entries + member IsEmpty : bool + + /// Gets the first element of the list + member Head : 'T + + /// Gets the tail of the list, which is a list containing all the elements of the list, excluding the first element + member Tail : 'T list + + /// Gets the element of the list at the given position. + /// Lists are represented as linked lists so this is an O(n) operation. + /// The index. + /// The value at the given index. + member Item : index:int -> 'T with get + + /// Gets a slice of the list, the elements of the list from the given start index to the given end index. + /// The start index. + /// The end index. + /// The sub list specified by the input indices. + member GetSlice : startIndex:int option * endIndex:int option -> 'T list + + /// Returns a list with head as its first element and tail as its subsequent elements + /// A new head value for the list. + /// The existing list. + /// 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.ISeq<'T> + interface System.Collections.Generic.IEnumerable<'T> + interface System.Collections.IEnumerable + +#if !FSCORE_PORTABLE_OLD + interface System.Collections.Generic.IReadOnlyCollection<'T> +#endif + + /// An abbreviation for the type of immutable singly-linked lists. + /// + /// Use the constructors [] and :: (infix) to create values of this type, or + /// the notation [1;2;3]. Use the values in the List module to manipulate + /// values of this type, or pattern match against the values directly. + and 'T list = List<'T> + + /// An abbreviation for the CLI type System.Collections.Generic.List<_> + type ResizeArray<'T> = System.Collections.Generic.List<'T> + + /// An abbreviation for the CLI type System.Collections.Generic.IEnumerable<_> + type seq<'T> = IEnumerable<'T> + namespace Microsoft.FSharp.Core open System diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index d6021b0661..a4ceb2ebdb 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -310,29 +310,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition finally activity.ChainDispose () - type ListEnumerator<'T,'U>(alist:list<'T>, activity:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, activity) - - 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 <- SeqProcessNextStates.Finished - activity.ChainComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext list - let length (source:ISeq<_>) = source.Fold (fun _ -> { new Folder<'T,int>(0) with @@ -471,72 +448,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition fat.Fold createFolder and AppendEnumerable<'T> (sources:list>) = - inherit ThinConcatEnumerable<'T, list>, ISeq<'T>>(sources, fun sources -> Upcast.seq (ThinListEnumerable>(List.rev sources))) + inherit ThinConcatEnumerable<'T, list>, ISeq<'T>>(sources, fun sources -> Upcast.seq (List.rev sources)) override this.Append source = Upcast.seq (AppendEnumerable (source::sources)) - and ThinListEnumerable<'T>(alist:list<'T>) = - inherit EnumerableBase<'T>() - - override __.Length () = alist.Length - - interface IEnumerable<'T> with - member __.GetEnumerator () = (Upcast.enumerable alist).GetEnumerator () - - interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new ListEnumerable<'T,'U>(alist, next, 1)) - - member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = - let result = createFolder 1 - try - let mutable lst = alist - while - ( match lst with - | hd :: tl when result.HaltedIdx = 0 -> - result.ProcessNext hd |> ignore - lst <- tl - true - | _ -> false - ) do () - - result.ChainComplete result.HaltedIdx - finally - result.ChainDispose () - result.Result - - and ListEnumerable<'T,'U>(alist:list<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Upcast.enumerator (new ListEnumerator<'T,'U>(alist, createFold transformFactory result pipeIdx, result)) - - interface ISeq<'U> with - member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new ListEnumerable<'T,'V>(alist, ComposedFactory.Combine transformFactory next, pipeIdx+1)) - - member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = - let result = createFolder (pipeIdx+1) - let consumer = createFold transformFactory result pipeIdx - try - let mutable lst = alist - while - ( match lst with - | hd :: tl when result.HaltedIdx = 0 -> - consumer.ProcessNext hd |> ignore - lst <- tl - true - | _ -> false - ) do () - - consumer.ChainComplete result.HaltedIdx - finally - consumer.ChainDispose () - result.Result - /// ThinEnumerable is used when the IEnumerable provided to ofSeq is neither an array or a list type ThinEnumerable<'T>(enumerable:IEnumerable<'T>) = inherit EnumerableBase<'T>() diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index 631d022434..450bcdd218 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -97,11 +97,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition new : list> -> AppendEnumerable<'T> override Append : ISeq<'T> -> ISeq<'T> - type internal ThinListEnumerable<'T> = - inherit EnumerableBase<'T> - new : list<'T> -> ThinListEnumerable<'T> - interface ISeq<'T> - type internal ThinResizeArrayEnumerable<'T> = inherit EnumerableBase<'T> new : ResizeArray<'T> -> ThinResizeArrayEnumerable<'T> From ba95b234ab998d4b75d126568a5fa22526c22f9b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 26 Apr 2017 19:24:02 +1000 Subject: [PATCH 65/83] Added list specific overloads --- src/fsharp/FSharp.Core/iseq.fs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 460adbdf3c..2d2ed73c95 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -1134,8 +1134,9 @@ namespace Microsoft.FSharp.Collections [] let toList (source : ISeq<'T>) = - checkNonNull "source" source - Microsoft.FSharp.Primitives.Basics.List.ofISeq source + match source with + | :? list<'T> as lst -> lst + | _ -> Microsoft.FSharp.Primitives.Basics.List.ofISeq source [] let replicate count x = @@ -1144,8 +1145,11 @@ namespace Microsoft.FSharp.Collections [] let isEmpty (source : ISeq<'T>) = - use ie = source.GetEnumerator() - not (ie.MoveNext()) + match source with + | :? list<'T> as lst -> lst.IsEmpty + | _ -> + use ie = source.GetEnumerator() + not (ie.MoveNext()) [] let cast (source: IEnumerable) : ISeq<'T> = From 8c16ea8831bc06122eeb5ced28a216bff411488b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Apr 2017 16:30:46 +1000 Subject: [PATCH 66/83] Optimization for 0/1 element arrays --- src/fsharp/FSharp.Core/iseq.fs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 2d2ed73c95..481c19a767 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -115,6 +115,12 @@ namespace Microsoft.FSharp.Collections member __.GetHashCode o = c.GetHashCode o._1 member __.Equals (lhs,rhs) = c.Equals (lhs._1, rhs._1) } + [] + let empty<'T> = Microsoft.FSharp.Collections.SeqComposition.Core.EmptyEnumerable<'T>.Instance + + [] + let singleton x = Upcast.seq (new SingletonEnumerable<_>(x)) + /// wraps a ResizeArray in the ISeq framework. Care must be taken that the underlying ResizeArray /// is not modified whilst it can be accessed as the ISeq, so check on version is performed. /// i.e. usually iteration on calls the enumerator provied by GetEnumerator ensure that the @@ -127,7 +133,10 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source:array<'T>) : ISeq<'T> = checkNonNull "source" source - Upcast.seq (ThinArrayEnumerable<'T> source) + match source.Length with + | 0 -> empty + | 1 -> singleton source.[0] + | _ -> Upcast.seq (ThinArrayEnumerable<'T> source) [] let ofList (source:list<'T>) : ISeq<'T> = @@ -171,9 +180,6 @@ namespace Microsoft.FSharp.Collections this.Result <- LanguagePrimitives.DivideByInt<'U> this.Result this.State override this.OnDispose () = () }) - [] - let empty<'T> = Microsoft.FSharp.Collections.SeqComposition.Core.EmptyEnumerable<'T>.Instance - [] let exactlyOne (source:ISeq<'T>) : 'T = source.Fold (fun pipeIdx -> @@ -596,9 +602,6 @@ namespace Microsoft.FSharp.Collections let concat (sources:ISeq<#ISeq<'T>>) : ISeq<'T> = Upcast.seq (ThinConcatEnumerable (sources, id)) - [] - let singleton x = Upcast.seq (new SingletonEnumerable<_>(x)) - [] let inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = let head = singleton initialState From bc92c68ea8162bd90f5801547e3e2ec8dfa073ea Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 30 Apr 2017 05:36:57 +1000 Subject: [PATCH 67/83] Map/Set use Seq.fold to utilize ISeq implementation --- src/fsharp/FSharp.Core/map.fs | 11 +---------- src/fsharp/FSharp.Core/set.fs | 11 +---------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/src/fsharp/FSharp.Core/map.fs b/src/fsharp/FSharp.Core/map.fs index f58abfcda7..0fe3ac0357 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/set.fs b/src/fsharp/FSharp.Core/set.fs index 6b31169c90..f33b27e1b5 100644 --- a/src/fsharp/FSharp.Core/set.fs +++ b/src/fsharp/FSharp.Core/set.fs @@ -495,17 +495,9 @@ 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 + 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 @@ -849,7 +841,6 @@ namespace Microsoft.FSharp.Collections [] let ofSeq (c : seq<_>) = new Set<_>(c) - [] let difference (s1: Set<'T>) (s2: Set<'T>) = s1 - s2 From 919a2a156a3d797df64ea07c153065c6c7d49965 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 1 May 2017 18:24:51 +1000 Subject: [PATCH 68/83] ISeq.length optimized for list.length --- src/fsharp/FSharp.Core/iseq.fs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 481c19a767..c19e13f9cf 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -133,10 +133,7 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source:array<'T>) : ISeq<'T> = checkNonNull "source" source - match source.Length with - | 0 -> empty - | 1 -> singleton source.[0] - | _ -> Upcast.seq (ThinArrayEnumerable<'T> source) + Upcast.seq (ThinArrayEnumerable<'T> source) [] let ofList (source:list<'T>) : ISeq<'T> = @@ -961,6 +958,7 @@ namespace Microsoft.FSharp.Collections let length (source:ISeq<'T>) = match source with | :? EnumerableBase<'T> as s -> s.Length () + | :? list<'T> as l -> l.Length | _ -> length source [] From b8335bcae925798a1c35c6a66b891d3c0cb1744a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 3 May 2017 16:34:03 +1000 Subject: [PATCH 69/83] Removed Upcast hack due to #2972 --- src/fsharp/FSharp.Core/iseq.fs | 75 +++++++++----------- src/fsharp/FSharp.Core/prim-types.fs | 52 ++++---------- src/fsharp/FSharp.Core/seqcore.fs | 100 ++++++++++++--------------- 3 files changed, 93 insertions(+), 134 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index c19e13f9cf..0c129b9c95 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -102,13 +102,6 @@ namespace Microsoft.FSharp.Collections // ineffictive ** let inline avoid boolean = match boolean with true -> true | false -> false - module internal Upcast = - // The f# compiler outputs unnecessary unbox.any calls in upcasts. If this functionality - // is fixed with the compiler then these functions can be removed. - let inline seq<'T,'seq when 'seq :> ISeq<'T> and 'seq : not struct> (t:'seq) : ISeq<'T> = (# "" t : ISeq<'T> #) - let inline enumerableNonGeneric<'enumerable when 'enumerable :> IEnumerable and 'enumerable : not struct> (t:'enumerable) : IEnumerable = (# "" t : IEnumerable #) - let inline outOfBand<'outOfBand when 'outOfBand :> IOutOfBand and 'outOfBand : not struct> (t:'outOfBand) : IOutOfBand = (# "" t : IOutOfBand #) - let inline valueComparer<'T when 'T : equality> ()= let c = HashIdentity.Structural<'T> { new IEqualityComparer> with @@ -119,7 +112,7 @@ namespace Microsoft.FSharp.Collections let empty<'T> = Microsoft.FSharp.Collections.SeqComposition.Core.EmptyEnumerable<'T>.Instance [] - let singleton x = Upcast.seq (new SingletonEnumerable<_>(x)) + let singleton<'T> (x:'T) : ISeq<'T> = upcast (new SingletonEnumerable<_>(x)) /// wraps a ResizeArray in the ISeq framework. Care must be taken that the underlying ResizeArray /// is not modified whilst it can be accessed as the ISeq, so check on version is performed. @@ -128,16 +121,16 @@ namespace Microsoft.FSharp.Collections /// performed in this case. If you want this funcitonality, then use the ofSeq function instead. [] let ofResizeArrayUnchecked (source:ResizeArray<'T>) : ISeq<'T> = - Upcast.seq (ThinResizeArrayEnumerable<'T> source) + upcast (ThinResizeArrayEnumerable<'T> source) [] let ofArray (source:array<'T>) : ISeq<'T> = checkNonNull "source" source - Upcast.seq (ThinArrayEnumerable<'T> source) + upcast (ThinArrayEnumerable<'T> source) [] let ofList (source:list<'T>) : ISeq<'T> = - Upcast.seq source + upcast source [] let ofSeq (source:seq<'T>) : ISeq<'T> = @@ -145,7 +138,7 @@ namespace Microsoft.FSharp.Collections | :? ISeq<'T> as seq -> seq | :? array<'T> as array -> ofArray array | null -> nullArg "source" - | _ -> Upcast.seq (ThinEnumerable<'T> source) + | _ -> upcast (ThinEnumerable<'T> source) [] let inline average (source:ISeq<'T>) = @@ -187,7 +180,7 @@ namespace Microsoft.FSharp.Collections this.Result <- value else this.State._2 <- true - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = @@ -213,7 +206,7 @@ namespace Microsoft.FSharp.Collections if this.State.MoveNext() then this.Result <- folder this.Result value this.State.Current else - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = () @@ -221,17 +214,17 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = - Upcast.seq (new UnfoldEnumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance, 1)) + upcast (new UnfoldEnumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance, 1)) [] let initInfinite<'T> (f:int->'T) : ISeq<'T> = - Upcast.seq (new InitEnumerableDecider<'T>(Nullable (), f, 1)) + upcast (new InitEnumerableDecider<'T>(Nullable (), f, 1)) [] let init<'T> (count:int) (f:int->'T) : ISeq<'T> = if count < 0 then invalidArgInputMustBeNonNegative "count" count elif count = 0 then empty else - Upcast.seq (new InitEnumerableDecider<'T>(Nullable count, f, 1)) + upcast (new InitEnumerableDecider<'T>(Nullable count, f, 1)) [] let inline iter f (source:ISeq<'T>) = @@ -249,7 +242,7 @@ namespace Microsoft.FSharp.Collections if this.State.MoveNext() then f value this.State.Current else - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = () @@ -265,7 +258,7 @@ namespace Microsoft.FSharp.Collections this.State._1 <- this.State._1 + 1 Unchecked.defaultof<_> else - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> override this.OnComplete _ = () override this.OnDispose () = this.State._2.Dispose () }) @@ -276,7 +269,7 @@ namespace Microsoft.FSharp.Collections { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = this.Result <- Some value - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] @@ -310,7 +303,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if f value then this.Result <- true - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] @@ -321,9 +314,9 @@ namespace Microsoft.FSharp.Collections if this.State.MoveNext() then if predicate value this.State.Current then this.Result <- true - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx else - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = () @@ -336,7 +329,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if element = value then this.Result <- true - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] @@ -346,7 +339,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if not (predicate value) then this.Result <- false - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] @@ -357,9 +350,9 @@ namespace Microsoft.FSharp.Collections if this.State.MoveNext() then if not (predicate value this.State.Current) then this.Result <- false - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx else - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = () @@ -447,12 +440,12 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if not (this.State.MoveNext()) then this.Result <- 1 - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx else let c = f value this.State.Current if c <> 0 then this.Result <- c - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = if this.Result = 0 && this.State.MoveNext() then @@ -597,7 +590,7 @@ namespace Microsoft.FSharp.Collections [] let concat (sources:ISeq<#ISeq<'T>>) : ISeq<'T> = - Upcast.seq (ThinConcatEnumerable (sources, id)) + upcast (ThinConcatEnumerable (sources, id)) [] let inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = @@ -788,7 +781,7 @@ namespace Microsoft.FSharp.Collections match f value with | (Some _) as some -> this.Result <- some - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx | None -> () Unchecked.defaultof<_> (* return value unused in Fold context *) }) @@ -799,7 +792,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if f value then this.Result <- Some value - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] @@ -810,7 +803,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if predicate value then this.Result <- Some this.State - (Upcast.outOfBand this).StopFurtherProcessing pipeIdx + (this :> IOutOfBand).StopFurtherProcessing pipeIdx else this.State <- this.State + 1 Unchecked.defaultof<_> (* return value unused in Fold context *) }) @@ -874,11 +867,11 @@ namespace Microsoft.FSharp.Collections let append (source1:ISeq<'T>) (source2: ISeq<'T>) : ISeq<'T> = match source1 with | :? EnumerableBase<'T> as s -> s.Append source2 - | _ -> Upcast.seq (new AppendEnumerable<_>([source2; source1])) + | _ -> upcast (new AppendEnumerable<_>([source2; source1])) [] - let delay (delayed:unit->ISeq<'T>) = - Upcast.seq (DelayedEnumerable (delayed, 1)) + let delay (delayed:unit->ISeq<'T>) : ISeq<'T> = + upcast (DelayedEnumerable (delayed, 1)) module internal GroupBy = let inline private impl (comparer:IEqualityComparer<'SafeKey>) (keyf:'T->'SafeKey) (getKey:'SafeKey->'Key) (source:ISeq<'T>) = @@ -1094,7 +1087,7 @@ namespace Microsoft.FSharp.Collections else None) - let cached = Upcast.seq (new UnfoldEnumerable<'T,'T,int>(unfolding, 0, IdentityFactory.Instance, 1)) + let cached : ISeq<'T> = upcast (new UnfoldEnumerable<'T,'T,int>(unfolding, 0, IdentityFactory.Instance, 1)) interface System.IDisposable with member __.Dispose() = @@ -1111,7 +1104,7 @@ namespace Microsoft.FSharp.Collections member __.GetEnumerator() = cached.GetEnumerator() interface System.Collections.IEnumerable with - member __.GetEnumerator() = (Upcast.enumerableNonGeneric cached).GetEnumerator() + member __.GetEnumerator() = (cached:>IEnumerable).GetEnumerator() interface ISeq<'T> with member __.PushTransform next = cached.PushTransform next @@ -1121,7 +1114,7 @@ namespace Microsoft.FSharp.Collections [] let cache (source:ISeq<'T>) : ISeq<'T> = - Upcast.seq (new CachedSeq<_> (source)) + upcast (new CachedSeq<_> (source)) [] let collect f sources = map f sources |> concat @@ -1140,9 +1133,9 @@ namespace Microsoft.FSharp.Collections | _ -> Microsoft.FSharp.Primitives.Basics.List.ofISeq source [] - let replicate count x = + let replicate<'T> count (x:'T) : ISeq<'T> = if count < 0 then raise (ArgumentOutOfRangeException "count") - Upcast.seq (new InitEnumerable<'T,'T>(Nullable count, (fun _ -> x), IdentityFactory.Instance, 1)) + upcast (new InitEnumerable<'T,'T>(Nullable count, (fun _ -> x), IdentityFactory.Instance, 1)) [] let isEmpty (source : ISeq<'T>) = diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index c89841ef28..32f4d49a34 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3531,16 +3531,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract member PushTransform<'U> : TransformFactory<'T,'U> -> ISeq<'U> abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result - module internal Upcast = - // The f# compiler outputs unnecessary unbox.any calls in upcasts. If this functionality - // is fixed with the compiler then these functions can be removed. - let inline seq<'T,'seq when 'seq :> ISeq<'T> and 'seq : not struct> (t:'seq) : ISeq<'T> = (# "" t : ISeq<'T> #) - let inline enumerable<'T,'enumerable when 'enumerable :> IEnumerable<'T> and 'enumerable : not struct> (t:'enumerable) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) - let inline enumerableNonGeneric<'enumerable when 'enumerable :> IEnumerable and 'enumerable : not struct> (t:'enumerable) : IEnumerable = (# "" t : IEnumerable #) - let inline enumerator<'T,'enumerator when 'enumerator :> IEnumerator<'T> and 'enumerator : not struct> (t:'enumerator) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) - let inline enumeratorNonGeneric<'enumerator when 'enumerator :> IEnumerator and 'enumerator : not struct> (t:'enumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline outOfBand<'outOfBand when 'outOfBand :> IOutOfBand and 'outOfBand : not struct> (t:'outOfBand) : IOutOfBand = (# "" t : IOutOfBand #) - namespace Microsoft.FSharp.Collections //------------------------------------------------------------------------- @@ -3756,7 +3746,7 @@ namespace Microsoft.FSharp.Collections activity.ChainDispose () interface System.Collections.IEnumerator with - member this.Current : obj = box ((Upcast.enumerator this)).Current + member this.Current : obj = box (this :> IEnumerator<'U>).Current member __.MoveNext () = result.SeqState <- 0(*InProcess*) moveNext list @@ -3772,23 +3762,21 @@ namespace Microsoft.FSharp.Collections type ListEnumerable<'T,'U>(alist:list<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = interface System.Collections.IEnumerable with member this.GetEnumerator () : System.Collections.IEnumerator = - let genericEnumerable = Upcast.enumerable this - let genericEnumerator = genericEnumerable.GetEnumerator () - Upcast.enumeratorNonGeneric genericEnumerator + 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 = transformFactory.Compose (Upcast.outOfBand result) pipeIdx result - Upcast.enumerator (new ListEnumerator<'T,'U>(alist, activity, result)) + let activity = transformFactory.Compose (result :> IOutOfBand) pipeIdx result + upcast (new ListEnumerator<'T,'U>(alist, activity, result)) interface ISeq<'U> with member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new ListEnumerable<'T,'V>(alist, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + upcast (new ListEnumerable<'T,'V>(alist, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = let result = createFolder (pipeIdx+1) - let consumer = transformFactory.Compose (Upcast.outOfBand result) pipeIdx result + let consumer = transformFactory.Compose (result :> IOutOfBand) pipeIdx result try let mutable lst = alist while @@ -3855,7 +3843,7 @@ namespace Microsoft.FSharp.Collections interface ISeq<'T> with member this.PushTransform<'U> (next:TransformFactory<'T,'U>) = - Upcast.seq (new ListSeqImplementation.ListEnumerable<'T,'U>(this, next, 1)) + upcast (new ListSeqImplementation.ListEnumerable<'T,'U>(this, next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = let result = createFolder 1 @@ -3910,16 +3898,6 @@ namespace Microsoft.FSharp.Core [] module Operators = - // The f# compiler outputs unnecessary unbox.any calls in upcasts. If this functionality - // is fixed with the compiler then these functions can be removed. - module Upcast = - let inline seq<'T,'seq when 'seq :> ISeq<'T> and 'seq : not struct> (t:'seq) : ISeq<'T> = (# "" t : ISeq<'T> #) - let inline enumerable<'T,'enumerable when 'enumerable :> IEnumerable<'T> and 'enumerable : not struct> (t:'enumerable) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) - let inline enumerableNonGeneric<'enumerable when 'enumerable :> System.Collections.IEnumerable and 'enumerable : not struct> (t:'enumerable) : System.Collections.IEnumerable = (# "" t : System.Collections.IEnumerable #) - let inline enumerator<'T,'enumerator when 'enumerator :> IEnumerator<'T> and 'enumerator : not struct> (t:'enumerator) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) - let inline enumeratorNonGeneric<'enumerator when 'enumerator :> System.Collections.IEnumerator and 'enumerator : not struct> (t:'enumerator) : System.Collections.IEnumerator = (# "" t : System.Collections.IEnumerator #) - let inline outOfBand<'outOfBand when 'outOfBand :> IOutOfBand and 'outOfBand : not struct> (t:'outOfBand) : IOutOfBand = (# "" t : IOutOfBand #) - #if MULTI_DIMENSIONAL_EXTENSION_PROPERTIES type ``[,]``<'T> with [] @@ -5352,7 +5330,7 @@ namespace Microsoft.FSharp.Core false interface IEnumerator with - member this.Current : obj = box ((Upcast.enumerator this)).Current + member this.Current : obj = box (this :> IEnumerator<'U>).Current member __.Reset () : unit = source.Reset () member __.MoveNext () = state <- Mode.Running @@ -5382,16 +5360,16 @@ namespace Microsoft.FSharp.Core interface IEnumerable<'U> with member __.GetEnumerator () = let folder = SetResultToInput<'U>() - Upcast.enumerator (new SeqSourceEnumerator<'T,'U>(source.GetEnumerator (), current.Compose (Upcast.outOfBand folder) pipeIdx folder, folder)) + upcast (new SeqSourceEnumerator<'T,'U>(source.GetEnumerator (), current.Compose (folder :> IOutOfBand) pipeIdx folder, folder)) interface IEnumerable with member __.GetEnumerator () = let folder = SetResultToInput<'U>() - Upcast.enumeratorNonGeneric (new SeqSourceEnumerator<'T,'U>(source.GetEnumerator (), current.Compose (Upcast.outOfBand folder) pipeIdx folder, folder)) + upcast (new SeqSourceEnumerator<'T,'U>(source.GetEnumerator (), current.Compose (folder :> IOutOfBand) pipeIdx folder, folder)) interface ISeq<'U> with member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new SeqSourceEnumerable<'T,'V>(source, ComposedFactory.Combine current next, pipeIdx+1)) + upcast (new SeqSourceEnumerable<'T,'V>(source, ComposedFactory.Combine current next, pipeIdx+1)) member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = source.Fold f current pipeIdx @@ -5401,11 +5379,11 @@ namespace Microsoft.FSharp.Core member __.GetEnumerator () = source.GetEnumerator () interface IEnumerable with - member __.GetEnumerator () = Upcast.enumeratorNonGeneric (source.GetEnumerator ()) + member __.GetEnumerator () = upcast (source.GetEnumerator ()) interface ISeq<'U> with member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new SeqSourceEnumerable<'U,'V>(source, next, 1)) + upcast (new SeqSourceEnumerable<'U,'V>(source, next, 1)) member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = source.Fold f IdentityFactory.Instance 1 @@ -5625,7 +5603,7 @@ namespace Microsoft.FSharp.Core member __.GetEnumerator () = singleStepRangeEnumerator () member __.Fold<'Result,'Output> (createFolder:PipeIdx->Folder<'Output,'Result>) (transformFactory:TransformFactory<'T,'Output>) pipeIdx : 'Result = let result = createFolder (pipeIdx+1) - let consumer = transformFactory.Compose (Upcast.outOfBand result) pipeIdx result + let consumer = transformFactory.Compose (result :> IOutOfBand) pipeIdx result try let mutable i : 'T = n while result.HaltedIdx = 0 && i <= m do @@ -5637,7 +5615,7 @@ namespace Microsoft.FSharp.Core finally consumer.ChainDispose () } - Upcast.enumerable (SeqSourceEnumerableThin<'T> source) + 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/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index a4ceb2ebdb..6f4725cfc0 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -162,16 +162,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition // a single funciton 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 #) - module internal Upcast = - // The f# compiler outputs unnecessary unbox.any calls in upcasts. If this functionality - // is fixed with the compiler then these functions can be removed. - let inline seq<'T,'seq when 'seq :> ISeq<'T> and 'seq : not struct> (t:'seq) : ISeq<'T> = (# "" t : ISeq<'T> #) - let inline enumerable<'T,'enumerable when 'enumerable :> IEnumerable<'T> and 'enumerable : not struct> (t:'enumerable) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) - let inline enumerableNonGeneric<'enumerable when 'enumerable :> IEnumerable and 'enumerable : not struct> (t:'enumerable) : IEnumerable = (# "" t : IEnumerable #) - let inline enumerator<'T,'enumerator when 'enumerator :> IEnumerator<'T> and 'enumerator : not struct> (t:'enumerator) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) - let inline enumeratorNonGeneric<'enumerator when 'enumerator :> IEnumerator and 'enumerator : not struct> (t:'enumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline outOfBand<'outOfBand when 'outOfBand :> IOutOfBand and 'outOfBand : not struct> (t:'outOfBand) : IOutOfBand = (# "" t : IOutOfBand #) - type IdentityFactory<'T> private () = inherit TransformFactory<'T,'T> () static let singleton : TransformFactory<'T,'T> = upcast (IdentityFactory<'T>()) @@ -193,7 +183,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract CanSkip : unit -> bool let createFold (factory:TransformFactory<_,_>) (folder:Folder<_,_>) pipeIdx = - factory.Compose (Upcast.outOfBand folder) pipeIdx folder + factory.Compose (folder :> IOutOfBand) pipeIdx folder type SeqProcessNextStates = | InProcess = 0 @@ -234,7 +224,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition activity.ChainDispose () interface IEnumerator with - member this.Current : obj = box ((Upcast.enumerator this)).Current + 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 () @@ -325,14 +315,12 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract member Append : ISeq<'T> -> ISeq<'T> abstract member Length : unit -> int - default this.Append source = Upcast.seq (AppendEnumerable [source; this]) + default this.Append source = upcast (AppendEnumerable [source; this]) default this.Length () = length this interface IEnumerable with member this.GetEnumerator () : IEnumerator = - let genericEnumerable = Upcast.enumerable this - let genericEnumerator = genericEnumerable.GetEnumerator () - Upcast.enumeratorNonGeneric genericEnumerator + upcast ((this:>IEnumerable<'T>).GetEnumerator ()) interface IEnumerable<'T> with // fsharp doesn't allow abstract interface methods @@ -349,11 +337,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new VanillaEnumerator<'T,'U>(enumerable.GetEnumerator(), createFold transformFactory result pipeIdx, result)) + upcast (new VanillaEnumerator<'T,'U>(enumerable.GetEnumerator(), createFold transformFactory result pipeIdx, result)) interface ISeq<'U> with member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new VanillaEnumerable<'T,'V>(enumerable, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + upcast (new VanillaEnumerable<'T,'V>(enumerable, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = let result = createFolder (pipeIdx+1) @@ -379,16 +367,16 @@ namespace Microsoft.FSharp.Collections.SeqComposition inherit Folder<'Collection, 'Result>(Unchecked.defaultof<_>) do - (Upcast.outOfBand this).ListenForStopFurtherProcessing (fun idx -> - (Upcast.outOfBand result).StopFurtherProcessing idx - (Upcast.outOfBand common).StopFurtherProcessing PipeIdx.MinValue) + (this :> IOutOfBand).ListenForStopFurtherProcessing (fun idx -> + (result :> IOutOfBand).StopFurtherProcessing idx + (common :> IOutOfBand).StopFurtherProcessing PipeIdx.MinValue) - (Upcast.outOfBand result).ListenForStopFurtherProcessing (fun idx -> - (Upcast.outOfBand this).StopFurtherProcessing idx - (Upcast.outOfBand common).StopFurtherProcessing PipeIdx.MaxValue) + (result :> IOutOfBand).ListenForStopFurtherProcessing (fun idx -> + (this :> IOutOfBand).StopFurtherProcessing idx + (common :> IOutOfBand).StopFurtherProcessing PipeIdx.MaxValue) let getCommonFolder = Closure.forceCapture (fun (_:PipeIdx) -> - (Upcast.outOfBand common).StopFurtherProcessing 0 + (common :> IOutOfBand).StopFurtherProcessing 0 common) override __.ProcessNext value = @@ -408,11 +396,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface IEnumerable<'U> with member __.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new ConcatEnumerator<'T,'U,'Collection>(sources, createFold transformFactory result pipeIdx, result)) + upcast (new ConcatEnumerator<'T,'U,'Collection>(sources, createFold transformFactory result pipeIdx, result)) interface ISeq<'U> with member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new ConcatEnumerable<'T,'V,'Collection>(sources, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + upcast (new ConcatEnumerable<'T,'V,'Collection>(sources, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = sources.Fold (fun lowerPipeIdx -> @@ -420,7 +408,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition let result = createFolder (thisPipeIdx+1) - let outOfBand = Upcast.outOfBand result + let outOfBand = result :> IOutOfBand let consumer = transformFactory.Compose outOfBand thisPipeIdx result @@ -437,21 +425,21 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = let result = Result<'T> () - Upcast.enumerator (new ConcatEnumerator<'T,'T,'Collection> (preEnumerate sources, createFold IdentityFactory.Instance result 1, result)) + upcast (new ConcatEnumerator<'T,'T,'Collection> (preEnumerate sources, createFold IdentityFactory.Instance result 1, result)) interface ISeq<'T> with member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (ConcatEnumerable<'T,'V,'Collection>(preEnumerate sources, next, 1)) + upcast (ConcatEnumerable<'T,'V,'Collection>(preEnumerate sources, next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = - let fat = Upcast.seq (ConcatEnumerable<'T,'T,'Collection>(preEnumerate sources, IdentityFactory.Instance, 1)) + let fat : ISeq<'T> = upcast (ConcatEnumerable<'T,'T,'Collection>(preEnumerate sources, IdentityFactory.Instance, 1)) fat.Fold createFolder and AppendEnumerable<'T> (sources:list>) = - inherit ThinConcatEnumerable<'T, list>, ISeq<'T>>(sources, fun sources -> Upcast.seq (List.rev sources)) + inherit ThinConcatEnumerable<'T, list>, ISeq<'T>>(sources, fun sources -> upcast (List.rev sources)) override this.Append source = - Upcast.seq (AppendEnumerable (source::sources)) + 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>) = @@ -475,7 +463,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface ISeq<'T> with member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new VanillaEnumerable<'T,'U>(enumerable, next, 1)) + upcast (new VanillaEnumerable<'T,'U>(enumerable, next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = let result = createFolder 1 @@ -502,7 +490,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface ISeq<'T> with member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new DelayedEnumerable<'U>((fun () -> (delayed()).PushTransform next), pipeIdx+1)) + upcast (new DelayedEnumerable<'U>((fun () -> (delayed()).PushTransform next), pipeIdx+1)) member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = (delayed()).Fold f @@ -522,7 +510,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface ISeq<'T> with member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (VanillaEnumerable<'T,'V>(this, next, 1)) + upcast (VanillaEnumerable<'T,'V>(this, next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = let result = createFolder 1 @@ -560,11 +548,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface IEnumerable<'U> with member __.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new ArrayEnumerator<'T,'U>(array, createFold transformFactory result pipeIdx, result)) + upcast (new ArrayEnumerator<'T,'U>(array, createFold transformFactory result pipeIdx, result)) interface ISeq<'U> with member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new ArrayEnumerable<'T,'V>(array, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + upcast (new ArrayEnumerable<'T,'V>(array, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member __.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = let result = createFolder (pipeIdx+1) @@ -587,11 +575,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition override __.Length () = array.Length interface IEnumerable<'T> with - member __.GetEnumerator () = (Upcast.enumerable array).GetEnumerator () + member __.GetEnumerator () = (array:>IEnumerable<'T>).GetEnumerator () interface ISeq<'T> with member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new ArrayEnumerable<'T,'U>(array, next, 1)) + upcast (new ArrayEnumerable<'T,'U>(array, next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = let result = createFolder 1 @@ -613,11 +601,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition override __.Length () = 1 interface IEnumerable<'T> with - member this.GetEnumerator () = Upcast.enumerator (new Singleton<'T>(item)) + member this.GetEnumerator () = (new Singleton<'T>(item)) :> IEnumerator<'T> interface ISeq<'T> with member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new ArrayEnumerable<'T,'U>([|item|], next, 1)) + upcast (new ArrayEnumerable<'T,'U>([|item|], next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = let result = createFolder 1 @@ -658,11 +646,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new ResizeArrayEnumerator<'T,'U>(resizeArray, createFold transformFactory result pipeIdx, result)) + upcast (new ResizeArrayEnumerator<'T,'U>(resizeArray, createFold transformFactory result pipeIdx, result)) interface ISeq<'U> with member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new ResizeArrayEnumerable<'T,'V>(resizeArray, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + upcast (new ResizeArrayEnumerable<'T,'V>(resizeArray, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member __.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = let result = createFolder (pipeIdx+1) @@ -685,11 +673,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition override __.Length () = resizeArray.Count interface IEnumerable<'T> with - member __.GetEnumerator () = (Upcast.enumerable resizeArray).GetEnumerator () + member __.GetEnumerator () = (resizeArray :> IEnumerable<'T>).GetEnumerator () interface ISeq<'T> with member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new ResizeArrayEnumerable<'T,'U>(resizeArray, next, 1)) + upcast (new ResizeArrayEnumerable<'T,'U>(resizeArray, next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = let result = createFolder 1 @@ -734,11 +722,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new UnfoldEnumerator<'T,'U,'GeneratorState>(generator, state, createFold transformFactory result pipeIdx, result)) + upcast (new UnfoldEnumerator<'T,'U,'GeneratorState>(generator, state, createFold transformFactory result pipeIdx, result)) interface ISeq<'U> with member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new UnfoldEnumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + upcast (new UnfoldEnumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = let result = createFolder (pipeIdx+1) @@ -815,11 +803,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new InitEnumerator<'T,'U>(count, f, createFold transformFactory result pipeIdx, result)) + upcast (new InitEnumerator<'T,'U>(count, f, createFold transformFactory result pipeIdx, result)) interface ISeq<'U> with member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new InitEnumerable<'T,'V>(count, f, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + upcast (new InitEnumerable<'T,'V>(count, f, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = let terminatingIdx = getInitTerminatingIdx count @@ -939,12 +927,12 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface ISeq<'T> with member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (InitEnumerable<'T,'V>(count, f, next, pipeIdx+1)) + upcast (InitEnumerable<'T,'V>(count, f, next, pipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = let result = createFolder 1 try - use enumerator = (Upcast.enumerable this).GetEnumerator () + use enumerator = (this:>IEnumerable<'T>).GetEnumerator () while result.HaltedIdx = 0 && enumerator.MoveNext () do result.ProcessNext enumerator.Current |> ignore @@ -1230,7 +1218,7 @@ namespace Microsoft.FSharp.Core.CompilerServices interface ISeq<'T> with member this.PushTransform<'U> (next:TransformFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new GeneratedSequenceBaseEnumerable<'T,'U>(this, next, 1)) + upcast (new GeneratedSequenceBaseEnumerable<'T,'U>(this, next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = let result = createFolder 1 @@ -1267,15 +1255,15 @@ namespace Microsoft.FSharp.Core.CompilerServices interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new VanillaEnumerator<'T,'U>(generatedSequence.GetFreshEnumerator(), current.Compose (Upcast.outOfBand result) pipeIdx result, result)) + upcast (new VanillaEnumerator<'T,'U>(generatedSequence.GetFreshEnumerator(), current.Compose (result :> IOutOfBand) pipeIdx result, result)) interface ISeq<'U> with member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new GeneratedSequenceBaseEnumerable<'T,'V>(generatedSequence, ComposedFactory.Combine current next, pipeIdx+1)) + upcast (new GeneratedSequenceBaseEnumerable<'T,'V>(generatedSequence, ComposedFactory.Combine current next, pipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = let result = createFolder (pipeIdx+1) - let consumer = current.Compose (Upcast.outOfBand result) pipeIdx result + let consumer = current.Compose (result :> IOutOfBand) pipeIdx result try use maybeGeneratedSequenceBase = generatedSequence.GetFreshEnumerator () match maybeGeneratedSequenceBase with From 04f5eff4415f4e57fc13ed7a8404fe87eb0b9167 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 5 May 2017 18:30:24 +1000 Subject: [PATCH 70/83] Consolidated common factory code --- src/fsharp/FSharp.Core/seqcore.fs | 98 ++++++++++++++++-------------- src/fsharp/FSharp.Core/seqcore.fsi | 9 ++- 2 files changed, 59 insertions(+), 48 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index 6f4725cfc0..eebc18ebb2 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -182,9 +182,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition // and it can only do it at the start of a sequence abstract CanSkip : unit -> bool - let createFold (factory:TransformFactory<_,_>) (folder:Folder<_,_>) pipeIdx = - factory.Compose (folder :> IOutOfBand) pipeIdx folder - type SeqProcessNextStates = | InProcess = 0 | NotStarted = 1 @@ -331,21 +328,35 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.PushTransform _ = derivedClassShouldImplement () member __.Fold _ = derivedClassShouldImplement () - and VanillaEnumerable<'T,'U>(enumerable:IEnumerable<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + and [] SeqFactoryBase<'T,'U>(transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() + member __.CreateActivityPipeline<'Result> (folder:Folder<'U,'Result>) : Activity<'T,'U> = + transformFactory.Compose (folder :> IOutOfBand) pipeIdx folder + + member this.CreatePipeline<'Result> (createFolder:PipeIdx->Folder<'U,'Result>, [] activity:byref>) = + let folder = createFolder (pipeIdx+1) + activity <- this.CreateActivityPipeline folder + folder + + member __.Compose next = ComposedFactory.Combine transformFactory next + + member __.PipeIdx = pipeIdx + + and VanillaEnumerable<'T,'U>(enumerable:IEnumerable<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) + interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcast (new VanillaEnumerator<'T,'U>(enumerable.GetEnumerator(), createFold transformFactory result pipeIdx, result)) + upcast (new VanillaEnumerator<'T,'U>(enumerable.GetEnumerator(), this.CreateActivityPipeline result, result)) interface ISeq<'U> with - member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - upcast (new VanillaEnumerable<'T,'V>(enumerable, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + upcast (new VanillaEnumerable<'T,'V>(enumerable, this.Compose next, this.PipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = - let result = createFolder (pipeIdx+1) - let consumer = createFold transformFactory result pipeIdx + let result, consumer = this.CreatePipeline createFolder try use enumerator = enumerable.GetEnumerator () while result.HaltedIdx = 0 && enumerator.MoveNext () do @@ -391,16 +402,16 @@ namespace Microsoft.FSharp.Collections.SeqComposition consumer.ChainDispose () and ConcatEnumerable<'T,'U,'Collection when 'Collection :> ISeq<'T>> (sources:ISeq<'Collection>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() + inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with - member __.GetEnumerator () : IEnumerator<'U> = + member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcast (new ConcatEnumerator<'T,'U,'Collection>(sources, createFold transformFactory result pipeIdx, result)) + upcast (new ConcatEnumerator<'T,'U,'Collection>(sources, this.CreateActivityPipeline result, result)) interface ISeq<'U> with member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - upcast (new ConcatEnumerable<'T,'V,'Collection>(sources, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + upcast (new ConcatEnumerable<'T,'V,'Collection>(sources, this.Compose next, this.PipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = sources.Fold (fun lowerPipeIdx -> @@ -425,7 +436,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = let result = Result<'T> () - upcast (new ConcatEnumerator<'T,'T,'Collection> (preEnumerate sources, createFold IdentityFactory.Instance result 1, result)) + upcast (new ConcatEnumerator<'T,'T,'Collection> (preEnumerate sources, result, result)) interface ISeq<'T> with member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = @@ -543,20 +554,19 @@ namespace Microsoft.FSharp.Collections.SeqComposition moveNext () type ArrayEnumerable<'T,'U>(array:array<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() + inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with - member __.GetEnumerator () : IEnumerator<'U> = + member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcast (new ArrayEnumerator<'T,'U>(array, createFold transformFactory result pipeIdx, result)) + upcast (new ArrayEnumerator<'T,'U>(array, this.CreateActivityPipeline result, result)) interface ISeq<'U> with - member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - upcast (new ArrayEnumerable<'T,'V>(array, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + upcast (new ArrayEnumerable<'T,'V>(array, this.Compose next, this.PipeIdx+1)) - member __.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = - let result = createFolder (pipeIdx+1) - let consumer = createFold transformFactory result pipeIdx + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = + let result, consumer = this.CreatePipeline createFolder try let array = array let mutable idx = 0 @@ -641,20 +651,19 @@ namespace Microsoft.FSharp.Collections.SeqComposition moveNext () type ResizeArrayEnumerable<'T,'U>(resizeArray:ResizeArray<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() + inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcast (new ResizeArrayEnumerator<'T,'U>(resizeArray, createFold transformFactory result pipeIdx, result)) + upcast (new ResizeArrayEnumerator<'T,'U>(resizeArray, this.CreateActivityPipeline result, result)) interface ISeq<'U> with - member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - upcast (new ResizeArrayEnumerable<'T,'V>(resizeArray, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + upcast (new ResizeArrayEnumerable<'T,'V>(resizeArray, this.Compose next, this.PipeIdx+1)) - member __.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = - let result = createFolder (pipeIdx+1) - let consumer = createFold transformFactory result pipeIdx + member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = + let result, consumer = this.CreatePipeline createFolder try let array = resizeArray let mutable idx = 0 @@ -717,20 +726,19 @@ namespace Microsoft.FSharp.Collections.SeqComposition moveNext () type UnfoldEnumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() + inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcast (new UnfoldEnumerator<'T,'U,'GeneratorState>(generator, state, createFold transformFactory result pipeIdx, result)) + upcast (new UnfoldEnumerator<'T,'U,'GeneratorState>(generator, state, this.CreateActivityPipeline result, result)) interface ISeq<'U> with member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - upcast (new UnfoldEnumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + upcast (new UnfoldEnumerable<'T,'V,'GeneratorState>(generator, state, this.Compose next, this.PipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = - let result = createFolder (pipeIdx+1) - let consumer = createFold transformFactory result pipeIdx + let result, consumer = this.CreatePipeline createFolder try let generator = generator let rec iterate current = @@ -798,21 +806,20 @@ namespace Microsoft.FSharp.Collections.SeqComposition moveNext () type InitEnumerable<'T,'U>(count:Nullable, f:int->'T, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() + inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcast (new InitEnumerator<'T,'U>(count, f, createFold transformFactory result pipeIdx, result)) + upcast (new InitEnumerator<'T,'U>(count, f, this.CreateActivityPipeline result, result)) interface ISeq<'U> with member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - upcast (new InitEnumerable<'T,'V>(count, f, ComposedFactory.Combine transformFactory next, pipeIdx+1)) + upcast (new InitEnumerable<'T,'V>(count, f, this.Compose next, this.PipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = let terminatingIdx = getInitTerminatingIdx count - let result = createFolder (pipeIdx+1) - let consumer = createFold transformFactory result pipeIdx + let result, consumer = this.CreatePipeline createFolder try let firstIdx = match box consumer with @@ -1249,21 +1256,20 @@ namespace Microsoft.FSharp.Core.CompilerServices count <- count + 1 count - and GeneratedSequenceBaseEnumerable<'T,'U>(generatedSequence:GeneratedSequenceBase<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = - inherit EnumerableBase<'U>() + and GeneratedSequenceBaseEnumerable<'T,'U>(generatedSequence:GeneratedSequenceBase<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcast (new VanillaEnumerator<'T,'U>(generatedSequence.GetFreshEnumerator(), current.Compose (result :> IOutOfBand) pipeIdx result, result)) + upcast (new VanillaEnumerator<'T,'U>(generatedSequence.GetFreshEnumerator(), this.CreateActivityPipeline result, result)) interface ISeq<'U> with - member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - upcast (new GeneratedSequenceBaseEnumerable<'T,'V>(generatedSequence, ComposedFactory.Combine current next, pipeIdx+1)) + member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + upcast (new GeneratedSequenceBaseEnumerable<'T,'V>(generatedSequence, this.Compose next, this.PipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = - let result = createFolder (pipeIdx+1) - let consumer = current.Compose (result :> IOutOfBand) pipeIdx result + let result, consumer = this.CreatePipeline createFolder try use maybeGeneratedSequenceBase = generatedSequence.GetFreshEnumerator () match maybeGeneratedSequenceBase with diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index 450bcdd218..982f9b5926 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -75,6 +75,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract member Length : unit -> int interface ISeq<'T> + [] + type SeqFactoryBase<'T,'U> = + inherit EnumerableBase<'U> + new : TransformFactory<'T,'U> * PipeIdx -> SeqFactoryBase<'T,'U> + [] type internal IdentityFactory<'T> = inherit TransformFactory<'T,'T> @@ -113,7 +118,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface ISeq<'T> type internal UnfoldEnumerable<'T,'U,'GeneratorState> = - inherit EnumerableBase<'U> + inherit SeqFactoryBase<'T,'U> new : ('GeneratorState->option<'T*'GeneratorState>)*'GeneratorState*TransformFactory<'T,'U>*PipeIdx -> UnfoldEnumerable<'T,'U,'GeneratorState> interface ISeq<'U> @@ -128,7 +133,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface ISeq<'T> type internal InitEnumerable<'T,'U> = - inherit EnumerableBase<'U> + inherit SeqFactoryBase<'T,'U> new : Nullable * (int->'T) * TransformFactory<'T,'U> * PipeIdx -> InitEnumerable<'T,'U> interface ISeq<'U> From 5b8aa9b9e6f50c3ba0f540aea9902c2ba20c36be Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 5 May 2017 18:42:29 +1000 Subject: [PATCH 71/83] Converted TransformFactory into interface --- src/fsharp/FSharp.Core/iseq.fs | 42 ++++++++--------- src/fsharp/FSharp.Core/iseq.fsi | 4 +- src/fsharp/FSharp.Core/prim-types.fs | 49 ++++++++++---------- src/fsharp/FSharp.Core/prim-types.fsi | 8 ++-- src/fsharp/FSharp.Core/seqcore.fs | 65 +++++++++++++-------------- src/fsharp/FSharp.Core/seqcore.fsi | 10 ++--- 6 files changed, 86 insertions(+), 92 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 0c129b9c95..494913a22a 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -290,7 +290,7 @@ namespace Microsoft.FSharp.Collections [] let inline except (itemsToExclude: seq<'T>) (source:ISeq<'T>) : ISeq<'T> when 'T:equality = checkNonNull "itemsToExclude" itemsToExclude - source.PushTransform { new TransformFactory<'T,'T>() with + source.PushTransform { new ITransformFactory<'T,'T> with override __.Compose _ _ next = upcast { new Transform<'T,'V,Lazy>>(next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = @@ -360,7 +360,7 @@ namespace Microsoft.FSharp.Collections [] let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source.PushTransform { new TransformFactory<'T,'T>() with + source.PushTransform { new ITransformFactory<'T,'T> with override __.Compose _ _ next = upcast { new Transform<'T,'V,NoValue>(next,Unchecked.defaultof) with override __.ProcessNext input = @@ -369,7 +369,7 @@ namespace Microsoft.FSharp.Collections [] let inline map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = - source.PushTransform { new TransformFactory<'T,'U>() with + source.PushTransform { new ITransformFactory<'T,'U> with override __.Compose _ _ next = upcast { new Transform<'T,'V,NoValue>(next,Unchecked.defaultof) with override __.ProcessNext input = @@ -377,7 +377,7 @@ namespace Microsoft.FSharp.Collections [] let inline mapi f (source:ISeq<_>) = - source.PushTransform { new TransformFactory<'T,'U>() with + source.PushTransform { new ITransformFactory<'T,'U> with override __.Compose _ _ next = upcast { new Transform<'T,'V,int>(next, -1) with override this.ProcessNext (input:'T) : bool = @@ -386,7 +386,7 @@ namespace Microsoft.FSharp.Collections [] let inline map2<'T,'U,'V> (map:'T->'U->'V) (source1:ISeq<'T>) (source2:ISeq<'U>) : ISeq<'V> = - source1.PushTransform { new TransformFactory<'T,'V>() with + source1.PushTransform { new ITransformFactory<'T,'V> with override __.Compose outOfBand pipeIdx (next:Activity<'V,'W>) = upcast { new TransformWithPostProcessing<'T,'W, IEnumerator<'U>>(next, (source2.GetEnumerator ())) with override this.ProcessNext input = @@ -400,7 +400,7 @@ namespace Microsoft.FSharp.Collections [] let inline mapi2<'T,'U,'V> (map:int->'T->'U->'V) (source1:ISeq<'T>) (source2:ISeq<'U>) : ISeq<'V> = - source1.PushTransform { new TransformFactory<'T,'V>() with + source1.PushTransform { new ITransformFactory<'T,'V> with override __.Compose<'W> outOfBand pipeIdx next = upcast { new TransformWithPostProcessing<'T,'W, Values>>(next, Values<_,_>(-1,source2.GetEnumerator ())) with override this.ProcessNext t = @@ -417,7 +417,7 @@ namespace Microsoft.FSharp.Collections [] let inline map3<'T,'U,'V,'W>(map:'T->'U->'V->'W) (source1:ISeq<'T>) (source2:ISeq<'U>) (source3:ISeq<'V>) : ISeq<'W> = - source1.PushTransform { new TransformFactory<'T,'W>() with + source1.PushTransform { new ITransformFactory<'T,'W> with override __.Compose<'X> outOfBand pipeIdx next = upcast { new TransformWithPostProcessing<'T,'X,Values,IEnumerator<'V>>>(next,Values<_,_>(source2.GetEnumerator(),source3.GetEnumerator())) with override this.ProcessNext t = @@ -454,7 +454,7 @@ namespace Microsoft.FSharp.Collections [] let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = - source.PushTransform { new TransformFactory<'T,'U>() with + source.PushTransform { new ITransformFactory<'T,'U> with override __.Compose _ _ next = upcast { new Transform<'T,'V,NoValue>(next,Unchecked.defaultof) with override __.ProcessNext input = @@ -464,7 +464,7 @@ namespace Microsoft.FSharp.Collections [] let inline distinct (source:ISeq<'T>) : ISeq<'T> when 'T:equality = - source.PushTransform { new TransformFactory<'T,'T>() with + source.PushTransform { new ITransformFactory<'T,'T> with override __.Compose _ _ next = upcast { new Transform<'T,'V,HashSet<'T>>(next,HashSet HashIdentity.Structural) with override this.ProcessNext (input:'T) : bool = @@ -472,7 +472,7 @@ namespace Microsoft.FSharp.Collections [] let inline distinctBy (keyf:'T->'Key) (source:ISeq<'T>) :ISeq<'T> when 'Key:equality = - source.PushTransform { new TransformFactory<'T,'T>() with + source.PushTransform { new ITransformFactory<'T,'T> with override __.Compose _ _ next = upcast { new Transform<'T,'V,HashSet<'Key>> (next,HashSet HashIdentity.Structural) with override this.ProcessNext (input:'T) : bool = @@ -556,7 +556,7 @@ namespace Microsoft.FSharp.Collections [] let pairwise (source:ISeq<'T>) : ISeq<'T*'T> = - source.PushTransform { new TransformFactory<'T,'T * 'T>() with + source.PushTransform { new ITransformFactory<'T,'T*'T> with override __.Compose _ _ next = upcast { new Transform<'T,'U,Values>(next, Values(true, Unchecked.defaultof<'T>)) with // member this.isFirst = this.State._1 @@ -596,7 +596,7 @@ namespace Microsoft.FSharp.Collections let inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = let head = singleton initialState let tail = - source.PushTransform { new TransformFactory<'T,'State>() with + source.PushTransform { new ITransformFactory<'T,'State> with override __.Compose _ _ next = upcast { new Transform<'T,'V,'State>(next, initialState) with override this.ProcessNext (input:'T) : bool = @@ -606,7 +606,7 @@ namespace Microsoft.FSharp.Collections [] let skip (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = - source.PushTransform { new TransformFactory<'T,'T>() with + source.PushTransform { new ITransformFactory<'T,'T> with override __.Compose _ _ next = let mutable this = Unchecked.defaultof> let skipper = @@ -638,7 +638,7 @@ namespace Microsoft.FSharp.Collections [] let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source.PushTransform { new TransformFactory<'T,'T>() with + source.PushTransform { new ITransformFactory<'T,'T> with override __.Compose _ _ next = upcast { new Transform<'T,'V,bool>(next,true) with // member this.skip = this.State @@ -673,7 +673,7 @@ namespace Microsoft.FSharp.Collections if takeCount < 0 then invalidArgInputMustBeNonNegative "count" takeCount elif takeCount = 0 then empty else - source.PushTransform { new TransformFactory<'T,'T>() with + source.PushTransform { new ITransformFactory<'T,'T> with member __.Compose outOfBand pipelineIdx next = if takeCount = 0 then outOfBand.StopFurtherProcessing pipelineIdx @@ -699,7 +699,7 @@ namespace Microsoft.FSharp.Collections [] let inline takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source.PushTransform { new TransformFactory<'T,'T>() with + source.PushTransform { new ITransformFactory<'T,'T> with member __.Compose outOfBand pipeIdx next = upcast { new Transform<'T,'V,NoValue>(next,Unchecked.defaultof) with override __.ProcessNext (input:'T) : bool = @@ -711,7 +711,7 @@ namespace Microsoft.FSharp.Collections [] let tail (source:ISeq<'T>) : ISeq<'T> = - source.PushTransform { new TransformFactory<'T,'T>() with + source.PushTransform { new ITransformFactory<'T,'T> with member __.Compose _ _ next = upcast { new TransformWithPostProcessing<'T,'V,bool>(next,true) with // member this.isFirst = this.State @@ -728,7 +728,7 @@ namespace Microsoft.FSharp.Collections [] let truncate (truncateCount:int) (source:ISeq<'T>) : ISeq<'T> = - source.PushTransform { new TransformFactory<'T,'T>() with + source.PushTransform { new ITransformFactory<'T,'T> with member __.Compose outOfBand pipeIdx next = upcast { new Transform<'T,'U,int>(next,(*count*)0) with // member this.count = this.State @@ -749,7 +749,7 @@ namespace Microsoft.FSharp.Collections [] let tryItem index (source:ISeq<'T>) = if index < 0 then None else - source.PushTransform { new TransformFactory<'T,'T>() with + source.PushTransform { new ITransformFactory<'T,'T> with override __.Compose _ _ next = let mutable this = Unchecked.defaultof> let skipper = @@ -835,7 +835,7 @@ namespace Microsoft.FSharp.Collections if windowSize <= 0 then invalidArgFmt "windowSize" "{0}\nwindowSize = {1}" [|SR.GetString SR.inputMustBePositive; windowSize|] - source.PushTransform { new TransformFactory<'T,'T[]>() with + source.PushTransform { new ITransformFactory<'T,'T[]> with member __.Compose outOfBand pipeIdx next = upcast { new Transform<'T,'U,Values<'T[],int,int>>(next,Values<'T[],int,int>(Array.zeroCreateUnchecked windowSize, 0, windowSize-1)) with @@ -1158,7 +1158,7 @@ namespace Microsoft.FSharp.Collections if chunkSize <= 0 then invalidArgFmt "chunkSize" "{0}\nchunkSize = {1}" [|SR.GetString SR.inputMustBePositive; chunkSize|] - source.PushTransform { new TransformFactory<'T,'T[]>() with + source.PushTransform { new ITransformFactory<'T,'T[]> with member __.Compose outOfBand pipeIdx next = upcast { new TransformWithPostProcessing<'T,'U,Values<'T[],int>>(next,Values<'T[],int>(Array.zeroCreateUnchecked chunkSize, 0)) with diff --git a/src/fsharp/FSharp.Core/iseq.fsi b/src/fsharp/FSharp.Core/iseq.fsi index 076daafa4c..98160503b9 100644 --- a/src/fsharp/FSharp.Core/iseq.fsi +++ b/src/fsharp/FSharp.Core/iseq.fsi @@ -39,7 +39,7 @@ namespace Microsoft.FSharp.Collections /// 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 TransformFactory's Compose function. + /// in the ITransformFactory's Compose function. [] type Transform<'T,'U,'State> = inherit Activity<'T,'U> @@ -51,7 +51,7 @@ namespace Microsoft.FSharp.Collections /// 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 TransformFactory's Compose function. + /// in the ITransformFactory's Compose function. [] type TransformWithPostProcessing<'T,'U,'State> = inherit Transform<'T,'U,'State> diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 32f4d49a34..ebb9250266 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3522,13 +3522,12 @@ namespace Microsoft.FSharp.Collections.SeqComposition override this.ChainComplete _ = () override this.ChainDispose () = () - [] - type TransformFactory<'T,'U> () = + type ITransformFactory<'T,'U> = abstract Compose<'V> : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> type ISeq<'T> = inherit IEnumerable<'T> - abstract member PushTransform<'U> : TransformFactory<'T,'U> -> ISeq<'U> + abstract member PushTransform<'U> : ITransformFactory<'T,'U> -> ISeq<'U> abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result namespace Microsoft.FSharp.Collections @@ -3707,13 +3706,12 @@ namespace Microsoft.FSharp.Collections loop n l module ListSeqImplementation = - type ComposedFactory<'T,'U,'V> private (first:TransformFactory<'T,'U>, second:TransformFactory<'U,'V>) = - inherit TransformFactory<'T,'V>() - - override this.Compose<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = - first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) + type ComposedFactory<'T,'U,'V> private (first:ITransformFactory<'T,'U>, second:ITransformFactory<'U,'V>) = + interface ITransformFactory<'T,'V> with + member this.Compose<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = + first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) - static member Combine (first:TransformFactory<'T,'U>) (second:TransformFactory<'U,'V>) : TransformFactory<'T,'V> = + static member Combine (first:ITransformFactory<'T,'U>) (second:ITransformFactory<'U,'V>) : ITransformFactory<'T,'V> = upcast ComposedFactory(first, second) type Result<'T>() = @@ -3759,7 +3757,7 @@ namespace Microsoft.FSharp.Collections elif result.SeqState = 1(*NotStarted*) then PrivateListHelpers.notStarted() else PrivateListHelpers.alreadyFinished() - type ListEnumerable<'T,'U>(alist:list<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + type ListEnumerable<'T,'U>(alist:list<'T>, transformFactory:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = interface System.Collections.IEnumerable with member this.GetEnumerator () : System.Collections.IEnumerator = upcast (this :> IEnumerable<'U>).GetEnumerator () @@ -3771,7 +3769,7 @@ namespace Microsoft.FSharp.Collections upcast (new ListEnumerator<'T,'U>(alist, activity, result)) interface ISeq<'U> with - member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + member __.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = upcast (new ListEnumerable<'T,'V>(alist, ComposedFactory.Combine transformFactory next, pipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = @@ -3842,7 +3840,7 @@ namespace Microsoft.FSharp.Collections PrivateListHelpers.sliceTake (j-i) (PrivateListHelpers.sliceSkip i l) interface ISeq<'T> with - member this.PushTransform<'U> (next:TransformFactory<'T,'U>) = + member this.PushTransform<'U> (next:ITransformFactory<'T,'U>) = upcast (new ListSeqImplementation.ListEnumerable<'T,'U>(this, next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = @@ -5294,20 +5292,19 @@ namespace Microsoft.FSharp.Core | Running = 1 | Finished = 2 - type ComposedFactory<'T,'U,'V> private (first:TransformFactory<'T,'U>, second:TransformFactory<'U,'V>) = - inherit TransformFactory<'T,'V>() - - override this.Compose<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = - first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) + type ComposedFactory<'T,'U,'V> private (first:ITransformFactory<'T,'U>, second:ITransformFactory<'U,'V>) = + interface ITransformFactory<'T,'V> with + member this.Compose<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = + first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) - static member Combine (first:TransformFactory<'T,'U>) (second:TransformFactory<'U,'V>) : TransformFactory<'T,'V> = + static member Combine (first:ITransformFactory<'T,'U>) (second:ITransformFactory<'U,'V>) : ITransformFactory<'T,'V> = upcast ComposedFactory(first, second) type IdentityFactory<'T> private () = - inherit TransformFactory<'T,'T> () - static let singleton : TransformFactory<'T,'T> = upcast (IdentityFactory<'T>()) - override __.Compose<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next + static let singleton : ITransformFactory<'T,'T> = upcast (IdentityFactory<'T>()) static member Instance = singleton + interface ITransformFactory<'T,'T> with + member __.Compose<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next type SetResultToInput<'T>() = inherit Folder<'T,'T>(Unchecked.defaultof<'T>) @@ -5354,9 +5351,9 @@ namespace Microsoft.FSharp.Core type ISeqSource<'T> = abstract member GetEnumerator : unit -> IEnumerator<'T> - abstract member Fold<'Result,'U> : f:(PipeIdx->Folder<'U,'Result>) -> TransformFactory<'T,'U> -> PipeIdx -> 'Result + abstract member Fold<'Result,'U> : f:(PipeIdx->Folder<'U,'Result>) -> ITransformFactory<'T,'U> -> PipeIdx -> 'Result - type SeqSourceEnumerable<'T,'U>(source:ISeqSource<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + type SeqSourceEnumerable<'T,'U>(source:ISeqSource<'T>, current:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = interface IEnumerable<'U> with member __.GetEnumerator () = let folder = SetResultToInput<'U>() @@ -5368,7 +5365,7 @@ namespace Microsoft.FSharp.Core upcast (new SeqSourceEnumerator<'T,'U>(source.GetEnumerator (), current.Compose (folder :> IOutOfBand) pipeIdx folder, folder)) interface ISeq<'U> with - member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + member __.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = upcast (new SeqSourceEnumerable<'T,'V>(source, ComposedFactory.Combine current next, pipeIdx+1)) member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = @@ -5382,7 +5379,7 @@ namespace Microsoft.FSharp.Core member __.GetEnumerator () = upcast (source.GetEnumerator ()) interface ISeq<'U> with - member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + member __.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = upcast (new SeqSourceEnumerable<'U,'V>(source, next, 1)) member this.Fold<'Result> (f:PipeIdx->Folder<'U,'Result>) = @@ -5601,7 +5598,7 @@ namespace Microsoft.FSharp.Core let source = { new ISeqSource<'T> with member __.GetEnumerator () = singleStepRangeEnumerator () - member __.Fold<'Result,'Output> (createFolder:PipeIdx->Folder<'Output,'Result>) (transformFactory:TransformFactory<'T,'Output>) pipeIdx : 'Result = + member __.Fold<'Result,'Output> (createFolder:PipeIdx->Folder<'Output,'Result>) (transformFactory:ITransformFactory<'T,'Output>) pipeIdx : 'Result = let result = createFolder (pipeIdx+1) let consumer = transformFactory.Compose (result :> IOutOfBand) pipeIdx result try diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index 1a4423e15b..ecc2442a77 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -1833,19 +1833,17 @@ namespace Microsoft.FSharp.Collections.SeqComposition override ChainComplete : PipeIdx -> unit override ChainDispose : unit -> unit - /// TransformFactory provides composition of Activities. Its intended to have a specialization + /// ITransformFactory provides composition of Activities. Its intended to have a specialization /// for each type of ISeq Activity. ISeq's PushTransform method is used to build a stack /// of Actvities that will be composed. - [] - type TransformFactory<'T,'U> = - new : unit -> TransformFactory<'T,'U> + type ITransformFactory<'T,'U> = abstract member Compose : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> /// ISeq<'T> is an extension to seq<'T> that provides the avilty to compose Activities /// as well as Fold the current Activity pipeline. type ISeq<'T> = inherit System.Collections.Generic.IEnumerable<'T> - abstract member PushTransform : TransformFactory<'T,'U> -> ISeq<'U> + abstract member PushTransform : ITransformFactory<'T,'U> -> ISeq<'U> abstract member Fold<'Result> : f:(PipeIdx->Folder<'T,'Result>) -> 'Result namespace Microsoft.FSharp.Collections diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index eebc18ebb2..19ec02801e 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -163,18 +163,17 @@ namespace Microsoft.FSharp.Collections.SeqComposition let inline forceCapture<'a,'b> (f:'a->'b) : 'a->'b = (# "" f : 'a->'b #) type IdentityFactory<'T> private () = - inherit TransformFactory<'T,'T> () - static let singleton : TransformFactory<'T,'T> = upcast (IdentityFactory<'T>()) - override __.Compose<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next + static let singleton : ITransformFactory<'T,'T> = upcast (IdentityFactory<'T>()) static member Instance = singleton + interface ITransformFactory<'T,'T> with + member __.Compose<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next - type ComposedFactory<'T,'U,'V> private (first:TransformFactory<'T,'U>, second:TransformFactory<'U,'V>) = - inherit TransformFactory<'T,'V>() + type ComposedFactory<'T,'U,'V> private (first:ITransformFactory<'T,'U>, second:ITransformFactory<'U,'V>) = + interface ITransformFactory<'T,'V> with + member this.Compose<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = + first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) - override this.Compose<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = - first.Compose outOfBand (pipeIdx-1) (second.Compose outOfBand pipeIdx next) - - static member Combine (first:TransformFactory<'T,'U>) (second:TransformFactory<'U,'V>) : TransformFactory<'T,'V> = + static member Combine (first:ITransformFactory<'T,'U>) (second:ITransformFactory<'U,'V>) : ITransformFactory<'T,'V> = upcast ComposedFactory(first, second) type ISkipable = @@ -328,7 +327,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.PushTransform _ = derivedClassShouldImplement () member __.Fold _ = derivedClassShouldImplement () - and [] SeqFactoryBase<'T,'U>(transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + and [] SeqFactoryBase<'T,'U>(transformFactory:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() member __.CreateActivityPipeline<'Result> (folder:Folder<'U,'Result>) : Activity<'T,'U> = @@ -343,7 +342,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.PipeIdx = pipeIdx - and VanillaEnumerable<'T,'U>(enumerable:IEnumerable<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + and VanillaEnumerable<'T,'U>(enumerable:IEnumerable<'T>, transformFactory:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with @@ -352,7 +351,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition upcast (new VanillaEnumerator<'T,'U>(enumerable.GetEnumerator(), this.CreateActivityPipeline result, result)) interface ISeq<'U> with - member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + member this.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = upcast (new VanillaEnumerable<'T,'V>(enumerable, this.Compose next, this.PipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = @@ -401,7 +400,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition override this.ChainDispose () = consumer.ChainDispose () - and ConcatEnumerable<'T,'U,'Collection when 'Collection :> ISeq<'T>> (sources:ISeq<'Collection>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + and ConcatEnumerable<'T,'U,'Collection when 'Collection :> ISeq<'T>> (sources:ISeq<'Collection>, transformFactory:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with @@ -410,7 +409,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition upcast (new ConcatEnumerator<'T,'U,'Collection>(sources, this.CreateActivityPipeline result, result)) interface ISeq<'U> with - member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + member this.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = upcast (new ConcatEnumerable<'T,'V,'Collection>(sources, this.Compose next, this.PipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = @@ -439,7 +438,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition upcast (new ConcatEnumerator<'T,'T,'Collection> (preEnumerate sources, result, result)) interface ISeq<'T> with - member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + member this.PushTransform (next:ITransformFactory<'T,'U>) : ISeq<'U> = upcast (ConcatEnumerable<'T,'V,'Collection>(preEnumerate sources, next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = @@ -473,7 +472,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.GetEnumerator () = enumerable.GetEnumerator () interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + member __.PushTransform (next:ITransformFactory<'T,'U>) : ISeq<'U> = upcast (new VanillaEnumerable<'T,'U>(enumerable, next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = @@ -500,7 +499,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition member this.GetEnumerator () : IEnumerator<'T> = (delayed()).GetEnumerator () interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + member __.PushTransform (next:ITransformFactory<'T,'U>) : ISeq<'U> = upcast (new DelayedEnumerable<'U>((fun () -> (delayed()).PushTransform next), pipeIdx+1)) member __.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) = @@ -520,7 +519,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition override this.Append source = source interface ISeq<'T> with - member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + member this.PushTransform (next:ITransformFactory<'T,'U>) : ISeq<'U> = upcast (VanillaEnumerable<'T,'V>(this, next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = @@ -553,7 +552,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type ArrayEnumerable<'T,'U>(array:array<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + type ArrayEnumerable<'T,'U>(array:array<'T>, transformFactory:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with @@ -562,7 +561,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition upcast (new ArrayEnumerator<'T,'U>(array, this.CreateActivityPipeline result, result)) interface ISeq<'U> with - member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + member this.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = upcast (new ArrayEnumerable<'T,'V>(array, this.Compose next, this.PipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = @@ -588,7 +587,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.GetEnumerator () = (array:>IEnumerable<'T>).GetEnumerator () interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + member __.PushTransform (next:ITransformFactory<'T,'U>) : ISeq<'U> = upcast (new ArrayEnumerable<'T,'U>(array, next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = @@ -614,7 +613,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition member this.GetEnumerator () = (new Singleton<'T>(item)) :> IEnumerator<'T> interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + member __.PushTransform (next:ITransformFactory<'T,'U>) : ISeq<'U> = upcast (new ArrayEnumerable<'T,'U>([|item|], next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = @@ -650,7 +649,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type ResizeArrayEnumerable<'T,'U>(resizeArray:ResizeArray<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + type ResizeArrayEnumerable<'T,'U>(resizeArray:ResizeArray<'T>, transformFactory:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with @@ -659,7 +658,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition upcast (new ResizeArrayEnumerator<'T,'U>(resizeArray, this.CreateActivityPipeline result, result)) interface ISeq<'U> with - member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + member this.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = upcast (new ResizeArrayEnumerable<'T,'V>(resizeArray, this.Compose next, this.PipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = @@ -685,7 +684,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.GetEnumerator () = (resizeArray :> IEnumerable<'T>).GetEnumerator () interface ISeq<'T> with - member __.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + member __.PushTransform (next:ITransformFactory<'T,'U>) : ISeq<'U> = upcast (new ResizeArrayEnumerable<'T,'U>(resizeArray, next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = @@ -725,7 +724,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type UnfoldEnumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + type UnfoldEnumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, transformFactory:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with @@ -734,7 +733,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition upcast (new UnfoldEnumerator<'T,'U,'GeneratorState>(generator, state, this.CreateActivityPipeline result, result)) interface ISeq<'U> with - member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + member this.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = upcast (new UnfoldEnumerable<'T,'V,'GeneratorState>(generator, state, this.Compose next, this.PipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = @@ -805,7 +804,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type InitEnumerable<'T,'U>(count:Nullable, f:int->'T, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + type InitEnumerable<'T,'U>(count:Nullable, f:int->'T, transformFactory:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with @@ -814,7 +813,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition upcast (new InitEnumerator<'T,'U>(count, f, this.CreateActivityPipeline result, result)) interface ISeq<'U> with - member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + member this.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = upcast (new InitEnumerable<'T,'V>(count, f, this.Compose next, this.PipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = @@ -933,7 +932,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition upto (if count.HasValue then Some (count.Value-1) else None) f interface ISeq<'T> with - member this.PushTransform (next:TransformFactory<'T,'U>) : ISeq<'U> = + member this.PushTransform (next:ITransformFactory<'T,'U>) : ISeq<'U> = upcast (InitEnumerable<'T,'V>(count, f, next, pipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = @@ -1224,7 +1223,7 @@ namespace Microsoft.FSharp.Core.CompilerServices member x.Reset() = raise <| new System.NotSupportedException() interface ISeq<'T> with - member this.PushTransform<'U> (next:TransformFactory<'T,'U>) : ISeq<'U> = + member this.PushTransform<'U> (next:ITransformFactory<'T,'U>) : ISeq<'U> = upcast (new GeneratedSequenceBaseEnumerable<'T,'U>(this, next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = @@ -1256,7 +1255,7 @@ namespace Microsoft.FSharp.Core.CompilerServices count <- count + 1 count - and GeneratedSequenceBaseEnumerable<'T,'U>(generatedSequence:GeneratedSequenceBase<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + and GeneratedSequenceBaseEnumerable<'T,'U>(generatedSequence:GeneratedSequenceBase<'T>, transformFactory:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with @@ -1265,7 +1264,7 @@ namespace Microsoft.FSharp.Core.CompilerServices upcast (new VanillaEnumerator<'T,'U>(generatedSequence.GetFreshEnumerator(), this.CreateActivityPipeline result, result)) interface ISeq<'U> with - member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = + member this.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = upcast (new GeneratedSequenceBaseEnumerable<'T,'V>(generatedSequence, this.Compose next, this.PipeIdx+1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'U,'Result>) = diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index 982f9b5926..c95c55cb75 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -78,12 +78,12 @@ namespace Microsoft.FSharp.Collections.SeqComposition [] type SeqFactoryBase<'T,'U> = inherit EnumerableBase<'U> - new : TransformFactory<'T,'U> * PipeIdx -> SeqFactoryBase<'T,'U> + new : ITransformFactory<'T,'U> * PipeIdx -> SeqFactoryBase<'T,'U> [] type internal IdentityFactory<'T> = - inherit TransformFactory<'T,'T> - static member Instance : TransformFactory<'T,'T> + interface ITransformFactory<'T,'T> + static member Instance : ITransformFactory<'T,'T> type internal ISkipable = // Seq.init(Infinite)? lazily uses Current. The only ISeq component that can do that is Skip @@ -119,7 +119,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition type internal UnfoldEnumerable<'T,'U,'GeneratorState> = inherit SeqFactoryBase<'T,'U> - new : ('GeneratorState->option<'T*'GeneratorState>)*'GeneratorState*TransformFactory<'T,'U>*PipeIdx -> UnfoldEnumerable<'T,'U,'GeneratorState> + new : ('GeneratorState->option<'T*'GeneratorState>)*'GeneratorState*ITransformFactory<'T,'U>*PipeIdx -> UnfoldEnumerable<'T,'U,'GeneratorState> interface ISeq<'U> type internal InitEnumerableDecider<'T> = @@ -134,7 +134,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition type internal InitEnumerable<'T,'U> = inherit SeqFactoryBase<'T,'U> - new : Nullable * (int->'T) * TransformFactory<'T,'U> * PipeIdx -> InitEnumerable<'T,'U> + new : Nullable * (int->'T) * ITransformFactory<'T,'U> * PipeIdx -> InitEnumerable<'T,'U> interface ISeq<'U> type internal DelayedEnumerable<'T> = From 1179590db94a71ebc1a49c2d321b4f403c06e17c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 6 May 2017 13:45:23 +1000 Subject: [PATCH 72/83] Moved list/array before seq in compilation order --- src/fsharp/FSharp.Core/FSharp.Core.fsproj | 24 ++++++++--------- src/fsharp/FSharp.Core/array.fs | 27 +++++++++---------- src/fsharp/FSharp.Core/collections.fs | 9 +++++++ src/fsharp/FSharp.Core/collections.fsi | 6 ++++- .../FSharp.Core/fslib-extra-pervasives.fs | 2 +- src/fsharp/FSharp.Core/list.fs | 9 +++---- src/fsharp/FSharp.Core/local.fs | 21 +++++++++++++++ src/fsharp/FSharp.Core/local.fsi | 18 ++----------- src/fsharp/FSharp.Core/seq.fs | 4 +-- src/fsharp/FSharp.Core/seqcore.fs | 10 ------- src/fsharp/FSharp.Core/seqcore.fsi | 6 ----- 11 files changed, 69 insertions(+), 67 deletions(-) diff --git a/src/fsharp/FSharp.Core/FSharp.Core.fsproj b/src/fsharp/FSharp.Core/FSharp.Core.fsproj index 1f6a7dc83e..7ca7782f4a 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.fsproj +++ b/src/fsharp/FSharp.Core/FSharp.Core.fsproj @@ -94,6 +94,18 @@ Collections/collections.fs + + Collections/list.fsi + + + Collections/list.fs + + + Collections/array.fsi + + + Collections/array.fs + Collections/seqcore.fsi @@ -118,18 +130,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 3a1cd0a94e..c33e97b11c 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 @@ -100,12 +99,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 x = @@ -185,7 +194,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[]) = @@ -435,7 +444,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 (keyf:'T->'Key) (array:'T[]) = @@ -1054,16 +1063,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 f (array : _[]) = checkNonNull "array" array diff --git a/src/fsharp/FSharp.Core/collections.fs b/src/fsharp/FSharp.Core/collections.fs index 49275a4f52..46c73a8f68 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 d81b542a31..5b04c9b32b 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 a2517c16cc..6014d10105 100644 --- a/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs +++ b/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs @@ -98,7 +98,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 (l:seq<'Key*'T>) = diff --git a/src/fsharp/FSharp.Core/list.fs b/src/fsharp/FSharp.Core/list.fs index 66cc213988..f41dbe9245 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 @@ -59,7 +58,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) = @@ -432,7 +431,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 (keyf:'T->'Key) (list:'T list) = @@ -522,10 +521,10 @@ namespace Microsoft.FSharp.Collections sortWith compareDescending xs [] - 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 f list = diff --git a/src/fsharp/FSharp.Core/local.fs b/src/fsharp/FSharp.Core/local.fs index 3eac3119ca..0e715835ce 100644 --- a/src/fsharp/FSharp.Core/local.fs +++ b/src/fsharp/FSharp.Core/local.fs @@ -1145,3 +1145,24 @@ module internal Array = res.[i] <- subUnchecked !startIndex minChunkSize array startIndex := !startIndex + minChunkSize res + + 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 + | _ -> + let res = ResizeArray source + res.ToArray() + + let toSeq (source : array<'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 () } \ No newline at end of file diff --git a/src/fsharp/FSharp.Core/local.fsi b/src/fsharp/FSharp.Core/local.fsi index 56ee687843..f197b712ac 100644 --- a/src/fsharp/FSharp.Core/local.fsi +++ b/src/fsharp/FSharp.Core/local.fsi @@ -70,35 +70,21 @@ 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> -> array<'T> + val toSeq : array<'T> -> seq<'T> \ No newline at end of file diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index b7334d6eaf..c23c36dc13 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1068,7 +1068,7 @@ namespace Microsoft.FSharp.Collections 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 groupByRefType (keyf:'T->'Key) (seq:seq<'T>) = seq |> groupByImpl StructBox<'Key>.Comparer (fun t -> StructBox (keyf t)) (fun sb -> sb.Value) [] let groupBy (keyf:'T->'Key) (seq:seq<'T>) = @@ -1151,7 +1151,7 @@ namespace Microsoft.FSharp.Collections 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) + let countByRefType (keyf:'T->'Key) (seq:seq<'T>) = seq |> countByImpl StructBox<'Key>.Comparer (fun t -> StructBox (keyf t)) (fun sb -> sb.Value) [] let countBy (keyf:'T->'Key) (source:seq<'T>) = diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index 19ec02801e..4853d9f5b3 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -964,16 +964,6 @@ namespace Microsoft.FSharp.Core.CompilerServices 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) diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index c95c55cb75..d16593c13e 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -160,12 +160,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 From 278742c7a85c57d15269658418d42d343890d465 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 6 May 2017 19:28:50 +1000 Subject: [PATCH 73/83] Removed duplicate code in Thin implementations --- src/fsharp/FSharp.Core/seqcore.fs | 67 ++---------------------------- src/fsharp/FSharp.Core/seqcore.fsi | 24 ++++++++--- 2 files changed, 21 insertions(+), 70 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index 4853d9f5b3..d9cc720a6d 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -453,7 +453,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition /// ThinEnumerable is used when the IEnumerable provided to ofSeq is neither an array or a list type ThinEnumerable<'T>(enumerable:IEnumerable<'T>) = - inherit EnumerableBase<'T>() + inherit VanillaEnumerable<'T,'T>(enumerable, IdentityFactory.Instance, 0) override __.Length () = match enumerable with @@ -468,25 +468,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition count <- count + 1 count - interface IEnumerable<'T> with - member __.GetEnumerator () = enumerable.GetEnumerator () - - interface ISeq<'T> with - member __.PushTransform (next:ITransformFactory<'T,'U>) : ISeq<'U> = - upcast (new VanillaEnumerable<'T,'U>(enumerable, next, 1)) - - member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = - let result = createFolder 1 - try - use enumerator = enumerable.GetEnumerator () - while result.HaltedIdx = 0 && enumerator.MoveNext () do - result.ProcessNext enumerator.Current |> ignore - - result.ChainComplete result.HaltedIdx - finally - result.ChainDispose () - result.Result - type DelayedEnumerable<'T>(delayed:unit->ISeq<'T>, pipeIdx:PipeIdx) = inherit EnumerableBase<'T>() @@ -579,31 +560,10 @@ namespace Microsoft.FSharp.Collections.SeqComposition result.Result type ThinArrayEnumerable<'T>(array:array<'T>) = - inherit EnumerableBase<'T>() + inherit ArrayEnumerable<'T,'T>(array, IdentityFactory.Instance, 0) override __.Length () = array.Length - interface IEnumerable<'T> with - member __.GetEnumerator () = (array:>IEnumerable<'T>).GetEnumerator () - - interface ISeq<'T> with - member __.PushTransform (next:ITransformFactory<'T,'U>) : ISeq<'U> = - upcast (new ArrayEnumerable<'T,'U>(array, next, 1)) - - member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = - let result = createFolder 1 - try - let array = array - let mutable idx = 0 - while result.HaltedIdx = 0 && idx < array.Length do - result.ProcessNext array.[idx] |> ignore - idx <- idx + 1 - - result.ChainComplete result.HaltedIdx - finally - result.ChainDispose () - result.Result - type SingletonEnumerable<'T>(item:'T) = inherit EnumerableBase<'T>() @@ -676,31 +636,10 @@ namespace Microsoft.FSharp.Collections.SeqComposition result.Result type ThinResizeArrayEnumerable<'T>(resizeArray:ResizeArray<'T>) = - inherit EnumerableBase<'T>() + inherit ResizeArrayEnumerable<'T,'T>(resizeArray, IdentityFactory.Instance, 0) override __.Length () = resizeArray.Count - interface IEnumerable<'T> with - member __.GetEnumerator () = (resizeArray :> IEnumerable<'T>).GetEnumerator () - - interface ISeq<'T> with - member __.PushTransform (next:ITransformFactory<'T,'U>) : ISeq<'U> = - upcast (new ResizeArrayEnumerable<'T,'U>(resizeArray, next, 1)) - - member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = - let result = createFolder 1 - try - let array = resizeArray - let mutable idx = 0 - while result.HaltedIdx = 0 && idx < array.Count do - result.ProcessNext array.[idx] |> ignore - idx <- idx + 1 - - result.ChainComplete result.HaltedIdx - finally - result.ChainDispose () - result.Result - type UnfoldEnumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, activity:Activity<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, activity) diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index d16593c13e..d3c14c19da 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -102,20 +102,32 @@ namespace Microsoft.FSharp.Collections.SeqComposition new : list> -> AppendEnumerable<'T> override Append : ISeq<'T> -> ISeq<'T> + type internal ResizeArrayEnumerable<'T,'U> = + inherit SeqFactoryBase<'T,'U> + new : ResizeArray<'T> * ITransformFactory<'T,'U> * PipeIdx -> ResizeArrayEnumerable<'T,'U> + interface ISeq<'U> + type internal ThinResizeArrayEnumerable<'T> = - inherit EnumerableBase<'T> + inherit ResizeArrayEnumerable<'T,'T> new : ResizeArray<'T> -> ThinResizeArrayEnumerable<'T> - interface ISeq<'T> + + type internal ArrayEnumerable<'T,'U> = + inherit SeqFactoryBase<'T,'U> + new : array<'T> * ITransformFactory<'T,'U> * PipeIdx -> ArrayEnumerable<'T,'U> + interface ISeq<'U> type internal ThinArrayEnumerable<'T> = - inherit EnumerableBase<'T> + inherit ArrayEnumerable<'T, 'T> new : array<'T> -> ThinArrayEnumerable<'T> - interface ISeq<'T> + + type internal VanillaEnumerable<'T,'U> = + inherit SeqFactoryBase<'T,'U> + new : IEnumerable<'T> * ITransformFactory<'T,'U> * PipeIdx -> VanillaEnumerable<'T,'U> + interface ISeq<'U> type internal ThinEnumerable<'T> = - inherit EnumerableBase<'T> + inherit VanillaEnumerable<'T,'T> new : IEnumerable<'T> -> ThinEnumerable<'T> - interface ISeq<'T> type internal UnfoldEnumerable<'T,'U,'GeneratorState> = inherit SeqFactoryBase<'T,'U> From a38fb2245cec9595dd3d1751d54037c77af9cb0c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 7 May 2017 10:46:35 +1000 Subject: [PATCH 74/83] Added EnumerableBase.GetRaw --- src/fsharp/FSharp.Core/seqcore.fs | 8 ++++++++ src/fsharp/FSharp.Core/seqcore.fsi | 1 + 2 files changed, 9 insertions(+) diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index d9cc720a6d..73f0afcc92 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -310,9 +310,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract member Append : ISeq<'T> -> ISeq<'T> abstract member Length : unit -> int + abstract member GetRaw : unit -> seq<'T> default this.Append source = upcast (AppendEnumerable [source; this]) default this.Length () = length this + default this.GetRaw () = upcast this interface IEnumerable with member this.GetEnumerator () : IEnumerator = @@ -476,6 +478,11 @@ namespace Microsoft.FSharp.Collections.SeqComposition | :? EnumerableBase<'T> as s -> s.Length () | s -> 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 () @@ -563,6 +570,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition inherit ArrayEnumerable<'T,'T>(array, IdentityFactory.Instance, 0) override __.Length () = array.Length + override __.GetRaw () = upcast array type SingletonEnumerable<'T>(item:'T) = inherit EnumerableBase<'T>() diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index d3c14c19da..9d46a79317 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -73,6 +73,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition new : unit -> EnumerableBase<'T> abstract member Append : ISeq<'T> -> ISeq<'T> abstract member Length : unit -> int + abstract member GetRaw : unit -> seq<'T> interface ISeq<'T> [] From 3331b829c809f954c77323308446bc101defb60e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 7 May 2017 10:56:25 +1000 Subject: [PATCH 75/83] made EnumerableBase internal --- src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs | 8 -------- src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs | 8 -------- src/fsharp/FSharp.Core/seqcore.fsi | 4 ++-- tests/fsharpqa/Source/Misc/LongSourceFile01.fs | 8 -------- 4 files changed, 2 insertions(+), 26 deletions(-) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs index 4c1ce59d5f..8a2f5c230b 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs @@ -634,20 +634,12 @@ Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: System.Type G Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void .ctor() Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void ChainComplete(Int32) Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void ChainDispose() -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Int32 GetHashCode() -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Int32 Length() -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Append(Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: System.String ToString() -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: System.Type GetType() -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Void .ctor() 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+EnumerableBase`1[T] 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() diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs index 2f52c700e9..0912701012 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs @@ -621,20 +621,12 @@ Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: System.Type G Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void .ctor() Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void ChainComplete(Int32) Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void ChainDispose() -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Int32 GetHashCode() -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Int32 Length() -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Append(Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: System.String ToString() -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: System.Type GetType() -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Void .ctor() 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+EnumerableBase`1[T] 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() diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index 9d46a79317..b7a36f1fb4 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -69,7 +69,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition type NoValue = struct end [] - type EnumerableBase<'T> = + type internal EnumerableBase<'T> = new : unit -> EnumerableBase<'T> abstract member Append : ISeq<'T> -> ISeq<'T> abstract member Length : unit -> int @@ -77,7 +77,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface ISeq<'T> [] - type SeqFactoryBase<'T,'U> = + type internal SeqFactoryBase<'T,'U> = inherit EnumerableBase<'U> new : ITransformFactory<'T,'U> * PipeIdx -> SeqFactoryBase<'T,'U> diff --git a/tests/fsharpqa/Source/Misc/LongSourceFile01.fs b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs index 5484feda32..e805735744 100644 --- a/tests/fsharpqa/Source/Misc/LongSourceFile01.fs +++ b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs @@ -552,20 +552,12 @@ Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: System.Type G Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void .ctor() Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void ChainComplete(Int32) Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,TResult]: Void ChainDispose() -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Int32 GetHashCode() -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Int32 Length() -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Append(Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]) -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: System.String ToString() -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: System.Type GetType() -Microsoft.FSharp.Collections.SeqComposition.Core+EnumerableBase`1[T]: Void .ctor() 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+EnumerableBase`1[T] 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() From e51ce8b3b6002399df4edbef8941c0db1de966a3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 7 May 2017 11:54:48 +1000 Subject: [PATCH 76/83] Fix surface area --- .../FSharp.Core.Unittests/SurfaceArea.coreclr.fs | 10 +++------- src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs | 10 +++------- tests/fsharpqa/Source/Misc/LongSourceFile01.fs | 10 +++------- 3 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs index 8a2f5c230b..a6dca4658b 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs @@ -658,14 +658,9 @@ Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Void ChainDispo Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Void set_Result(TResult) Microsoft.FSharp.Collections.SeqComposition.IOutOfBand: Void ListenForStopFurtherProcessing(System.Action`1[System.Int32]) Microsoft.FSharp.Collections.SeqComposition.IOutOfBand: Void StopFurtherProcessing(Int32) -Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] PushTransform[TResult](Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]) +Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] PushTransform[TResult](Microsoft.FSharp.Collections.SeqComposition.ITransformFactory`2[T,TResult]) Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: TResult Fold[TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]]) -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Int32 GetHashCode() -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,V] Compose[V](Microsoft.FSharp.Collections.SeqComposition.IOutOfBand, Int32, Microsoft.FSharp.Collections.SeqComposition.Activity`2[TResult,V]) -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: System.String ToString() -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: System.Type GetType() -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.SeqComposition.ITransformFactory`2[T,TResult]: Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,V] Compose[V](Microsoft.FSharp.Collections.SeqComposition.IOutOfBand, Int32, Microsoft.FSharp.Collections.SeqComposition.Activity`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]) @@ -1126,6 +1121,7 @@ Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Int32 GetHash Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Int32 Length() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Append(Microsoft.FSharp.Collections.SeqComposition.ISeq`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/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs index 0912701012..b1f492245e 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs @@ -645,14 +645,9 @@ Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Void ChainDispo Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Void set_Result(TResult) Microsoft.FSharp.Collections.SeqComposition.IOutOfBand: Void ListenForStopFurtherProcessing(System.Action`1[System.Int32]) Microsoft.FSharp.Collections.SeqComposition.IOutOfBand: Void StopFurtherProcessing(Int32) -Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] PushTransform[TResult](Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]) +Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] PushTransform[TResult](Microsoft.FSharp.Collections.SeqComposition.ITransformFactory`2[T,TResult]) Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: TResult Fold[TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]]) -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Int32 GetHashCode() -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,V] Compose[V](Microsoft.FSharp.Collections.SeqComposition.IOutOfBand, Int32, Microsoft.FSharp.Collections.SeqComposition.Activity`2[TResult,V]) -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: System.String ToString() -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: System.Type GetType() -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.SeqComposition.ITransformFactory`2[T,TResult]: Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,V] Compose[V](Microsoft.FSharp.Collections.SeqComposition.IOutOfBand, Int32, Microsoft.FSharp.Collections.SeqComposition.Activity`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]) @@ -1160,6 +1155,7 @@ Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Int32 GetHash Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Int32 Length() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Append(Microsoft.FSharp.Collections.SeqComposition.ISeq`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/fsharpqa/Source/Misc/LongSourceFile01.fs b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs index e805735744..d35f290ee7 100644 --- a/tests/fsharpqa/Source/Misc/LongSourceFile01.fs +++ b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs @@ -576,14 +576,9 @@ Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Void ChainDispo Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]: Void set_Result(TResult) Microsoft.FSharp.Collections.SeqComposition.IOutOfBand: Void ListenForStopFurtherProcessing(System.Action`1[System.Int32]) Microsoft.FSharp.Collections.SeqComposition.IOutOfBand: Void StopFurtherProcessing(Int32) -Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] PushTransform[TResult](Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]) +Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[TResult] PushTransform[TResult](Microsoft.FSharp.Collections.SeqComposition.ITransformFactory`2[T,TResult]) Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T]: TResult Fold[TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Collections.SeqComposition.Folder`2[T,TResult]]) -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Boolean Equals(System.Object) -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Int32 GetHashCode() -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,V] Compose[V](Microsoft.FSharp.Collections.SeqComposition.IOutOfBand, Int32, Microsoft.FSharp.Collections.SeqComposition.Activity`2[TResult,V]) -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: System.String ToString() -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: System.Type GetType() -Microsoft.FSharp.Collections.SeqComposition.TransformFactory`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.SeqComposition.ITransformFactory`2[T,TResult]: Microsoft.FSharp.Collections.SeqComposition.Activity`2[T,V] Compose[V](Microsoft.FSharp.Collections.SeqComposition.IOutOfBand, Int32, Microsoft.FSharp.Collections.SeqComposition.Activity`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]) @@ -1033,6 +1028,7 @@ Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Int32 GetHash Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Int32 Length() Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1[T]: Microsoft.FSharp.Collections.SeqComposition.ISeq`1[T] Append(Microsoft.FSharp.Collections.SeqComposition.ISeq`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 From ffadb9f6556aeba8f971ebd53414f01894a69554 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 8 May 2017 19:37:26 +1000 Subject: [PATCH 77/83] Moved ISeq.length into Basics --- src/fsharp/FSharp.Core/iseq.fs | 2 +- src/fsharp/FSharp.Core/local.fs | 12 +++++++++++- src/fsharp/FSharp.Core/local.fsi | 5 ++++- src/fsharp/FSharp.Core/seqcore.fs | 11 ++--------- src/fsharp/FSharp.Core/seqcore.fsi | 2 -- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 494913a22a..9eba449081 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -952,7 +952,7 @@ namespace Microsoft.FSharp.Collections match source with | :? EnumerableBase<'T> as s -> s.Length () | :? list<'T> as l -> l.Length - | _ -> length source + | _ -> Microsoft.FSharp.Primitives.Basics.ISeq.length source [] let toArray (source:ISeq<'T>) = diff --git a/src/fsharp/FSharp.Core/local.fs b/src/fsharp/FSharp.Core/local.fs index 0e715835ce..08b59c7eaa 100644 --- a/src/fsharp/FSharp.Core/local.fs +++ b/src/fsharp/FSharp.Core/local.fs @@ -1165,4 +1165,14 @@ module internal Array = member this.GetEnumerator(): Collections.IEnumerator = (source:>System.Collections.IEnumerable).GetEnumerator () member this.GetEnumerator(): IEnumerator<'T> = - (source:>IEnumerable<'T>).GetEnumerator () } \ No newline at end of file + (source:>IEnumerable<'T>).GetEnumerator () } + +module internal ISeq = + open Microsoft.FSharp.Collections.SeqComposition + + let length (source:ISeq<_>) = + source.Fold (fun _ -> + { new Folder<'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 f197b712ac..4df794ac9e 100644 --- a/src/fsharp/FSharp.Core/local.fsi +++ b/src/fsharp/FSharp.Core/local.fsi @@ -87,4 +87,7 @@ module internal Array = val stableSortInPlaceWith: comparer:('T -> 'T -> int) -> array:'T[] -> unit val stableSortInPlace: array:'T[] -> unit when 'T : comparison val ofSeq : seq<'T> -> array<'T> - val toSeq : array<'T> -> seq<'T> \ No newline at end of file + val toSeq : array<'T> -> seq<'T> + +module internal ISeq = + val length : ISeq<'T> -> int \ No newline at end of file diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index 73f0afcc92..d009e36be8 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -296,13 +296,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition finally activity.ChainDispose () - let length (source:ISeq<_>) = - source.Fold (fun _ -> - { new Folder<'T,int>(0) with - override this.ProcessNext v = - this.Result <- this.Result + 1 - Unchecked.defaultof<_> (* return value unused in Fold context *) }) - [] type EnumerableBase<'T> () = let derivedClassShouldImplement () = @@ -313,7 +306,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract member GetRaw : unit -> seq<'T> default this.Append source = upcast (AppendEnumerable [source; this]) - default this.Length () = length this + default this.Length () = Microsoft.FSharp.Primitives.Basics.ISeq.length this default this.GetRaw () = upcast this interface IEnumerable with @@ -476,7 +469,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition override __.Length () = match delayed() with | :? EnumerableBase<'T> as s -> s.Length () - | s -> length s + | s -> Microsoft.FSharp.Primitives.Basics.ISeq.length s override __.GetRaw () = match delayed() with diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index b7a36f1fb4..15f31f5e33 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -91,8 +91,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition // and it can only do it at the start of a sequence abstract CanSkip : unit -> bool - val internal length : ISeq<'T> -> int - type internal ThinConcatEnumerable<'T, 'Sources, 'Collection when 'Collection :> ISeq<'T>> = inherit EnumerableBase<'T> new : 'Sources * ('Sources->ISeq<'Collection>) -> ThinConcatEnumerable<'T, 'Sources, 'Collection> From c4f8b436422d4c23654cc050d91d46982732e098 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 8 May 2017 19:46:27 +1000 Subject: [PATCH 78/83] Added ISeq support in Array.ofSeq --- src/fsharp/FSharp.Core/local.fs | 85 +++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src/fsharp/FSharp.Core/local.fs b/src/fsharp/FSharp.Core/local.fs index 08b59c7eaa..ddaa2a82e2 100644 --- a/src/fsharp/FSharp.Core/local.fs +++ b/src/fsharp/FSharp.Core/local.fs @@ -949,6 +949,75 @@ module internal List = module internal Array = open System + open System.Collections.Generic + open Microsoft.FSharp.Collections.SeqComposition + +#if FX_NO_ARRAY_KEY_SORT + // Mimic behavior of BCL QSort routine, used under the hood by various array sorting APIs + let qsort<'Key,'Value>(keys : 'Key[], values : 'Value[], start : int, last : int, comparer : IComparer<'Key>) = + let valuesExist = + match values with + | null -> false + | _ -> true + + let swap (p1, p2) = + let tk = keys.[p1] + keys.[p1] <- keys.[p2] + keys.[p2] <- tk + if valuesExist then + let tv = values.[p1] + values.[p1] <- values.[p2] + values.[p2] <- tv + + let partition (left, right, pivot) = + let value = keys.[pivot] + swap (pivot, right) + let mutable store = left + + for i in left..(right - 1) do + if comparer.Compare(keys.[i],value) < 0 then + swap(i, store) + store <- store + 1 + + swap (store, right) + store + + let rec qs (left, right) = + if left < right then + let pivot = left + (right-left)/2 + let newpivot = partition(left,right,pivot) + qs(left,newpivot - 1) + qs(newpivot+1,right) + + qs(start, last) + + type System.Array with + static member Sort<'Key,'Value>(keys : 'Key[], values : 'Value[], comparer : IComparer<'Key>) = + let valuesExist = + match values with + | null -> false + | _ -> true + match keys,values with + | null,_ -> raise (ArgumentNullException()) + | _,_ when valuesExist && (keys.Length <> values.Length) -> raise (ArgumentException()) + | _,_ -> qsort(keys, values, 0, keys.Length-1, comparer) + + static member Sort<'Key,'Value when 'Key : comparison>(keys : 'Key[], values : 'Value[]) = + let valuesExist = + match values with + | null -> false + | _ -> true + match keys,values with + | null,_ -> raise (ArgumentNullException()) + | _,_ when valuesExist && (keys.Length <> values.Length) -> raise (ArgumentException()) + | _,_ -> qsort(keys,values,0,keys.Length-1,LanguagePrimitives.FastGenericComparer<'Key>) + + static member Sort<'Key,'Value>(keys : 'Key[], values : 'Value[], start : int, length : int, comparer : IComparer<'Key>) = + match keys with + | null -> raise (ArgumentNullException()) + | _ -> qsort(keys,values,start,start+length-1,comparer) +#else +#endif let inline fastComparerForArraySort<'t when 't : comparison> () = LanguagePrimitives.FastGenericComparerCanBeNull<'t> @@ -1146,6 +1215,21 @@ module internal Array = startIndex := !startIndex + minChunkSize res + type FoldToArray<'T> () = + inherit Folder<'T, array<'T>>(Unchecked.defaultof<_>) + + let mutable tmp = ResizeArray () + + override this.ProcessNext input = + tmp.Add input + true (* result unused in fold *) + + override this.ChainComplete _ = + this.Result <- tmp.ToArray () + + let ofISeq (s : ISeq<'T>) = + s.Fold (fun _ -> upcast FoldToArray()) + let ofSeq (source : seq<'T>) = match source with | :? ('T[]) as res -> (res.Clone() :?> 'T[]) @@ -1156,6 +1240,7 @@ module internal Array = let arr = zeroCreateUnchecked res.Count res.CopyTo(arr, 0) arr + | :? ISeq<'T> as s -> ofISeq s | _ -> let res = ResizeArray source res.ToArray() From eb5299f725e4889607141b5ff02d1a21eb5aabe1 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 8 May 2017 19:46:46 +1000 Subject: [PATCH 79/83] Added IReadOnlyCollection to Array.ofSeq --- src/fsharp/FSharp.Core/local.fs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/fsharp/FSharp.Core/local.fs b/src/fsharp/FSharp.Core/local.fs index ddaa2a82e2..b05c7ece85 100644 --- a/src/fsharp/FSharp.Core/local.fs +++ b/src/fsharp/FSharp.Core/local.fs @@ -1241,6 +1241,15 @@ module internal Array = res.CopyTo(arr, 0) arr | :? ISeq<'T> as s -> ofISeq s +#if !FSCORE_PORTABLE_OLD + | :? 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 +#endif | _ -> let res = ResizeArray source res.ToArray() From 3fd12433bc849f91755325021a1ae03227adbe20 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 13 May 2017 17:51:46 +1000 Subject: [PATCH 80/83] Merged EnumeratorBase and Result --- src/fsharp/FSharp.Core/seqcore.fs | 380 +++++++++++++++++------------- 1 file changed, 217 insertions(+), 163 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index d009e36be8..c82318f3f9 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -186,15 +186,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition | NotStarted = 1 | Finished = 2 - type Result<'T>() = - inherit Folder<'T,'T>(Unchecked.defaultof<'T>) - - member val SeqState = SeqProcessNextStates.NotStarted with get, set - - override this.ProcessNext (input:'T) : bool = - this.Result <- input - true - type EmptyEnumerator<'T>() = let current () = failwith "library implementation error: Current should never be called" @@ -213,89 +204,6 @@ namespace Microsoft.FSharp.Collections.SeqComposition static let element : IEnumerator<'T> = upcast (new EmptyEnumerator<'T> ()) static member Element = element - [] - type EnumeratorBase<'T>(result:Result<'T>, activity:Activity) = - interface IDisposable with - member __.Dispose () : unit = - 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 __.Current = - if result.SeqState = SeqProcessNextStates.InProcess then result.Result - else - match result.SeqState with - | SeqProcessNextStates.NotStarted -> notStarted() - | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> failwith "library implementation error: all states should have been handled" - - type VanillaEnumerator<'T,'U>(source:IEnumerator<'T>, activity:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, activity) - - let rec moveNext () = - if (result.HaltedIdx = 0) && source.MoveNext () then - if activity.ProcessNext source.Current then - true - else - moveNext () - else - result.SeqState <- SeqProcessNextStates.Finished - activity.ChainComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () - - interface IDisposable with - member __.Dispose () = - try - source.Dispose () - finally - activity.ChainDispose () - - type ConcatEnumerator<'T,'U,'Collection when 'Collection :> IEnumerable<'T>> (sources:IEnumerable<'Collection>, activity:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, activity) - - let main = sources.GetEnumerator () - - let mutable active = EmptyEnumerators.Element - - let rec moveNext () = - if result.HaltedIdx <> 0 then false - else - if active.MoveNext () then - if activity.ProcessNext active.Current then - true - else - moveNext () - elif main.MoveNext () then - active.Dispose () - active <- main.Current.GetEnumerator () - moveNext () - else - result.SeqState <- SeqProcessNextStates.Finished - activity.ChainComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () - - interface IDisposable with - member __.Dispose () = - try - main.Dispose () - active.Dispose () - finally - activity.ChainDispose () - [] type EnumerableBase<'T> () = let derivedClassShouldImplement () = @@ -336,14 +244,78 @@ namespace Microsoft.FSharp.Collections.SeqComposition member __.Compose next = ComposedFactory.Combine transformFactory next member __.PipeIdx = pipeIdx + + and [] EnumeratorBase<'T>() = + inherit Folder<'T,'T>(Unchecked.defaultof<'T>) + + member val SeqState = SeqProcessNextStates.NotStarted with get, set + abstract Activity : Activity + + 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 __.FinaliseConstruct(activity':Activity<'T,'U>) = + activity <- activity' + + override this.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 Construct (source:IEnumerator<'T>) (factory:SeqFactoryBase<'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>, transformFactory:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcast (new VanillaEnumerator<'T,'U>(enumerable.GetEnumerator(), this.CreateActivityPipeline result, result)) + member this.GetEnumerator () = VanillaEnumerator<'T,'U>.Construct (enumerable.GetEnumerator()) this interface ISeq<'U> with member this.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = @@ -395,13 +367,58 @@ namespace Microsoft.FSharp.Collections.SeqComposition 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 this.Activity = upcast activity + + member __.FinaliseConstruct(activity':Activity<'T,'U>) = + activity <- activity' + + 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 Construct (sources:IEnumerable<'Collection>) (factory:SeqFactoryBase<'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 :> ISeq<'T>> (sources:ISeq<'Collection>, transformFactory:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcast (new ConcatEnumerator<'T,'U,'Collection>(sources, this.CreateActivityPipeline result, result)) + member this.GetEnumerator () = ConcatEnumerator<'T,'U,'Collection>.Construct sources this interface ISeq<'U> with member this.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = @@ -427,18 +444,17 @@ namespace Microsoft.FSharp.Collections.SeqComposition and ThinConcatEnumerable<'T, 'Sources, 'Collection when 'Collection :> ISeq<'T>> (sources:'Sources, preEnumerate:'Sources->ISeq<'Collection>) = inherit EnumerableBase<'T>() + member private __.Fatten : ISeq<'T> = upcast (ConcatEnumerable<'T,'T,'Collection>(preEnumerate sources, IdentityFactory.Instance, 1)) + interface IEnumerable<'T> with - member this.GetEnumerator () : IEnumerator<'T> = - let result = Result<'T> () - upcast (new ConcatEnumerator<'T,'T,'Collection> (preEnumerate sources, result, result)) + member this.GetEnumerator () = this.Fatten.GetEnumerator () interface ISeq<'T> with member this.PushTransform (next:ITransformFactory<'T,'U>) : ISeq<'U> = upcast (ConcatEnumerable<'T,'V,'Collection>(preEnumerate sources, next, 1)) member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = - let fat : ISeq<'T> = upcast (ConcatEnumerable<'T,'T,'Collection>(preEnumerate sources, IdentityFactory.Instance, 1)) - fat.Fold createFolder + this.Fatten.Fold createFolder and AppendEnumerable<'T> (sources:list>) = inherit ThinConcatEnumerable<'T, list>, ISeq<'T>>(sources, fun sources -> upcast (List.rev sources)) @@ -511,35 +527,44 @@ namespace Microsoft.FSharp.Collections.SeqComposition result.ChainDispose () result.Result - type ArrayEnumerator<'T,'U>(array:array<'T>, activity:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, activity) + type ArrayEnumerator<'T,'U> private (array:array<'T>) = + inherit EnumeratorBase<'U>() let mutable idx = 0 + let mutable activity = Unchecked.defaultof> + + member __.FinaliseConstruct(activity':Activity<'T,'U>) = + activity <- activity' + + override this.Activity = upcast activity - let rec moveNext () = - if (result.HaltedIdx = 0) && idx < array.Length then + member private this.MoveNext () = + if this.HaltedIdx = 0 && idx < array.Length then idx <- idx+1 if activity.ProcessNext array.[idx-1] then true else - moveNext () + this.MoveNext () else - result.SeqState <- SeqProcessNextStates.Finished - activity.ChainComplete result.HaltedIdx + this.SeqState <- SeqProcessNextStates.Finished + activity.ChainComplete this.HaltedIdx false interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () + member this.MoveNext () = + this.SeqState <- SeqProcessNextStates.InProcess + this.MoveNext () + + static member Construct (array:array<'T>) (factory:SeqFactoryBase<'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>, transformFactory:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcast (new ArrayEnumerator<'T,'U>(array, this.CreateActivityPipeline result, result)) + member this.GetEnumerator () = ArrayEnumerator<'T,'U>.Construct array this interface ISeq<'U> with member this.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = @@ -588,35 +613,44 @@ namespace Microsoft.FSharp.Collections.SeqComposition result.ChainDispose () result.Result - type ResizeArrayEnumerator<'T,'U>(array:ResizeArray<'T>, activity:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, activity) + type ResizeArrayEnumerator<'T,'U> private (array:ResizeArray<'T>) = + inherit EnumeratorBase<'U>() let mutable idx = 0 + let mutable activity = Unchecked.defaultof> + + member __.FinaliseConstruct(activity':Activity<'T,'U>) = + activity <- activity' - let rec moveNext () = - if (result.HaltedIdx = 0) && idx < array.Count then + override this.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 - moveNext () + this.MoveNext () else - result.SeqState <- SeqProcessNextStates.Finished - activity.ChainComplete result.HaltedIdx + this.SeqState <- SeqProcessNextStates.Finished + activity.ChainComplete this.HaltedIdx false interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () + member this.MoveNext () = + this.SeqState <- SeqProcessNextStates.InProcess + this.MoveNext () + + static member Construct (array:ResizeArray<'T>) (factory:SeqFactoryBase<'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>, transformFactory:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcast (new ResizeArrayEnumerator<'T,'U>(resizeArray, this.CreateActivityPipeline result, result)) + member this.GetEnumerator () = ResizeArrayEnumerator<'T,'U>.Construct resizeArray this interface ISeq<'U> with member this.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = @@ -641,13 +675,20 @@ namespace Microsoft.FSharp.Collections.SeqComposition override __.Length () = resizeArray.Count - type UnfoldEnumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, activity:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, activity) + type UnfoldEnumerator<'T,'U,'State> private (generator:'State->option<'T*'State>, state:'State) = + inherit EnumeratorBase<'U>() let mutable current = state - let rec moveNext () = - if result.HaltedIdx <> 0 then + let mutable activity = Unchecked.defaultof> + + member __.FinaliseConstruct(activity':Activity<'T,'U>) = + activity <- activity' + + override this.Activity = upcast activity + + member private this.MoveNext () = + if this.HaltedIdx <> 0 then false else match generator current with @@ -656,21 +697,24 @@ namespace Microsoft.FSharp.Collections.SeqComposition if activity.ProcessNext item then true else - moveNext () + this.MoveNext () | _ -> false interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () + member this.MoveNext () = + this.SeqState <- SeqProcessNextStates.InProcess + this.MoveNext () + + static member Construct (generator:'State->option<'T*'State>) (state:'State) (factory:SeqFactoryBase<'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, transformFactory:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcast (new UnfoldEnumerator<'T,'U,'GeneratorState>(generator, state, this.CreateActivityPipeline result, result)) + member this.GetEnumerator () = UnfoldEnumerator<'T,'U,'GeneratorState>.Construct generator state this interface ISeq<'U> with member this.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = @@ -703,13 +747,8 @@ namespace Microsoft.FSharp.Collections.SeqComposition else System.Int32.MaxValue - type InitEnumerator<'T,'U>(count:Nullable, f:int->'T, activity:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, activity) - - let isSkipping = - match box activity with - | :? ISkipable as skip -> skip.CanSkip - | _ -> fun () -> false + type InitEnumerator<'T,'U>(count:Nullable, f:int->'T) = + inherit EnumeratorBase<'U>() let terminatingIdx = getInitTerminatingIdx count @@ -717,8 +756,22 @@ namespace Microsoft.FSharp.Collections.SeqComposition let mutable maybeSkipping = true let mutable idx = -1 - let rec moveNext () = - if result.HaltedIdx = 0 && idx < terminatingIdx then + let mutable activity = Unchecked.defaultof> + let mutable isSkipping = Unchecked.defaultofbool> + + member __.FinaliseConstruct(activity':Activity<'T,'U>) = + activity <- activity' + + isSkipping <- + match box activity with + | :? ISkipable as skip -> skip.CanSkip + | _ -> fun () -> false + + + override this.Activity = upcast activity + + member private this.MoveNext () = + if this.HaltedIdx = 0 && idx < terminatingIdx then idx <- idx + 1 if maybeSkipping then @@ -727,30 +780,33 @@ namespace Microsoft.FSharp.Collections.SeqComposition maybeSkipping <- isSkipping () if maybeSkipping then - moveNext () + this.MoveNext () elif activity.ProcessNext (f idx) then true else - moveNext () - elif result.HaltedIdx = 0 && idx = System.Int32.MaxValue then + this.MoveNext () + elif this.HaltedIdx = 0 && idx = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else - result.SeqState <- SeqProcessNextStates.Finished - activity.ChainComplete result.HaltedIdx + this.SeqState <- SeqProcessNextStates.Finished + activity.ChainComplete this.HaltedIdx false interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () + member this.MoveNext () = + this.SeqState <- SeqProcessNextStates.InProcess + this.MoveNext () + + static member Construct (count:Nullable) (f:int->'T) (factory:SeqFactoryBase<'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, transformFactory:ITransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcast (new InitEnumerator<'T,'U>(count, f, this.CreateActivityPipeline result, result)) + member this.GetEnumerator () = InitEnumerator<'T,'U>.Construct count f this interface ISeq<'U> with member this.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = @@ -1189,9 +1245,7 @@ namespace Microsoft.FSharp.Core.CompilerServices inherit SeqFactoryBase<'T,'U>(transformFactory, pipeIdx) interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcast (new VanillaEnumerator<'T,'U>(generatedSequence.GetFreshEnumerator(), this.CreateActivityPipeline result, result)) + member this.GetEnumerator () = VanillaEnumerator<'T,'U>.Construct (generatedSequence.GetFreshEnumerator()) this interface ISeq<'U> with member this.PushTransform (next:ITransformFactory<'U,'V>) : ISeq<'V> = From 09e3c98e242b955982314f72696e32b56986d3fc Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 13 May 2017 17:55:23 +1000 Subject: [PATCH 81/83] Use list for small ISeqs --- src/fsharp/FSharp.Core/iseq.fs | 2 +- src/fsharp/FSharp.Core/seqcore.fs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 9eba449081..1ae5fbf7fe 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -602,7 +602,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext (input:'T) : bool = this.State <- folder this.State input TailCall.avoid (next.ProcessNext this.State) } } - concat (ofSeq [| head ; tail |]) + concat (ofList [ head ; tail ]) [] let skip (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index c82318f3f9..0a488d806f 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -600,7 +600,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition interface ISeq<'T> with member __.PushTransform (next:ITransformFactory<'T,'U>) : ISeq<'U> = - upcast (new ArrayEnumerable<'T,'U>([|item|], next, 1)) + ([item] :> ISeq<'T>).PushTransform next member this.Fold<'Result> (createFolder:PipeIdx->Folder<'T,'Result>) = let result = createFolder 1 From f0100854e415a57d854c43735c9e19925b2d3d77 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 15 May 2017 19:08:55 +1000 Subject: [PATCH 82/83] Thin direct calls to IEnumerable.GetEnumerator --- src/fsharp/FSharp.Core/seqcore.fs | 6 ++++++ src/fsharp/FSharp.Core/seqcore.fsi | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index 0a488d806f..b9e94bee75 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -479,6 +479,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition count <- count + 1 count + interface IEnumerable<'T> with + member __.GetEnumerator () = enumerable.GetEnumerator () + type DelayedEnumerable<'T>(delayed:unit->ISeq<'T>, pipeIdx:PipeIdx) = inherit EnumerableBase<'T>() @@ -590,6 +593,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition 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>() diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index 15f31f5e33..646ab782ce 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -118,6 +118,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition type internal ThinArrayEnumerable<'T> = inherit ArrayEnumerable<'T, 'T> new : array<'T> -> ThinArrayEnumerable<'T> + interface IEnumerable<'T> type internal VanillaEnumerable<'T,'U> = inherit SeqFactoryBase<'T,'U> @@ -127,6 +128,7 @@ namespace Microsoft.FSharp.Collections.SeqComposition type internal ThinEnumerable<'T> = inherit VanillaEnumerable<'T,'T> new : IEnumerable<'T> -> ThinEnumerable<'T> + interface IEnumerable<'T> type internal UnfoldEnumerable<'T,'U,'GeneratorState> = inherit SeqFactoryBase<'T,'U> From ded9bb71682328b92a22f765471c2c72d59f118f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 18 May 2017 19:12:01 +1000 Subject: [PATCH 83/83] Provided an optimized GetEnumerator for scan --- src/fsharp/FSharp.Core/iseq.fs | 96 ++++++++++++++++++++++++++---- src/fsharp/FSharp.Core/iseq.fsi | 2 +- src/fsharp/FSharp.Core/seqcore.fsi | 3 + 3 files changed, 90 insertions(+), 11 deletions(-) diff --git a/src/fsharp/FSharp.Core/iseq.fs b/src/fsharp/FSharp.Core/iseq.fs index 1ae5fbf7fe..92dc11b277 100644 --- a/src/fsharp/FSharp.Core/iseq.fs +++ b/src/fsharp/FSharp.Core/iseq.fs @@ -108,6 +108,20 @@ namespace Microsoft.FSharp.Collections member __.GetHashCode o = c.GetHashCode o._1 member __.Equals (lhs,rhs) = c.Equals (lhs._1, rhs._1) } + [] + type PreferGetEnumerator<'T>() = + inherit EnumerableBase<'T>() + + abstract GetEnumerator: unit -> IEnumerator<'T> + abstract GetSeq : unit -> ISeq<'T> + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = this.GetEnumerator () + + interface ISeq<'T> with + member this.PushTransform<'U> (next:ITransformFactory<'T,'U>) : ISeq<'U> = (this.GetSeq()).PushTransform next + member this.Fold<'Result> (f:PipeIdx->Folder<'T,'Result>) : 'Result = (this.GetSeq()).Fold f + [] let empty<'T> = Microsoft.FSharp.Collections.SeqComposition.Core.EmptyEnumerable<'T>.Instance @@ -592,17 +606,79 @@ namespace Microsoft.FSharp.Collections let concat (sources:ISeq<#ISeq<'T>>) : ISeq<'T> = upcast (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 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 inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = - let head = singleton initialState - let tail = - source.PushTransform { new ITransformFactory<'T,'State> with - override __.Compose _ _ next = - upcast { new Transform<'T,'V,'State>(next, initialState) with - override this.ProcessNext (input:'T) : bool = - this.State <- folder this.State input - TailCall.avoid (next.ProcessNext this.State) } } - concat (ofList [ head ; tail ]) + let scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) : ISeq<'State> = + upcast { new PreferGetEnumerator<'State>() with + member this.GetEnumerator () = + upcast new ScanEnumerator<'T,'State>(folder, initialState, source) + + member this.GetSeq () = + let head = singleton initialState + let tail = + source.PushTransform { new ITransformFactory<'T,'State> with + override __.Compose _ _ next = + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + upcast { new Transform<'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 skip (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = diff --git a/src/fsharp/FSharp.Core/iseq.fsi b/src/fsharp/FSharp.Core/iseq.fsi index 98160503b9..0c78d1e567 100644 --- a/src/fsharp/FSharp.Core/iseq.fsi +++ b/src/fsharp/FSharp.Core/iseq.fsi @@ -217,7 +217,7 @@ namespace Microsoft.FSharp.Collections val inline reduce : f:('T->'T->'T) -> source:ISeq<'T> -> 'T [] - val inline scan : folder:('State->'T->'State) -> initialState:'State -> source:ISeq<'T> -> ISeq<'State> + val scan : folder:('State->'T->'State) -> initialState:'State -> source:ISeq<'T> -> ISeq<'State> [] val skip : skipCount:int -> source:ISeq<'T> -> ISeq<'T> diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index 646ab782ce..ec6ef0f288 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -74,6 +74,9 @@ namespace Microsoft.FSharp.Collections.SeqComposition abstract member Append : ISeq<'T> -> ISeq<'T> abstract member Length : unit -> int abstract member GetRaw : unit -> seq<'T> + default Append : ISeq<'T> -> ISeq<'T> + default Length : unit -> int + default GetRaw : unit -> seq<'T> interface ISeq<'T> []