From 5ec5c9658ab899eae86483439a83dda52507cbc6 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 28 Sep 2016 19:42:15 +1000 Subject: [PATCH 001/286] Basis of SeqComposer - Removed all dynamic casting - Split enumerable/enumerator - Implementations of map, filter, skip, pairwise --- src/fsharp/FSharp.Core/seq.fs | 266 ++++++++++++++++++++++++++++------ 1 file changed, 223 insertions(+), 43 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ca062b62d2a..45f7817a3ad 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -22,6 +22,215 @@ namespace Microsoft.FSharp.Collections let check started = if not started then notStarted() let dispose (r : System.IDisposable) = r.Dispose() + module SeqComposer = + module Helpers = + // used for performance reasons; these are not recursive calls, so should be safe + let inline avoidTailCall x = + match x with + | true -> true + | false -> false + + type Factory = + static member Filter f g = Filter (fun x -> f x && g x) + static member Map f g = Map (f >> g) + + and [] SeqComponent<'T,'U> () = + abstract ProcessNext : 'T * byref<'U> -> bool + + abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V> + + abstract ComposeMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U> + abstract ComposeFilter : Filter<'T> -> SeqComponent<'T,'U> + abstract ComposeFilterMap<'S> : FilterMap<'S,'T> -> SeqComponent<'S,'U> + abstract ComposeMapFilter<'S> : MapFilter<'S,'T> -> SeqComponent<'S,'U> + + override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second) + + default second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) + default second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second) + default second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) + default second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) + + and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) = + inherit SeqComponent<'T,'V>() + + override __.ProcessNext (input:'T, output:byref<'V>) :bool = + let mutable temp = Unchecked.defaultof<'U> + if first.ProcessNext (input, &temp) then + Helpers.avoidTailCall (second.ProcessNext (temp, &output)) + else + false + + override __.Composer (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = + upcast Composed (first, second.Composer next) + + member __.First = first + member __.Second = second + + and Map<'T,'U> (map:'T->'U) = + inherit SeqComponent<'T,'U>() + + override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = + second.ComposeMap first + + override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = + upcast Factory.Map first.Map second.Map + + override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = + upcast FilterMap (first, second) + + override second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = + upcast FilterMap (first.Filter, Factory.Map first.Map.Map second.Map) + + override __.ProcessNext (input:'T, output:byref<'U>) : bool = + output <- map input + true + + member __.Map :'T->'U = map + + and Filter<'T> (filter:'T->bool) = + inherit SeqComponent<'T,'T>() + + override this.Composer (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = + next.ComposeFilter this + + override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> = + upcast MapFilter (first, second) + + override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'T> = + upcast Factory.Filter first.Filter second.Filter + + override second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'T> = + upcast MapFilter(first.Map, Factory.Filter first.Filter.Filter second.Filter) + + override __.ProcessNext (input:'T, output:byref<'T>) : bool = + if filter input then + output <- input + true + else + false + + member __.Filter :'T->bool = filter + + and MapFilter<'T,'U> (map:Map<'T,'U>, filter:Filter<'U>) = + inherit SeqComponent<'T,'U>() + + override __.ProcessNext (input:'T, output:byref<'U>) :bool = + output <- map.Map input + Helpers.avoidTailCall (filter.Filter output) + + override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> = + second.ComposeMapFilter first + + member __.Map : Map<'T,'U> = map + member __.Filter : Filter<'U> = filter + + and FilterMap<'T,'U> (filter:Filter<'T>, map:Map<'T,'U>) = + inherit SeqComponent<'T,'U>() + + override __.ProcessNext (input:'T, output:byref<'U>) : bool = + if filter.Filter input then + output <- map.Map input + true + else + false + + override this.Composer (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.ComposeFilterMap this + + member __.Filter : Filter<'T> = filter + member __.Map : Map<'T,'U> = map + + and Pairwise<'T> () = + inherit SeqComponent<'T,'T*'T>() + + let mutable isFirst = true + let mutable lastValue = Unchecked.defaultof<'T> + + override __.ProcessNext (input:'T, output:byref<'T*'T>) : bool = + if isFirst then + lastValue <- input + isFirst <- false + false + else + output <- lastValue, input + lastValue <- input + true + + and Skip<'T> (skipCount:int) = + inherit SeqComponent<'T,'T>() + + let mutable count = 0 + + override __.ProcessNext (input:'T, output:byref<'T>) : bool = + if count < skipCount then + count <- count + 1 + false + else + output <- input + true + + type SeqProcessNextStates = + | NotStarted = 1 + | Finished = 2 + | InProcess = 3 + + type SeqEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) = + let mutable source = enumerator + let mutable state = SeqProcessNextStates.NotStarted + let mutable current = Unchecked.defaultof<_> + + let rec moveNext () = + if source.MoveNext () then + if t2u.ProcessNext (source.Current, ¤t) then + true + else + moveNext () + else + state <- SeqProcessNextStates.Finished + false + + interface IDisposable with + member x.Dispose():unit = + match source with + | null -> () + | _ -> + source.Dispose () + source <- Unchecked.defaultof<_> + + interface IEnumerator with + member this.Current : obj = box (this:>IEnumerator<'U>).Current + member __.MoveNext () = + state <- SeqProcessNextStates.InProcess + moveNext () + member __.Reset () : unit = noReset () + + interface IEnumerator<'U> with + member x.Current = + match state with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> () + current + + [] + type SeqEnumerableBase<'T> () = + abstract member Compose<'U> : SeqComponent<'T,'U> -> IEnumerable<'U> + + type SeqEnumerable<'T,'U>(generator:IEnumerable<'T>, t2u:SeqComponent<'T,'U>) = + inherit SeqEnumerableBase<'U>() + + let getEnumerator () : IEnumerator<'U> = + upcast (new SeqEnumerator<'T,'U>(generator.GetEnumerator(), t2u)) + + interface IEnumerable with + member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ()) + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = getEnumerator () + + override __.Compose (u2v:SeqComponent<'U,'V>) = + new SeqEnumerable<'T,'V>(generator, t2u.Composer u2v) :> IEnumerable<'V> + let cast (e : IEnumerator) : IEnumerator<'T> = { new IEnumerator<'T> with member x.Current = unbox<'T> e.Current @@ -109,18 +318,6 @@ namespace Microsoft.FSharp.Collections interface System.IDisposable with member this.Dispose() = this.Dispose() - let map f (e : IEnumerator<_>) : IEnumerator<_>= - upcast - { new MapEnumerator<_>() with - member this.DoMoveNext (curr : byref<_>) = - if e.MoveNext() then - curr <- (f e.Current) - true - else - false - member this.Dispose() = e.Dispose() - } - let mapi f (e : IEnumerator<_>) : IEnumerator<_> = let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) let i = ref (-1) @@ -216,23 +413,6 @@ namespace Microsoft.FSharp.Collections interface System.IDisposable with member x.Dispose() = e.Dispose() } - let filter f (e : IEnumerator<'T>) = - let started = ref false - let this = - { new IEnumerator<'T> with - member x.Current = check !started; e.Current - interface IEnumerator with - member x.Current = check !started; box e.Current - member x.MoveNext() = - let rec next() = - if not !started then started := true - e.MoveNext() && (f e.Current || next()) - next() - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = e.Dispose() } - this - let unfold f x : IEnumerator<_> = let state = ref x upcast @@ -964,17 +1144,21 @@ namespace Microsoft.FSharp.Collections mkSeq (fun () -> f (ie1.GetEnumerator()) (source2.GetEnumerator()) (source3.GetEnumerator())) [] - let filter f source = + let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = checkNonNull "source" source - revamp (IEnumerator.filter f) source + match source with + | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Filter f) + | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Filter f)) [] - let where f source = filter f source + let where f source = filter f source [] - let map f source = + let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> = checkNonNull "source" source - revamp (IEnumerator.map f) source + match source with + | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Map f) + | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Map f)) [] let mapi f source = @@ -1252,15 +1436,11 @@ namespace Microsoft.FSharp.Collections yield ie.Current } [] - let pairwise (source: seq<'T>) = - checkNonNull "source" source - seq { use ie = source.GetEnumerator() - if ie.MoveNext() then - let iref = ref ie.Current - while ie.MoveNext() do - let j = ie.Current - yield (!iref, j) - iref := j } + let pairwise<'T> (source:seq<'T>) : seq<'T*'T> = + checkNonNull "source" source + match source with + | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Pairwise ()) + | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Pairwise ())) [] let scan<'T,'State> f (z:'State) (source : seq<'T>) = From c74e97f0e1647c2567651729dde6636e33c2110d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Sep 2016 16:05:23 +1000 Subject: [PATCH 002/286] Fixed output due to change in Seq.map --- .../analyses/tailcalls.NoNeedToTailcall.output.test.bsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl index 5f4e677efc6..785a337a2f4 100644 --- a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl +++ b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl @@ -38,7 +38,7 @@ value simpleLibraryCall6 at line 60 does not make a critical tailcall value simpleLibraryCall7 at line 61 does not make a critical tailcall value simpleLibraryCall8 at line 62 does not make a critical tailcall value simpleLibraryCall9 at line 63 does not make a critical tailcall -value simpleLibraryCall10 at line 65 does not make a critical tailcall +value simpleLibraryCall10 at line 65 may make a critical tailcall value simpleLibraryCall11 at line 66 does not make a critical tailcall value simpleLibraryCall12 at line 67 does not make a critical tailcall value simpleLibraryCall13 at line 68 does not make a critical tailcall From 515231df18a5c17f878ae92d0b0e6c02d1c3d317 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Sep 2016 18:05:20 +1000 Subject: [PATCH 003/286] delayed component creation to respect mutability - Added take, mapi - Added same exceptions for skip & take - Added composable skip & take - Added array source - Added source specific folding for functions like sum (required growing of surface area, so currently not exposed) --- src/fsharp/FSharp.Core/seq.fs | 644 +++++++++++++++++++++------------- 1 file changed, 405 insertions(+), 239 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 45f7817a3ad..ba17f59305e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -15,222 +15,12 @@ namespace Microsoft.FSharp.Collections module IEnumerator = - let noReset() = raise (new System.NotSupportedException(SR.GetString(SR.resetNotSupported))) let notStarted() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationNotStarted))) let alreadyFinished() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationAlreadyFinished))) let check started = if not started then notStarted() let dispose (r : System.IDisposable) = r.Dispose() - module SeqComposer = - module Helpers = - // used for performance reasons; these are not recursive calls, so should be safe - let inline avoidTailCall x = - match x with - | true -> true - | false -> false - - type Factory = - static member Filter f g = Filter (fun x -> f x && g x) - static member Map f g = Map (f >> g) - - and [] SeqComponent<'T,'U> () = - abstract ProcessNext : 'T * byref<'U> -> bool - - abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V> - - abstract ComposeMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U> - abstract ComposeFilter : Filter<'T> -> SeqComponent<'T,'U> - abstract ComposeFilterMap<'S> : FilterMap<'S,'T> -> SeqComponent<'S,'U> - abstract ComposeMapFilter<'S> : MapFilter<'S,'T> -> SeqComponent<'S,'U> - - override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second) - - default second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) - default second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second) - default second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) - default second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) - - and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) = - inherit SeqComponent<'T,'V>() - - override __.ProcessNext (input:'T, output:byref<'V>) :bool = - let mutable temp = Unchecked.defaultof<'U> - if first.ProcessNext (input, &temp) then - Helpers.avoidTailCall (second.ProcessNext (temp, &output)) - else - false - - override __.Composer (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = - upcast Composed (first, second.Composer next) - - member __.First = first - member __.Second = second - - and Map<'T,'U> (map:'T->'U) = - inherit SeqComponent<'T,'U>() - - override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = - second.ComposeMap first - - override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = - upcast Factory.Map first.Map second.Map - - override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = - upcast FilterMap (first, second) - - override second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = - upcast FilterMap (first.Filter, Factory.Map first.Map.Map second.Map) - - override __.ProcessNext (input:'T, output:byref<'U>) : bool = - output <- map input - true - - member __.Map :'T->'U = map - - and Filter<'T> (filter:'T->bool) = - inherit SeqComponent<'T,'T>() - - override this.Composer (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = - next.ComposeFilter this - - override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> = - upcast MapFilter (first, second) - - override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'T> = - upcast Factory.Filter first.Filter second.Filter - - override second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'T> = - upcast MapFilter(first.Map, Factory.Filter first.Filter.Filter second.Filter) - - override __.ProcessNext (input:'T, output:byref<'T>) : bool = - if filter input then - output <- input - true - else - false - - member __.Filter :'T->bool = filter - - and MapFilter<'T,'U> (map:Map<'T,'U>, filter:Filter<'U>) = - inherit SeqComponent<'T,'U>() - - override __.ProcessNext (input:'T, output:byref<'U>) :bool = - output <- map.Map input - Helpers.avoidTailCall (filter.Filter output) - - override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> = - second.ComposeMapFilter first - - member __.Map : Map<'T,'U> = map - member __.Filter : Filter<'U> = filter - - and FilterMap<'T,'U> (filter:Filter<'T>, map:Map<'T,'U>) = - inherit SeqComponent<'T,'U>() - - override __.ProcessNext (input:'T, output:byref<'U>) : bool = - if filter.Filter input then - output <- map.Map input - true - else - false - - override this.Composer (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.ComposeFilterMap this - - member __.Filter : Filter<'T> = filter - member __.Map : Map<'T,'U> = map - - and Pairwise<'T> () = - inherit SeqComponent<'T,'T*'T>() - - let mutable isFirst = true - let mutable lastValue = Unchecked.defaultof<'T> - - override __.ProcessNext (input:'T, output:byref<'T*'T>) : bool = - if isFirst then - lastValue <- input - isFirst <- false - false - else - output <- lastValue, input - lastValue <- input - true - - and Skip<'T> (skipCount:int) = - inherit SeqComponent<'T,'T>() - - let mutable count = 0 - - override __.ProcessNext (input:'T, output:byref<'T>) : bool = - if count < skipCount then - count <- count + 1 - false - else - output <- input - true - - type SeqProcessNextStates = - | NotStarted = 1 - | Finished = 2 - | InProcess = 3 - - type SeqEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) = - let mutable source = enumerator - let mutable state = SeqProcessNextStates.NotStarted - let mutable current = Unchecked.defaultof<_> - - let rec moveNext () = - if source.MoveNext () then - if t2u.ProcessNext (source.Current, ¤t) then - true - else - moveNext () - else - state <- SeqProcessNextStates.Finished - false - - interface IDisposable with - member x.Dispose():unit = - match source with - | null -> () - | _ -> - source.Dispose () - source <- Unchecked.defaultof<_> - - interface IEnumerator with - member this.Current : obj = box (this:>IEnumerator<'U>).Current - member __.MoveNext () = - state <- SeqProcessNextStates.InProcess - moveNext () - member __.Reset () : unit = noReset () - - interface IEnumerator<'U> with - member x.Current = - match state with - | SeqProcessNextStates.NotStarted -> notStarted() - | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> () - current - - [] - type SeqEnumerableBase<'T> () = - abstract member Compose<'U> : SeqComponent<'T,'U> -> IEnumerable<'U> - - type SeqEnumerable<'T,'U>(generator:IEnumerable<'T>, t2u:SeqComponent<'T,'U>) = - inherit SeqEnumerableBase<'U>() - - let getEnumerator () : IEnumerator<'U> = - upcast (new SeqEnumerator<'T,'U>(generator.GetEnumerator(), t2u)) - - interface IEnumerable with - member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ()) - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = getEnumerator () - - override __.Compose (u2v:SeqComponent<'U,'V>) = - new SeqEnumerable<'T,'V>(generator, t2u.Composer u2v) :> IEnumerable<'V> - let cast (e : IEnumerator) : IEnumerator<'T> = { new IEnumerator<'T> with member x.Current = unbox<'T> e.Current @@ -1023,6 +813,395 @@ namespace Microsoft.FSharp.Collections [] [] module Seq = + type ISeqEnumerable<'T> = + abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State + + module SeqComposer = + open IEnumerator + + module Helpers = + // used for performance reasons; these are not recursive calls, so should be safe + let inline avoidTailCall x = + match x with + | true -> true + | false -> false + + let inline ComposeFilter f g x = f x && g x + + type [] SeqComponent<'T,'U> () = + abstract ProcessNext : input:'T * halt:byref * output:byref<'U> -> bool + abstract OnComplete : unit -> unit + + abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V> + + abstract ComposeMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U> + abstract ComposeFilter : Filter<'T> -> SeqComponent<'T,'U> + abstract ComposeFilterMap<'S> : FilterMap<'S,'T> -> SeqComponent<'S,'U> + abstract ComposeMapFilter<'S> : MapFilter<'S,'T> -> SeqComponent<'S,'U> + abstract ComposeSkip : Skip<'T> -> SeqComponent<'T,'U> + + default __.OnComplete () = () + + default first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second) + + default second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) + default second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second) + default second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) + default second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) + default second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second) + + and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) = + inherit SeqComponent<'T,'V>() + + override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) :bool = + let mutable temp = Unchecked.defaultof<'U> + if first.ProcessNext (input, &halted, &temp) && not halted then + second.ProcessNext (temp, &halted, &output) + else + false + + override __.Composer (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = + upcast Composed (first, second.Composer next) + + override __.OnComplete () = + first.OnComplete () + second.OnComplete () + + and Map<'T,'U> (map:'T->'U) = + inherit SeqComponent<'T,'U>() + + override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = + second.ComposeMap first + + override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = + upcast Map (first.Map >> second.Map) + + override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = + upcast FilterMap (first.Filter, second.Map) + + override second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = + upcast FilterMap (first.Filter, first.Map >> second.Map) + + override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool = + output <- map input + true + + member __.Map : 'T->'U = map + + and Mapi<'T,'U> (mapi:int->'T->'U) = + inherit SeqComponent<'T,'U>() + + let mutable idx = 0 + + override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool = + output <- mapi idx input + idx <- idx + 1 + true + + member __.Mapi : int->'T->'U = mapi + + and Filter<'T> (filter:'T->bool) = + inherit SeqComponent<'T,'T>() + + override this.Composer (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = + next.ComposeFilter this + + override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> = + upcast MapFilter (first.Map, second.Filter) + + override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'T> = + upcast Filter (Helpers.ComposeFilter first.Filter second.Filter) + + override second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'T> = + upcast MapFilter (first.Map, Helpers.ComposeFilter first.Filter second.Filter) + + override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool = + if filter input then + output <- input + true + else + false + + member __.Filter :'T->bool = filter + + and MapFilter<'T,'U> (map:'T->'U, filter:'U->bool) = + inherit SeqComponent<'T,'U>() + + override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) :bool = + output <- map input + Helpers.avoidTailCall (filter output) + + override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> = + second.ComposeMapFilter first + + member __.Map : 'T->'U = map + member __.Filter : 'U->bool = filter + + and FilterMap<'T,'U> (filter:'T->bool, map:'T->'U) = + inherit SeqComponent<'T,'U>() + + override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool = + if filter input then + output <- map input + true + else + false + + override this.Composer (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.ComposeFilterMap this + + member __.Filter : 'T->bool = filter + member __.Map : 'T->'U = map + + and Pairwise<'T> () = + inherit SeqComponent<'T,'T*'T>() + + let mutable isFirst = true + let mutable lastValue = Unchecked.defaultof<'T> + + override __.ProcessNext (input:'T, halted:byref, output:byref<'T*'T>) : bool = + if isFirst then + lastValue <- input + isFirst <- false + false + else + output <- lastValue, input + lastValue <- input + true + + and Skip<'T> (skipCount:int) = + inherit SeqComponent<'T,'T>() + + let mutable count = 0 + + override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = + second.ComposeSkip first + + override second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'T> = + if System.Int32.MaxValue - second.SkipCount > first.SkipCount then + upcast Skip (first.SkipCount + second.SkipCount) + else + upcast Composed (first, second) + + override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool = + if count < skipCount then + count <- count + 1 + false + else + output <- input + true + + override __.OnComplete () = + if count < skipCount then + let x = skipCount - count + invalidOpFmt "tried to skip {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + + member __.SkipCount = skipCount + + and Take<'T> (takeCount:int) = + inherit SeqComponent<'T,'T>() + + let mutable count = 0 + + override second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'T> = + if System.Int32.MaxValue - second.TakeCount > first.SkipCount then + upcast SkipTake (first.SkipCount, first.SkipCount+second.TakeCount) + else + upcast Composed (first, second) + + override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool = + if count < takeCount then + count <- count + 1 + output <- input + true + else + halted <- true + false + + override __.OnComplete () = + if count < takeCount then + let x = takeCount - count + invalidOpFmt "tried to take {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + + member __.TakeCount = takeCount + + and SkipTake<'T> (startIdx:int, endIdx:int) = + inherit SeqComponent<'T,'T>() + + let mutable count = 0 + + override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool = + if count < startIdx then + count <- count + 1 + false + elif count < endIdx then + count <- count + 1 + output <- input + true + else + halted <- true + false + + override __.OnComplete () = + if count < startIdx then + let x = startIdx - count + invalidOpFmt "tried to skip {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + elif count < endIdx then + let x = endIdx - count + invalidOpFmt "tried to take {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + + type SeqProcessNextStates = + | NotStarted = 1 + | Finished = 2 + | InProcess = 3 + + type SeqEnumeratorEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) = + let mutable state = SeqProcessNextStates.NotStarted + let mutable current = Unchecked.defaultof<'U> + let mutable halted = false + + let mutable source = enumerator + + let rec moveNext () = + if (not halted) && source.MoveNext () then + if t2u.ProcessNext (source.Current, &halted, ¤t) then + true + else + moveNext () + else + state <- SeqProcessNextStates.Finished + t2u.OnComplete () + false + + interface IDisposable with + member x.Dispose():unit = + match source with + | null -> () + | _ -> source.Dispose (); source <- Unchecked.defaultof<_> + + interface IEnumerator with + member this.Current : obj = box (this:>IEnumerator<'U>).Current + member __.MoveNext () = + state <- SeqProcessNextStates.InProcess + moveNext () + member __.Reset () : unit = noReset () + + interface IEnumerator<'U> with + member x.Current = + match state with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> () + current + + type SeqArrayEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) = + let mutable state = SeqProcessNextStates.NotStarted + let mutable current = Unchecked.defaultof<'U> + let mutable halted = false + + let mutable idx = 0 + + let rec moveNext () = + if (not halted) && idx < array.Length then + idx <- idx+1 + if t2u.ProcessNext (array.[idx-1], &halted, ¤t) then + true + else + moveNext () + else + state <- SeqProcessNextStates.Finished + t2u.OnComplete () + false + + interface IDisposable with + member x.Dispose() : unit = () + + interface IEnumerator with + member this.Current : obj = box (this:>IEnumerator<'U>).Current + member __.MoveNext () = + state <- SeqProcessNextStates.InProcess + moveNext () + member __.Reset () : unit = noReset () + + interface IEnumerator<'U> with + member x.Current = + match state with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> () + current + + [] + type ComposableEnumerable<'T> () = + abstract member Compose<'U> : (unit -> SeqComponent<'T,'U>) -> IEnumerable<'U> + + type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:unit->SeqComponent<'T,'U>) = + inherit ComposableEnumerable<'U>() + + let getEnumerator () : IEnumerator<'U> = + upcast (new SeqEnumeratorEnumerator<'T,'U>(enumerable.GetEnumerator(), current ())) + + interface IEnumerable with + member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ()) + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = getEnumerator () + + override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> = + upcast new SeqEnumerable<'T,'V>(enumerable, fun () -> (current ()).Composer (next ())) + + interface ISeqEnumerable<'U> with + member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let enumerator = enumerable.GetEnumerator () + let components = current () + let mutable output = Unchecked.defaultof<'U> + let mutable halt = false + + let mutable state = initialState + while (not halt) && enumerator.MoveNext () do + if components.ProcessNext (enumerator.Current, &halt, &output) then + state <- folder'.Invoke (state, output) + + state + + type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:unit->SeqComponent<'T,'U>) = + inherit ComposableEnumerable<'U>() + + let getEnumerator () : IEnumerator<'U> = + upcast (new SeqArrayEnumerator<'T,'U>(array, current ())) + + interface IEnumerable with + member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ()) + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = getEnumerator () + + override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> = + upcast new SeqArrayEnumerable<'T,'V>(array, fun () -> (current ()).Composer (next ())) + + interface ISeqEnumerable<'U> with + member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let mutable idx = 0 + let components = current () + let mutable current = Unchecked.defaultof<'U> + let mutable halt = false + + let mutable state = initialState + while (not halt) && idx < array.Length do + if components.ProcessNext (array.[idx], &halt, ¤t) then + state <- folder'.Invoke(state, current) + idx <- idx + 1 + + state + + #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions @@ -1143,27 +1322,30 @@ namespace Microsoft.FSharp.Collections let revamp3 f (ie1 : seq<_>) (source2 : seq<_>) (source3 : seq<_>) = mkSeq (fun () -> f (ie1.GetEnumerator()) (source2.GetEnumerator()) (source3.GetEnumerator())) - [] - let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = + let private seqFactory createSeqComponent (source:seq<'T>) = checkNonNull "source" source match source with - | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Filter f) - | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Filter f)) + | :? SeqComposer.ComposableEnumerable<'T> as s -> s.Compose createSeqComponent + | :? array<'T> as a -> upcast (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent)) + | _ -> upcast (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent)) + + let private seqFactoryForImmutable seqComponent (source:seq<'T>) = + source |> seqFactory (fun () -> seqComponent) + + [] + let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = + source |> seqFactoryForImmutable (SeqComposer.Filter f) [] let where f source = filter f source [] let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> = - checkNonNull "source" source - match source with - | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Map f) - | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Map f)) + source |> seqFactoryForImmutable (SeqComposer.Map f) [] let mapi f source = - checkNonNull "source" source - revamp (IEnumerator.mapi f) source + source |> seqFactory (fun () -> upcast SeqComposer.Mapi f) [] let mapi2 f source1 source2 = @@ -1247,16 +1429,10 @@ namespace Microsoft.FSharp.Collections [] let take count (source : seq<'T>) = - checkNonNull "source" source if count < 0 then invalidArgInputMustBeNonNegative "count" count (* Note: don't create or dispose any IEnumerable if n = 0 *) if count = 0 then empty else - seq { use e = source.GetEnumerator() - for x in 0 .. count - 1 do - if not (e.MoveNext()) then - invalidOpFmt "tried to take {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - yield e.Current } + source |> seqFactory (fun () -> upcast SeqComposer.Take count) [] let isEmpty (source : seq<'T>) = @@ -1437,10 +1613,7 @@ namespace Microsoft.FSharp.Collections [] let pairwise<'T> (source:seq<'T>) : seq<'T*'T> = - checkNonNull "source" source - match source with - | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Pairwise ()) - | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Pairwise ())) + source |> seqFactory (fun () -> upcast SeqComposer.Pairwise ()) [] let scan<'T,'State> f (z:'State) (source : seq<'T>) = @@ -1878,14 +2051,7 @@ namespace Microsoft.FSharp.Collections [] let skip count (source: seq<_>) = - checkNonNull "source" source - seq { use e = source.GetEnumerator() - for x in 1 .. count do - if not (e.MoveNext()) then - invalidOpFmt "tried to skip {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - while e.MoveNext() do - yield e.Current } + source |> seqFactory (fun () -> upcast SeqComposer.Skip count) [] let skipWhile p (source: seq<_>) = From ce6b12621fc2b2fa831b8542f47b7d8db87284ba Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Sep 2016 18:49:22 +1000 Subject: [PATCH 004/286] Temporarily remove the ISeqEnumerable interface It was causing build issues as it was currently unused. --- src/fsharp/FSharp.Core/seq.fs | 66 +++++++++++++++++------------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ba17f59305e..1c1d7a089a2 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -813,8 +813,8 @@ namespace Microsoft.FSharp.Collections [] [] module Seq = - type ISeqEnumerable<'T> = - abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State +// type ISeqEnumerable<'T> = +// abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State module SeqComposer = open IEnumerator @@ -1153,21 +1153,21 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> = upcast new SeqEnumerable<'T,'V>(enumerable, fun () -> (current ()).Composer (next ())) - interface ISeqEnumerable<'U> with - member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let enumerator = enumerable.GetEnumerator () - let components = current () - let mutable output = Unchecked.defaultof<'U> - let mutable halt = false - - let mutable state = initialState - while (not halt) && enumerator.MoveNext () do - if components.ProcessNext (enumerator.Current, &halt, &output) then - state <- folder'.Invoke (state, output) - - state +// interface ISeqEnumerable<'U> with +// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = +// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder +// +// let enumerator = enumerable.GetEnumerator () +// let components = current () +// let mutable output = Unchecked.defaultof<'U> +// let mutable halt = false +// +// let mutable state = initialState +// while (not halt) && enumerator.MoveNext () do +// if components.ProcessNext (enumerator.Current, &halt, &output) then +// state <- folder'.Invoke (state, output) +// +// state type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:unit->SeqComponent<'T,'U>) = inherit ComposableEnumerable<'U>() @@ -1184,22 +1184,22 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> = upcast new SeqArrayEnumerable<'T,'V>(array, fun () -> (current ()).Composer (next ())) - interface ISeqEnumerable<'U> with - member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let mutable idx = 0 - let components = current () - let mutable current = Unchecked.defaultof<'U> - let mutable halt = false - - let mutable state = initialState - while (not halt) && idx < array.Length do - if components.ProcessNext (array.[idx], &halt, ¤t) then - state <- folder'.Invoke(state, current) - idx <- idx + 1 - - state +// interface ISeqEnumerable<'U> with +// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = +// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder +// +// let mutable idx = 0 +// let components = current () +// let mutable current = Unchecked.defaultof<'U> +// let mutable halt = false +// +// let mutable state = initialState +// while (not halt) && idx < array.Length do +// if components.ProcessNext (array.[idx], &halt, ¤t) then +// state <- folder'.Invoke(state, current) +// idx <- idx + 1 +// +// state From 118ca3d19b2465addff0c7cab30b60c0fec5bccc Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Sep 2016 19:59:49 +1000 Subject: [PATCH 005/286] Fixing halting on take --- src/fsharp/FSharp.Core/seq.fs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 1c1d7a089a2..5f4b34ceb26 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -855,7 +855,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) :bool = let mutable temp = Unchecked.defaultof<'U> - if first.ProcessNext (input, &halted, &temp) && not halted then + if first.ProcessNext (input, &halted, &temp) then second.ProcessNext (temp, &halted, &output) else false @@ -1013,6 +1013,7 @@ namespace Microsoft.FSharp.Collections if count < takeCount then count <- count + 1 output <- input + halted <- count = takeCount true else halted <- true @@ -1038,6 +1039,7 @@ namespace Microsoft.FSharp.Collections elif count < endIdx then count <- count + 1 output <- input + halted <- count = endIdx true else halted <- true From e2a5ae4d619a90bd097c21324a8c327dd3148c29 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 2 Oct 2016 18:26:16 +1100 Subject: [PATCH 006/286] Return current as match of match statement for perf *slight* performance improvement --- src/fsharp/FSharp.Core/seq.fs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 5f4b34ceb26..afff06239bb 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1096,8 +1096,7 @@ namespace Microsoft.FSharp.Collections match state with | SeqProcessNextStates.NotStarted -> notStarted() | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> () - current + | _ -> current type SeqArrayEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) = let mutable state = SeqProcessNextStates.NotStarted @@ -1133,8 +1132,7 @@ namespace Microsoft.FSharp.Collections match state with | SeqProcessNextStates.NotStarted -> notStarted() | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> () - current + | _ -> current [] type ComposableEnumerable<'T> () = From 7fce803a777823d48ef634622e101dc18127c525 Mon Sep 17 00:00:00 2001 From: liboz Date: Mon, 3 Oct 2016 16:34:00 -0400 Subject: [PATCH 007/286] renaming cleanup. Adding ListEnumerable. Adding Choose --- src/fsharp/FSharp.Core/seq.fs | 149 ++++++++++++++++++++++++---------- 1 file changed, 104 insertions(+), 45 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index afff06239bb..58f034d1914 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -834,21 +834,21 @@ namespace Microsoft.FSharp.Collections abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V> - abstract ComposeMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U> - abstract ComposeFilter : Filter<'T> -> SeqComponent<'T,'U> - abstract ComposeFilterMap<'S> : FilterMap<'S,'T> -> SeqComponent<'S,'U> - abstract ComposeMapFilter<'S> : MapFilter<'S,'T> -> SeqComponent<'S,'U> - abstract ComposeSkip : Skip<'T> -> SeqComponent<'T,'U> + abstract ComposeWithMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U> + abstract ComposeWithFilter : Filter<'T> -> SeqComponent<'T,'U> + abstract ComposeWithFilterThenMap<'S> : FilterThenMap<'S,'T> -> SeqComponent<'S,'U> + abstract ComposeWithMapThenFilter<'S> : MapThenFilter<'S,'T> -> SeqComponent<'S,'U> + abstract ComposeWithSkip : Skip<'T> -> SeqComponent<'T,'U> default __.OnComplete () = () - default first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second) + default first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second) - default second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) - default second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second) - default second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) - default second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) - default second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second) + default second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) + default second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second) + default second.ComposeWithFilterThenMap<'S> (first:FilterThenMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) + default second.ComposeWithMapThenFilter<'S> (first:MapThenFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) + default second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second) and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) = inherit SeqComponent<'T,'V>() @@ -871,16 +871,16 @@ namespace Microsoft.FSharp.Collections inherit SeqComponent<'T,'U>() override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = - second.ComposeMap first + second.ComposeWithMap first - override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = + override second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Map (first.Map >> second.Map) - override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = - upcast FilterMap (first.Filter, second.Map) + override second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'U> = + upcast FilterThenMap (first.Filter, second.Map) - override second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = - upcast FilterMap (first.Filter, first.Map >> second.Map) + override second.ComposeWithFilterThenMap<'S> (first:FilterThenMap<'S,'T>) : SeqComponent<'S,'U> = + upcast FilterThenMap (first.Filter, first.Map >> second.Map) override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool = output <- map input @@ -903,17 +903,17 @@ namespace Microsoft.FSharp.Collections and Filter<'T> (filter:'T->bool) = inherit SeqComponent<'T,'T>() - override this.Composer (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = - next.ComposeFilter this + override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = + second.ComposeWithFilter first - override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> = - upcast MapFilter (first.Map, second.Filter) + override second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> = + upcast MapThenFilter (first.Map, second.Filter) - override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'T> = + override second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'T> = upcast Filter (Helpers.ComposeFilter first.Filter second.Filter) - override second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'T> = - upcast MapFilter (first.Map, Helpers.ComposeFilter first.Filter second.Filter) + override second.ComposeWithMapThenFilter<'S> (first:MapThenFilter<'S,'T>) : SeqComponent<'S,'T> = + upcast MapThenFilter (first.Map, Helpers.ComposeFilter first.Filter second.Filter) override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool = if filter input then @@ -924,7 +924,7 @@ namespace Microsoft.FSharp.Collections member __.Filter :'T->bool = filter - and MapFilter<'T,'U> (map:'T->'U, filter:'U->bool) = + and MapThenFilter<'T,'U> (map:'T->'U, filter:'U->bool) = inherit SeqComponent<'T,'U>() override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) :bool = @@ -932,12 +932,12 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (filter output) override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> = - second.ComposeMapFilter first + second.ComposeWithMapThenFilter first member __.Map : 'T->'U = map member __.Filter : 'U->bool = filter - and FilterMap<'T,'U> (filter:'T->bool, map:'T->'U) = + and FilterThenMap<'T,'U> (filter:'T->bool, map:'T->'U) = inherit SeqComponent<'T,'U>() override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool = @@ -947,7 +947,7 @@ namespace Microsoft.FSharp.Collections else false - override this.Composer (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.ComposeFilterMap this + override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = second.ComposeWithFilterThenMap first member __.Filter : 'T->bool = filter member __.Map : 'T->'U = map @@ -974,10 +974,10 @@ namespace Microsoft.FSharp.Collections let mutable count = 0 override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = - second.ComposeSkip first + second.ComposeWithSkip first - override second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'T> = - if System.Int32.MaxValue - second.SkipCount > first.SkipCount then + override second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'T> = + if Int32.MaxValue - first.SkipCount - second.SkipCount > 0 then upcast Skip (first.SkipCount + second.SkipCount) else upcast Composed (first, second) @@ -1003,9 +1003,9 @@ namespace Microsoft.FSharp.Collections let mutable count = 0 - override second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'T> = - if System.Int32.MaxValue - second.TakeCount > first.SkipCount then - upcast SkipTake (first.SkipCount, first.SkipCount+second.TakeCount) + override second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'T> = + if Int32.MaxValue - first.SkipCount - second.TakeCount > 0 then + upcast SkipThenTake (first.SkipCount, first.SkipCount+second.TakeCount) else upcast Composed (first, second) @@ -1027,7 +1027,7 @@ namespace Microsoft.FSharp.Collections member __.TakeCount = takeCount - and SkipTake<'T> (startIdx:int, endIdx:int) = + and SkipThenTake<'T> (startIdx:int, endIdx:int) = inherit SeqComponent<'T,'T>() let mutable count = 0 @@ -1054,13 +1054,22 @@ namespace Microsoft.FSharp.Collections let x = endIdx - count invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + + and Choose<'T, 'U> (choose:'T->'U option) = + inherit SeqComponent<'T,'U>() + + override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool = + match choose input with + | Some value -> output <- value + true + | None -> false type SeqProcessNextStates = | NotStarted = 1 | Finished = 2 | InProcess = 3 - type SeqEnumeratorEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) = + type SeqComposedEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) = let mutable state = SeqProcessNextStates.NotStarted let mutable current = Unchecked.defaultof<'U> let mutable halted = false @@ -1079,7 +1088,7 @@ namespace Microsoft.FSharp.Collections false interface IDisposable with - member x.Dispose():unit = + member __.Dispose():unit = match source with | null -> () | _ -> source.Dispose (); source <- Unchecked.defaultof<_> @@ -1092,13 +1101,13 @@ namespace Microsoft.FSharp.Collections member __.Reset () : unit = noReset () interface IEnumerator<'U> with - member x.Current = + member __.Current = match state with | SeqProcessNextStates.NotStarted -> notStarted() | SeqProcessNextStates.Finished -> alreadyFinished() | _ -> current - type SeqArrayEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) = + type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) = let mutable state = SeqProcessNextStates.NotStarted let mutable current = Unchecked.defaultof<'U> let mutable halted = false @@ -1118,7 +1127,7 @@ namespace Microsoft.FSharp.Collections false interface IDisposable with - member x.Dispose() : unit = () + member __.Dispose() : unit = () interface IEnumerator with member this.Current : obj = box (this:>IEnumerator<'U>).Current @@ -1128,7 +1137,43 @@ namespace Microsoft.FSharp.Collections member __.Reset () : unit = noReset () interface IEnumerator<'U> with - member x.Current = + member __.Current = + match state with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> current + + type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>) = + let mutable state = SeqProcessNextStates.NotStarted + let mutable current = Unchecked.defaultof<'U> + let mutable halted = false + + let mutable list = alist + + let rec moveNext () = + match halted, list with + | false, head::tail -> + list <- tail + if t2u.ProcessNext (head, &halted, ¤t) then + true + else + moveNext () + | _ -> state <- SeqProcessNextStates.Finished + t2u.OnComplete () + false + + interface IDisposable with + member __.Dispose() : unit = () + + interface IEnumerator with + member this.Current : obj = box (this:>IEnumerator<'U>).Current + member __.MoveNext () = + state <- SeqProcessNextStates.InProcess + moveNext () + member __.Reset () : unit = noReset () + + interface IEnumerator<'U> with + member __.Current = match state with | SeqProcessNextStates.NotStarted -> notStarted() | SeqProcessNextStates.Finished -> alreadyFinished() @@ -1142,7 +1187,7 @@ namespace Microsoft.FSharp.Collections inherit ComposableEnumerable<'U>() let getEnumerator () : IEnumerator<'U> = - upcast (new SeqEnumeratorEnumerator<'T,'U>(enumerable.GetEnumerator(), current ())) + upcast (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current ())) interface IEnumerable with member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ()) @@ -1173,7 +1218,7 @@ namespace Microsoft.FSharp.Collections inherit ComposableEnumerable<'U>() let getEnumerator () : IEnumerator<'U> = - upcast (new SeqArrayEnumerator<'T,'U>(array, current ())) + upcast (new ArrayComposedEnumerator<'T,'U>(array, current ())) interface IEnumerable with member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ()) @@ -1201,6 +1246,20 @@ namespace Microsoft.FSharp.Collections // // state + type SeqListEnumerable<'T,'U>(alist:list<'T>, current:unit->SeqComponent<'T,'U>) = + inherit ComposableEnumerable<'U>() + + let getEnumerator () : IEnumerator<'U> = + upcast (new ListComposedEnumerator<'T,'U>(alist, current ())) + + interface IEnumerable with + member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ()) + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = getEnumerator () + + override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> = + upcast new SeqListEnumerable<'T,'V>(alist, fun () -> (current ()).Composer (next ())) #if FX_NO_ICLONEABLE @@ -1327,6 +1386,7 @@ namespace Microsoft.FSharp.Collections match source with | :? SeqComposer.ComposableEnumerable<'T> as s -> s.Compose createSeqComponent | :? array<'T> as a -> upcast (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent)) + | :? list<'T> as a -> upcast (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent)) | _ -> upcast (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent)) let private seqFactoryForImmutable seqComponent (source:seq<'T>) = @@ -1368,8 +1428,7 @@ namespace Microsoft.FSharp.Collections [] let choose f source = - checkNonNull "source" source - revamp (IEnumerator.choose f) source + source |> seqFactoryForImmutable (SeqComposer.Choose f) [] let indexed source = From e5bf10a3f37e5abd401f4fd69202ff30a86ca0dc Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 4 Oct 2016 20:00:31 +1100 Subject: [PATCH 008/286] Remove unbox.any when upcasting to IEnumer(able|ator) Thanks to @liboz for reminding me of the performance hit here. This is noticeable when you have small collections to be iterated. --- src/fsharp/FSharp.Core/seq.fs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 58f034d1914..6895051cda0 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -828,6 +828,10 @@ namespace Microsoft.FSharp.Collections let inline ComposeFilter f g x = f x && g x + let inline UpcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) + let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) + let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) + type [] SeqComponent<'T,'U> () = abstract ProcessNext : input:'T * halt:byref * output:byref<'U> -> bool abstract OnComplete : unit -> unit @@ -1094,7 +1098,7 @@ namespace Microsoft.FSharp.Collections | _ -> source.Dispose (); source <- Unchecked.defaultof<_> interface IEnumerator with - member this.Current : obj = box (this:>IEnumerator<'U>).Current + member this.Current : obj = box (Helpers.UpcastEnumerator this).Current member __.MoveNext () = state <- SeqProcessNextStates.InProcess moveNext () @@ -1130,7 +1134,7 @@ namespace Microsoft.FSharp.Collections member __.Dispose() : unit = () interface IEnumerator with - member this.Current : obj = box (this:>IEnumerator<'U>).Current + member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current member __.MoveNext () = state <- SeqProcessNextStates.InProcess moveNext () @@ -1187,16 +1191,16 @@ namespace Microsoft.FSharp.Collections inherit ComposableEnumerable<'U>() let getEnumerator () : IEnumerator<'U> = - upcast (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current ())) + Helpers.UpcastEnumerator (new SeqEnumeratorEnumerator<'T,'U>(enumerable.GetEnumerator(), current ())) interface IEnumerable with - member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ()) + member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ()) interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = getEnumerator () override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> = - upcast new SeqEnumerable<'T,'V>(enumerable, fun () -> (current ()).Composer (next ())) + Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, fun () -> (current ()).Composer (next ()))) // interface ISeqEnumerable<'U> with // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = @@ -1218,16 +1222,16 @@ namespace Microsoft.FSharp.Collections inherit ComposableEnumerable<'U>() let getEnumerator () : IEnumerator<'U> = - upcast (new ArrayComposedEnumerator<'T,'U>(array, current ())) + Helpers.UpcastEnumerator (new SeqArrayEnumerator<'T,'U>(array, current ())) interface IEnumerable with - member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ()) + member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ()) interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = getEnumerator () override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> = - upcast new SeqArrayEnumerable<'T,'V>(array, fun () -> (current ()).Composer (next ())) + Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, fun () -> (current ()).Composer (next ()))) // interface ISeqEnumerable<'U> with // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = @@ -1385,9 +1389,9 @@ namespace Microsoft.FSharp.Collections checkNonNull "source" source match source with | :? SeqComposer.ComposableEnumerable<'T> as s -> s.Compose createSeqComponent - | :? array<'T> as a -> upcast (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent)) - | :? list<'T> as a -> upcast (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent)) - | _ -> upcast (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent)) + | :? array<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent)) + | :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent)) + | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent)) let private seqFactoryForImmutable seqComponent (source:seq<'T>) = source |> seqFactory (fun () -> seqComponent) From 113c5903396066d121f353de09f906799a504574 Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 4 Oct 2016 22:13:24 -0400 Subject: [PATCH 009/286] remove old mapi function --- src/fsharp/FSharp.Core/seq.fs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 6895051cda0..5ca6b376d72 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -108,21 +108,6 @@ namespace Microsoft.FSharp.Collections interface System.IDisposable with member this.Dispose() = this.Dispose() - let mapi f (e : IEnumerator<_>) : IEnumerator<_> = - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let i = ref (-1) - upcast - { new MapEnumerator<_>() with - member this.DoMoveNext curr = - i := !i + 1 - if e.MoveNext() then - curr <- f.Invoke(!i, e.Current) - true - else - false - member this.Dispose() = e.Dispose() - } - let map2 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) : IEnumerator<_>= let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) upcast From dd80725e539142567428d2f001a7697496970562 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 5 Oct 2016 10:09:17 -0400 Subject: [PATCH 010/286] skipwhile/takewhile --- src/fsharp/FSharp.Core/seq.fs | 46 +++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 5ca6b376d72..12533201ea2 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1043,7 +1043,35 @@ namespace Microsoft.FSharp.Collections let x = endIdx - count invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - + + and SkipWhile<'T> (predicate: 'T -> bool) = + inherit SeqComponent<'T,'T>() + + let mutable skip = true + + override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool = + if skip then + skip <- predicate input + if skip then + false + else + output <- input + true + else + output <- input + true + + and TakeWhile<'T> (predicate: 'T -> bool) = + inherit SeqComponent<'T,'T>() + + override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool = + if predicate input then + output <- input + true + else + halted <- true + false + and Choose<'T, 'U> (choose:'T->'U option) = inherit SeqComponent<'T,'U>() @@ -2091,11 +2119,7 @@ namespace Microsoft.FSharp.Collections *) [] let takeWhile p (source: seq<_>) = - checkNonNull "source" source - seq { use e = source.GetEnumerator() - let latest = ref Unchecked.defaultof<_> - while e.MoveNext() && (latest := e.Current; p !latest) do - yield !latest } + source |> seqFactory (fun () -> upcast SeqComposer.TakeWhile p) [] let skip count (source: seq<_>) = @@ -2103,15 +2127,7 @@ namespace Microsoft.FSharp.Collections [] let skipWhile p (source: seq<_>) = - checkNonNull "source" source - seq { use e = source.GetEnumerator() - let latest = ref (Unchecked.defaultof<_>) - let ok = ref false - while e.MoveNext() do - if (latest := e.Current; (!ok || not (p !latest))) then - ok := true - yield !latest } - + source |> seqFactory (fun () -> upcast SeqComposer.SkipWhile p) [] let forall2 p (source1: seq<_>) (source2: seq<_>) = From 01675fe6688b65593ec78f5a4685194a3489de2a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 7 Oct 2016 20:18:45 +1100 Subject: [PATCH 011/286] Changes SeqComposer to build bottom-up A more direct calling process. Slows things down *slightly* when only a single item is being processed, but is a better model to build from going forward. --- src/fsharp/FSharp.Core/seq.fs | 319 +++++++++++++--------------------- 1 file changed, 125 insertions(+), 194 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 12533201ea2..655ff4fb830 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -817,167 +817,137 @@ namespace Microsoft.FSharp.Collections let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - type [] SeqComponent<'T,'U> () = - abstract ProcessNext : input:'T * halt:byref * output:byref<'U> -> bool - abstract OnComplete : unit -> unit + type [] SeqComponentFactory<'T,'U> () = + abstract Create<'V> : SeqComponent<'U,'V> -> SeqComponent<'T,'V> + + member __.Compose<'V> (next:SeqComponent<'U,'V>) = Unchecked.defaultof<_> - abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V> + and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = + inherit SeqComponentFactory<'T,'V> () + override __.Create<'W> (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create (second.Create next) - abstract ComposeWithMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U> - abstract ComposeWithFilter : Filter<'T> -> SeqComponent<'T,'U> - abstract ComposeWithFilterThenMap<'S> : FilterThenMap<'S,'T> -> SeqComponent<'S,'U> - abstract ComposeWithMapThenFilter<'S> : MapThenFilter<'S,'T> -> SeqComponent<'S,'U> - abstract ComposeWithSkip : Skip<'T> -> SeqComponent<'T,'U> + and MapFactory<'T,'U> (map:'T->'U) = + inherit SeqComponentFactory<'T,'U> () + override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map - default __.OnComplete () = () + and MapiFactory<'T,'U> (mapi:int->'T->'U) = + inherit SeqComponentFactory<'T,'U> () + override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next) - default first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second) + and FilterFactory<'T> (filter:'T->bool) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Filter (filter, next) - default second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) - default second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second) - default second.ComposeWithFilterThenMap<'S> (first:FilterThenMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) - default second.ComposeWithMapThenFilter<'S> (first:MapThenFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second) - default second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second) + and PairwiseFactory<'T> () = + inherit SeqComponentFactory<'T,'T*'T> () + override __.Create<'V> (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next - and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) = - inherit SeqComponent<'T,'V>() + and SkipFactory<'T> (count:int) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next) - override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) :bool = - let mutable temp = Unchecked.defaultof<'U> - if first.ProcessNext (input, &halted, &temp) then - second.ProcessNext (temp, &halted, &output) - else - false + and SkipWhileFactory<'T> (perdicate:'T->bool) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next) - override __.Composer (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = - upcast Composed (first, second.Composer next) + and TakeWhileFactory<'T> (perdicate:'T->bool) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, next) - override __.OnComplete () = - first.OnComplete () - second.OnComplete () + and TakeFactory<'T> (count:int) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, next) - and Map<'T,'U> (map:'T->'U) = - inherit SeqComponent<'T,'U>() + and ChooseFactory<'T,'U> (filter:'T->option<'U>) = + inherit SeqComponentFactory<'T,'U> () + override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next) - override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = - second.ComposeWithMap first + and [] SeqComponent<'T,'U> () = + abstract ProcessNext : input:'T * halt:byref * output:byref<'U> -> bool + abstract OnComplete : unit -> unit - override second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = - upcast Map (first.Map >> second.Map) - - override second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'U> = - upcast FilterThenMap (first.Filter, second.Map) + abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> + abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> - override second.ComposeWithFilterThenMap<'S> (first:FilterThenMap<'S,'T>) : SeqComponent<'S,'U> = - upcast FilterThenMap (first.Filter, first.Map >> second.Map) + default __.OnComplete () = () - override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool = - output <- map input - true + default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) + default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) - member __.Map : 'T->'U = map + and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'T,'V>() - and Mapi<'T,'U> (mapi:int->'T->'U) = - inherit SeqComponent<'T,'U>() + default this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) - let mutable idx = 0 + override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = + next.ProcessNext (map input, &halted, &output) - override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool = - output <- mapi idx input - idx <- idx + 1 - true + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'T,'V>() - member __.Mapi : int->'T->'U = mapi + override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = + let u = map input + if filter u then + next.ProcessNext (u, &halted, &output) + else + false - and Filter<'T> (filter:'T->bool) = - inherit SeqComponent<'T,'T>() + and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'T,'V>() - override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = - second.ComposeWithFilter first + let mutable idx = 0 - override second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> = - upcast MapThenFilter (first.Map, second.Filter) + override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = + idx <- idx + 1 + next.ProcessNext(mapi (idx-1) input, &halted, &output) - override second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'T> = - upcast Filter (Helpers.ComposeFilter first.Filter second.Filter) + and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>() - override second.ComposeWithMapThenFilter<'S> (first:MapThenFilter<'S,'T>) : SeqComponent<'S,'T> = - upcast MapThenFilter (first.Map, Helpers.ComposeFilter first.Filter second.Filter) + default this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) - override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool = + override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = if filter input then - output <- input - true + next.ProcessNext (input, &halted, &output) else false - member __.Filter :'T->bool = filter - - and MapThenFilter<'T,'U> (map:'T->'U, filter:'U->bool) = - inherit SeqComponent<'T,'U>() - - override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) :bool = - output <- map input - Helpers.avoidTailCall (filter output) - - override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> = - second.ComposeWithMapThenFilter first - - member __.Map : 'T->'U = map - member __.Filter : 'U->bool = filter - - and FilterThenMap<'T,'U> (filter:'T->bool, map:'T->'U) = - inherit SeqComponent<'T,'U>() + and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'T,'V>() - override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool = + override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = if filter input then - output <- map input - true + next.ProcessNext (map input, &halted, &output) else false - override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = second.ComposeWithFilterThenMap first - - member __.Filter : 'T->bool = filter - member __.Map : 'T->'U = map - - and Pairwise<'T> () = - inherit SeqComponent<'T,'T*'T>() + and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) = + inherit SeqComponent<'T,'V>() let mutable isFirst = true let mutable lastValue = Unchecked.defaultof<'T> - override __.ProcessNext (input:'T, halted:byref, output:byref<'T*'T>) : bool = + override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = if isFirst then lastValue <- input isFirst <- false false else - output <- lastValue, input + let currentPair = lastValue, input lastValue <- input - true + next.ProcessNext(currentPair, &halted, &output) - and Skip<'T> (skipCount:int) = - inherit SeqComponent<'T,'T>() + and Skip<'T,'V> (skipCount:int, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>() let mutable count = 0 - override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = - second.ComposeWithSkip first - - override second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'T> = - if Int32.MaxValue - first.SkipCount - second.SkipCount > 0 then - upcast Skip (first.SkipCount + second.SkipCount) - else - upcast Composed (first, second) - - override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool = + override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = if count < skipCount then count <- count + 1 false else - output <- input - true + next.ProcessNext (input, &halted, &output) override __.OnComplete () = if count < skipCount then @@ -985,25 +955,16 @@ namespace Microsoft.FSharp.Collections invalidOpFmt "tried to skip {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - member __.SkipCount = skipCount - - and Take<'T> (takeCount:int) = - inherit SeqComponent<'T,'T>() + and Take<'T,'V> (takeCount:int, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>() let mutable count = 0 - override second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'T> = - if Int32.MaxValue - first.SkipCount - second.TakeCount > 0 then - upcast SkipThenTake (first.SkipCount, first.SkipCount+second.TakeCount) - else - upcast Composed (first, second) - - override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool = + override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = if count < takeCount then count <- count + 1 - output <- input halted <- count = takeCount - true + next.ProcessNext (input, &halted, &output) else halted <- true false @@ -1014,73 +975,46 @@ namespace Microsoft.FSharp.Collections invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - member __.TakeCount = takeCount - - and SkipThenTake<'T> (startIdx:int, endIdx:int) = - inherit SeqComponent<'T,'T>() - - let mutable count = 0 - - override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool = - if count < startIdx then - count <- count + 1 - false - elif count < endIdx then - count <- count + 1 - output <- input - halted <- count = endIdx - true - else - halted <- true - false - - override __.OnComplete () = - if count < startIdx then - let x = startIdx - count - invalidOpFmt "tried to skip {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - elif count < endIdx then - let x = endIdx - count - invalidOpFmt "tried to take {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - - and SkipWhile<'T> (predicate: 'T -> bool) = - inherit SeqComponent<'T,'T>() + and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>() let mutable skip = true - override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool = + override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = if skip then skip <- predicate input if skip then false else - output <- input - true + next.ProcessNext (input, &halted, &output) else - output <- input - true + next.ProcessNext (input, &halted, &output) - and TakeWhile<'T> (predicate: 'T -> bool) = - inherit SeqComponent<'T,'T>() + and TakeWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>() - override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool = + override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = if predicate input then - output <- input - true + next.ProcessNext(input, &halted, &output) else halted <- true false - and Choose<'T, 'U> (choose:'T->'U option) = - inherit SeqComponent<'T,'U>() + and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'T,'V>() - override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool = + override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = match choose input with - | Some value -> output <- value - true + | Some value -> next.ProcessNext (value, &halted, &output) | None -> false + and Tail<'T> () = + inherit SeqComponent<'T,'T>() + + override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool = + output <- input + true + type SeqProcessNextStates = | NotStarted = 1 | Finished = 2 @@ -1198,13 +1132,13 @@ namespace Microsoft.FSharp.Collections [] type ComposableEnumerable<'T> () = - abstract member Compose<'U> : (unit -> SeqComponent<'T,'U>) -> IEnumerable<'U> + abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> - type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:unit->SeqComponent<'T,'U>) = + type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = inherit ComposableEnumerable<'U>() let getEnumerator () : IEnumerator<'U> = - Helpers.UpcastEnumerator (new SeqEnumeratorEnumerator<'T,'U>(enumerable.GetEnumerator(), current ())) + Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create (Tail ()))) interface IEnumerable with member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ()) @@ -1212,8 +1146,8 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = getEnumerator () - override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, fun () -> (current ()).Composer (next ()))) + override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, ComposedFactory (current, next))) // interface ISeqEnumerable<'U> with // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = @@ -1231,11 +1165,11 @@ namespace Microsoft.FSharp.Collections // // state - type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:unit->SeqComponent<'T,'U>) = + type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) = inherit ComposableEnumerable<'U>() let getEnumerator () : IEnumerator<'U> = - Helpers.UpcastEnumerator (new SeqArrayEnumerator<'T,'U>(array, current ())) + Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create (Tail ()))) interface IEnumerable with member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ()) @@ -1243,8 +1177,8 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = getEnumerator () - override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, fun () -> (current ()).Composer (next ()))) + override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, ComposedFactory (current, next))) // interface ISeqEnumerable<'U> with // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = @@ -1263,11 +1197,11 @@ namespace Microsoft.FSharp.Collections // // state - type SeqListEnumerable<'T,'U>(alist:list<'T>, current:unit->SeqComponent<'T,'U>) = + type SeqListEnumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) = inherit ComposableEnumerable<'U>() let getEnumerator () : IEnumerator<'U> = - upcast (new ListComposedEnumerator<'T,'U>(alist, current ())) + Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create (Tail ()))) interface IEnumerable with member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ()) @@ -1275,8 +1209,8 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = getEnumerator () - override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> = - upcast new SeqListEnumerable<'T,'V>(alist, fun () -> (current ()).Composer (next ())) + override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next))) #if FX_NO_ICLONEABLE @@ -1406,23 +1340,20 @@ namespace Microsoft.FSharp.Collections | :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent)) | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent)) - let private seqFactoryForImmutable seqComponent (source:seq<'T>) = - source |> seqFactory (fun () -> seqComponent) - [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = - source |> seqFactoryForImmutable (SeqComposer.Filter f) + source |> seqFactory (SeqComposer.FilterFactory f) [] let where f source = filter f source [] let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> = - source |> seqFactoryForImmutable (SeqComposer.Map f) + source |> seqFactory (SeqComposer.MapFactory f) [] let mapi f source = - source |> seqFactory (fun () -> upcast SeqComposer.Mapi f) + source |> seqFactory (SeqComposer.MapiFactory f) [] let mapi2 f source1 source2 = @@ -1445,7 +1376,7 @@ namespace Microsoft.FSharp.Collections [] let choose f source = - source |> seqFactoryForImmutable (SeqComposer.Choose f) + source |> seqFactory (SeqComposer.ChooseFactory f) [] let indexed source = @@ -1508,7 +1439,7 @@ namespace Microsoft.FSharp.Collections if count < 0 then invalidArgInputMustBeNonNegative "count" count (* Note: don't create or dispose any IEnumerable if n = 0 *) if count = 0 then empty else - source |> seqFactory (fun () -> upcast SeqComposer.Take count) + source |> seqFactory (SeqComposer.TakeFactory count) [] let isEmpty (source : seq<'T>) = @@ -1689,7 +1620,7 @@ namespace Microsoft.FSharp.Collections [] let pairwise<'T> (source:seq<'T>) : seq<'T*'T> = - source |> seqFactory (fun () -> upcast SeqComposer.Pairwise ()) + source |> seqFactory (SeqComposer.PairwiseFactory ()) [] let scan<'T,'State> f (z:'State) (source : seq<'T>) = @@ -2119,15 +2050,15 @@ namespace Microsoft.FSharp.Collections *) [] let takeWhile p (source: seq<_>) = - source |> seqFactory (fun () -> upcast SeqComposer.TakeWhile p) + source |> seqFactory (SeqComposer.TakeWhileFactory p) [] let skip count (source: seq<_>) = - source |> seqFactory (fun () -> upcast SeqComposer.Skip count) + source |> seqFactory (SeqComposer.SkipFactory count) [] let skipWhile p (source: seq<_>) = - source |> seqFactory (fun () -> upcast SeqComposer.SkipWhile p) + source |> seqFactory (SeqComposer.SkipWhileFactory p) [] let forall2 p (source1: seq<_>) (source2: seq<_>) = From 751d54ca820171ca32f1d8e070a5b8eb03d447f4 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 7 Oct 2016 20:30:18 +1100 Subject: [PATCH 012/286] Remove unused member --- src/fsharp/FSharp.Core/seq.fs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 655ff4fb830..f39da6f8bc6 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -819,8 +819,6 @@ namespace Microsoft.FSharp.Collections type [] SeqComponentFactory<'T,'U> () = abstract Create<'V> : SeqComponent<'U,'V> -> SeqComponent<'T,'V> - - member __.Compose<'V> (next:SeqComponent<'U,'V>) = Unchecked.defaultof<_> and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = inherit SeqComponentFactory<'T,'V> () From 441a9b19642761a743d5728f9a11575808fe2c88 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Oct 2016 06:55:59 +1100 Subject: [PATCH 013/286] Simplified ProcessNext call by creating Result object Due to the bottom-up build process I now have a consistent output signature, which allowed it to be wrapped in an single object rather than being passed up and down the chain of ProcessNext calls. --- src/fsharp/FSharp.Core/seq.fs | 222 +++++++++++++++++----------------- 1 file changed, 114 insertions(+), 108 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index f39da6f8bc6..299b493a181 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -817,107 +817,123 @@ namespace Microsoft.FSharp.Collections let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) + type Result<'T>() = + let mutable halted = false + + member __.StopFurtherProcessing () = halted <- true + member __.Halted = halted + + member val Current = Unchecked.defaultof<'T> with get, set + type [] SeqComponentFactory<'T,'U> () = - abstract Create<'V> : SeqComponent<'U,'V> -> SeqComponent<'T,'V> + abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V> and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = inherit SeqComponentFactory<'T,'V> () - override __.Create<'W> (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create (second.Create next) + override __.Create<'W> (result:Result<'W>) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create result (second.Create result next) + + and ChooseFactory<'T,'U> (filter:'T->option<'U>) = + inherit SeqComponentFactory<'T,'U> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next) + + and FilterFactory<'T> (filter:'T->bool) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next) - - and FilterFactory<'T> (filter:'T->bool) = - inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Filter (filter, next) + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () - override __.Create<'V> (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next) + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (perdicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next) + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next) and TakeWhileFactory<'T> (perdicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, next) + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, result, next) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, next) - - and ChooseFactory<'T,'U> (filter:'T->option<'U>) = - inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next) + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next) and [] SeqComponent<'T,'U> () = - abstract ProcessNext : input:'T * halt:byref * output:byref<'U> -> bool + abstract ProcessNext : input:'T -> bool abstract OnComplete : unit -> unit - abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> - abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> + abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> + abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> default __.OnComplete () = () - default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) - default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) + default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) + default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) - and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) = + and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqComponent<'U,'V>) = inherit SeqComponent<'T,'V>() - default this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) + override __.ProcessNext (input:'T) : bool = + match choose input with + | Some value -> Helpers.avoidTailCall (next.ProcessNext value) + | None -> false - override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = - next.ProcessNext (map input, &halted, &output) + and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>() - and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) = + default this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) + + override __.ProcessNext (input:'T) : bool = + if filter input then + Helpers.avoidTailCall (next.ProcessNext input) + else + false + + and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqComponent<'U,'V>) = inherit SeqComponent<'T,'V>() - override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = - let u = map input - if filter u then - next.ProcessNext (u, &halted, &output) + override __.ProcessNext (input:'T) : bool = + if filter input then + Helpers.avoidTailCall (next.ProcessNext (map input)) else false - and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqComponent<'U,'V>) = + and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) = inherit SeqComponent<'T,'V>() - let mutable idx = 0 + override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) - override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = - idx <- idx + 1 - next.ProcessNext(mapi (idx-1) input, &halted, &output) + override __.ProcessNext (input:'T) : bool = + Helpers.avoidTailCall (next.ProcessNext (map input)) - and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) = + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) = inherit SeqComponent<'T,'V>() - default this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) - - override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = - if filter input then - next.ProcessNext (input, &halted, &output) + override __.ProcessNext (input:'T) : bool = + let u = map input + if filter u then + Helpers.avoidTailCall (next.ProcessNext u) else false - and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqComponent<'U,'V>) = + and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqComponent<'U,'V>) = inherit SeqComponent<'T,'V>() - override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = - if filter input then - next.ProcessNext (map input, &halted, &output) - else - false + let mutable idx = 0 + + override __.ProcessNext (input:'T) : bool = + idx <- idx + 1 + Helpers.avoidTailCall (next.ProcessNext (mapi (idx-1) input)) and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) = inherit SeqComponent<'T,'V>() @@ -925,7 +941,7 @@ namespace Microsoft.FSharp.Collections let mutable isFirst = true let mutable lastValue = Unchecked.defaultof<'T> - override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = + override __.ProcessNext (input:'T) : bool = if isFirst then lastValue <- input isFirst <- false @@ -933,19 +949,19 @@ namespace Microsoft.FSharp.Collections else let currentPair = lastValue, input lastValue <- input - next.ProcessNext(currentPair, &halted, &output) + Helpers.avoidTailCall (next.ProcessNext currentPair) and Skip<'T,'V> (skipCount:int, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>() let mutable count = 0 - override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = + override __.ProcessNext (input:'T) : bool = if count < skipCount then count <- count + 1 false else - next.ProcessNext (input, &halted, &output) + Helpers.avoidTailCall (next.ProcessNext input) override __.OnComplete () = if count < skipCount then @@ -953,18 +969,34 @@ namespace Microsoft.FSharp.Collections invalidOpFmt "tried to skip {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - and Take<'T,'V> (takeCount:int, next:SeqComponent<'T,'V>) = + and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>() + + let mutable skip = true + + override __.ProcessNext (input:'T) : bool = + if skip then + skip <- predicate input + if skip then + false + else + Helpers.avoidTailCall (next.ProcessNext input) + else + Helpers.avoidTailCall (next.ProcessNext input) + + and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>() let mutable count = 0 - override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = + override __.ProcessNext (input:'T) : bool = if count < takeCount then count <- count + 1 - halted <- count = takeCount - next.ProcessNext (input, &halted, &output) + if count = takeCount then + result.StopFurtherProcessing () + next.ProcessNext input else - halted <- true + result.StopFurtherProcessing () false override __.OnComplete () = @@ -973,44 +1005,21 @@ namespace Microsoft.FSharp.Collections invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) = + and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>() - let mutable skip = true - - override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = - if skip then - skip <- predicate input - if skip then - false - else - next.ProcessNext (input, &halted, &output) - else - next.ProcessNext (input, &halted, &output) - - and TakeWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) = - inherit SeqComponent<'T,'V>() - - override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = + override __.ProcessNext (input:'T) : bool = if predicate input then - next.ProcessNext(input, &halted, &output) + next.ProcessNext input else - halted <- true + result.StopFurtherProcessing () false - and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqComponent<'U,'V>) = - inherit SeqComponent<'T,'V>() - - override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool = - match choose input with - | Some value -> next.ProcessNext (value, &halted, &output) - | None -> false - - and Tail<'T> () = + and Tail<'T> (result:Result<'T>) = inherit SeqComponent<'T,'T>() - override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool = - output <- input + override __.ProcessNext (input:'T) : bool = + result.Current <- input true type SeqProcessNextStates = @@ -1018,16 +1027,14 @@ namespace Microsoft.FSharp.Collections | Finished = 2 | InProcess = 3 - type SeqComposedEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) = + type SeqComposedEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = let mutable state = SeqProcessNextStates.NotStarted - let mutable current = Unchecked.defaultof<'U> - let mutable halted = false let mutable source = enumerator let rec moveNext () = - if (not halted) && source.MoveNext () then - if t2u.ProcessNext (source.Current, &halted, ¤t) then + if (not result.Halted) && source.MoveNext () then + if t2u.ProcessNext source.Current then true else moveNext () @@ -1054,19 +1061,17 @@ namespace Microsoft.FSharp.Collections match state with | SeqProcessNextStates.NotStarted -> notStarted() | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> current + | _ -> result.Current - type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) = + type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = let mutable state = SeqProcessNextStates.NotStarted - let mutable current = Unchecked.defaultof<'U> - let mutable halted = false let mutable idx = 0 let rec moveNext () = - if (not halted) && idx < array.Length then + if (not result.Halted) && idx < array.Length then idx <- idx+1 - if t2u.ProcessNext (array.[idx-1], &halted, ¤t) then + if t2u.ProcessNext array.[idx-1] then true else moveNext () @@ -1090,20 +1095,18 @@ namespace Microsoft.FSharp.Collections match state with | SeqProcessNextStates.NotStarted -> notStarted() | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> current + | _ -> result.Current - type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>) = + type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = let mutable state = SeqProcessNextStates.NotStarted - let mutable current = Unchecked.defaultof<'U> - let mutable halted = false let mutable list = alist let rec moveNext () = - match halted, list with + match result.Halted, list with | false, head::tail -> list <- tail - if t2u.ProcessNext (head, &halted, ¤t) then + if t2u.ProcessNext head then true else moveNext () @@ -1126,7 +1129,7 @@ namespace Microsoft.FSharp.Collections match state with | SeqProcessNextStates.NotStarted -> notStarted() | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> current + | _ -> result.Current [] type ComposableEnumerable<'T> () = @@ -1136,7 +1139,8 @@ namespace Microsoft.FSharp.Collections inherit ComposableEnumerable<'U>() let getEnumerator () : IEnumerator<'U> = - Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create (Tail ()))) + let result = Result<'U> () + Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) interface IEnumerable with member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ()) @@ -1167,7 +1171,8 @@ namespace Microsoft.FSharp.Collections inherit ComposableEnumerable<'U>() let getEnumerator () : IEnumerator<'U> = - Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create (Tail ()))) + let result = Result<'U> () + Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result)) interface IEnumerable with member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ()) @@ -1199,7 +1204,8 @@ namespace Microsoft.FSharp.Collections inherit ComposableEnumerable<'U>() let getEnumerator () : IEnumerator<'U> = - Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create (Tail ()))) + let result = Result<'U> () + Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result)) interface IEnumerable with member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ()) From 16461ea2045674ca4429e82544e5a4b953688e90 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Oct 2016 10:36:05 +1100 Subject: [PATCH 014/286] default -> override --- src/fsharp/FSharp.Core/seq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 299b493a181..bd93cfdd017 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -891,7 +891,7 @@ namespace Microsoft.FSharp.Collections and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>() - default this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) + override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) override __.ProcessNext (input:'T) : bool = if filter input then From 9c2e7d4a03dae014167ee0f5c8e40a08997b1310 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Oct 2016 19:35:08 +1100 Subject: [PATCH 015/286] OptimizedClosure for mapi --- src/fsharp/FSharp.Core/seq.fs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index bd93cfdd017..62711b6c7d4 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -930,10 +930,11 @@ namespace Microsoft.FSharp.Collections inherit SeqComponent<'T,'V>() let mutable idx = 0 + let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi override __.ProcessNext (input:'T) : bool = idx <- idx + 1 - Helpers.avoidTailCall (next.ProcessNext (mapi (idx-1) input)) + Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) = inherit SeqComponent<'T,'V>() @@ -1156,14 +1157,14 @@ namespace Microsoft.FSharp.Collections // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder // // let enumerator = enumerable.GetEnumerator () -// let components = current () -// let mutable output = Unchecked.defaultof<'U> -// let mutable halt = false +// let result = Result<'U> () +// +// let components = current.Create result (Tail result) // // let mutable state = initialState -// while (not halt) && enumerator.MoveNext () do -// if components.ProcessNext (enumerator.Current, &halt, &output) then -// state <- folder'.Invoke (state, output) +// while (not result.Halted) && enumerator.MoveNext () do +// if components.ProcessNext (enumerator.Current) then +// state <- folder'.Invoke (state, result.Current) // // state @@ -1188,14 +1189,13 @@ namespace Microsoft.FSharp.Collections // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder // // let mutable idx = 0 -// let components = current () -// let mutable current = Unchecked.defaultof<'U> -// let mutable halt = false +// let result = Result<'U> () +// let components = current.Create result (Tail result) // // let mutable state = initialState -// while (not halt) && idx < array.Length do -// if components.ProcessNext (array.[idx], &halt, ¤t) then -// state <- folder'.Invoke(state, current) +// while (not result.Halted) && idx < array.Length do +// if components.ProcessNext array.[idx] then +// state <- folder'.Invoke(state, result.Current) // idx <- idx + 1 // // state From 86d8781037360e5cc9bfec9eff7223c3d3a43f6d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Oct 2016 20:19:46 +1100 Subject: [PATCH 016/286] Consolidated code in base class ensuring performance Retained MoveNext in derived class to ensure we didn't add an extra virtual call into the call stack. --- src/fsharp/FSharp.Core/seq.fs | 144 ++++++++++++++-------------------- 1 file changed, 60 insertions(+), 84 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 62711b6c7d4..89b18b6f2db 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -817,9 +817,16 @@ namespace Microsoft.FSharp.Collections let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) + type SeqProcessNextStates = + | NotStarted = 1 + | Finished = 2 + | InProcess = 3 + type Result<'T>() = let mutable halted = false + member val SeqState = SeqProcessNextStates.NotStarted with get, set + member __.StopFurtherProcessing () = halted <- true member __.Halted = halted @@ -1023,15 +1030,25 @@ namespace Microsoft.FSharp.Collections result.Current <- input true - type SeqProcessNextStates = - | NotStarted = 1 - | Finished = 2 - | InProcess = 3 + [] + type ComposedEnumerator<'T>(result:Result<'T>) = + interface IDisposable with + member __.Dispose() : unit = () - type SeqComposedEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = - let mutable state = SeqProcessNextStates.NotStarted + interface IEnumerator with + member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current + member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)" + member __.Reset () : unit = noReset () - let mutable source = enumerator + interface IEnumerator<'T> with + member __.Current = + match result.SeqState with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> result.Current + + type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = + inherit ComposedEnumerator<'U>(result) let rec moveNext () = if (not result.Halted) && source.MoveNext () then @@ -1040,32 +1057,20 @@ namespace Microsoft.FSharp.Collections else moveNext () else - state <- SeqProcessNextStates.Finished + result.SeqState <- SeqProcessNextStates.Finished t2u.OnComplete () false - interface IDisposable with - member __.Dispose():unit = - match source with - | null -> () - | _ -> source.Dispose (); source <- Unchecked.defaultof<_> - interface IEnumerator with - member this.Current : obj = box (Helpers.UpcastEnumerator this).Current member __.MoveNext () = - state <- SeqProcessNextStates.InProcess + result.SeqState <- SeqProcessNextStates.InProcess moveNext () - member __.Reset () : unit = noReset () - interface IEnumerator<'U> with - member __.Current = - match state with - | SeqProcessNextStates.NotStarted -> notStarted() - | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> result.Current + interface IDisposable with + member __.Dispose() = source.Dispose () type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = - let mutable state = SeqProcessNextStates.NotStarted + inherit ComposedEnumerator<'U>(result) let mutable idx = 0 @@ -1077,77 +1082,58 @@ namespace Microsoft.FSharp.Collections else moveNext () else - state <- SeqProcessNextStates.Finished + result.SeqState <- SeqProcessNextStates.Finished t2u.OnComplete () false - interface IDisposable with - member __.Dispose() : unit = () - interface IEnumerator with - member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current member __.MoveNext () = - state <- SeqProcessNextStates.InProcess + result.SeqState <- SeqProcessNextStates.InProcess moveNext () - member __.Reset () : unit = noReset () - - interface IEnumerator<'U> with - member __.Current = - match state with - | SeqProcessNextStates.NotStarted -> notStarted() - | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> result.Current type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = - let mutable state = SeqProcessNextStates.NotStarted + inherit ComposedEnumerator<'U>(result) let mutable list = alist - let rec moveNext () = - match result.Halted, list with + let rec moveNext current = + match result.Halted, current with | false, head::tail -> - list <- tail if t2u.ProcessNext head then + list <- tail true else - moveNext () - | _ -> state <- SeqProcessNextStates.Finished - t2u.OnComplete () - false - - interface IDisposable with - member __.Dispose() : unit = () + moveNext tail + | _ -> + result.SeqState <- SeqProcessNextStates.Finished + t2u.OnComplete () + false interface IEnumerator with - member this.Current : obj = box (this:>IEnumerator<'U>).Current member __.MoveNext () = - state <- SeqProcessNextStates.InProcess - moveNext () - member __.Reset () : unit = noReset () - - interface IEnumerator<'U> with - member __.Current = - match state with - | SeqProcessNextStates.NotStarted -> notStarted() - | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> result.Current + result.SeqState <- SeqProcessNextStates.InProcess + moveNext list [] type ComposableEnumerable<'T> () = abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> + interface IEnumerable with + member this.GetEnumerator () : IEnumerator = + let genericEnumerable = Helpers.UpcastEnumerable this + let genericEnumerator = genericEnumerable.GetEnumerator () + Helpers.UpcastEnumeratorNonGeneric genericEnumerator + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" + type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = inherit ComposableEnumerable<'U>() - let getEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) - - interface IEnumerable with - member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ()) - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = getEnumerator () + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, ComposedFactory (current, next))) @@ -1171,15 +1157,10 @@ namespace Microsoft.FSharp.Collections type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) = inherit ComposableEnumerable<'U>() - let getEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result)) - - interface IEnumerable with - member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ()) - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = getEnumerator () + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, ComposedFactory (current, next))) @@ -1203,15 +1184,10 @@ namespace Microsoft.FSharp.Collections type SeqListEnumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) = inherit ComposableEnumerable<'U>() - let getEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result)) - - interface IEnumerable with - member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ()) - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = getEnumerator () + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next))) From 3a3fd6fc9b90b4c1c97a3250b10e626ab40797fb Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Oct 2016 20:38:54 +1100 Subject: [PATCH 017/286] Added ComposableEnumerableFactoryHelper Sweeping up common functionality --- src/fsharp/FSharp.Core/seq.fs | 46 ++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 89b18b6f2db..5c88f61a6cc 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1127,16 +1127,28 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" - type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = + [] + type ComposableEnumerableFactoryHelper<'T,'U> (seqComponentFactory:SeqComponentFactory<'T,'U>) = inherit ComposableEnumerable<'U>() + member __.FactoryCompose next = + ComposedFactory (seqComponentFactory, next) + + member __.CreateSeqComponent () = + let result = Result<'U> () + let seqComponent = seqComponentFactory.Create result (Tail result) + result, seqComponent + + type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) = + inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory) + interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) + let result, seqComponent = this.CreateSeqComponent () + Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), seqComponent, result)) - override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, ComposedFactory (current, next))) + override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, this.FactoryCompose next)) // interface ISeqEnumerable<'U> with // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = @@ -1154,16 +1166,16 @@ namespace Microsoft.FSharp.Collections // // state - type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) = - inherit ComposableEnumerable<'U>() + type SeqArrayEnumerable<'T,'U>(array:array<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) = + inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory) interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result)) + let result, seqComponent = this.CreateSeqComponent () + Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, seqComponent, result)) - override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, ComposedFactory (current, next))) + override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, this.FactoryCompose next)) // interface ISeqEnumerable<'U> with // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = @@ -1181,16 +1193,16 @@ namespace Microsoft.FSharp.Collections // // state - type SeqListEnumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) = - inherit ComposableEnumerable<'U>() + type SeqListEnumerable<'T,'U>(alist:list<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) = + inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory) interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result)) + let result, seqComponent = this.CreateSeqComponent () + Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, seqComponent, result)) - override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next))) + override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, this.FactoryCompose next)) #if FX_NO_ICLONEABLE From 7ff0fb091d99d85ae60441f2c6ed6968784bacfc Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 05:36:56 +1100 Subject: [PATCH 018/286] init(Infinite)? implementations Not as simple as it should be due to the original implementation deciding to evaluate Current in a lazy fashion. Comments have been splattered around hopefully describing the situation in enough detail. --- src/fsharp/FSharp.Core/seq.fs | 92 ++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 5c88f61a6cc..2c74e6f63ad 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -878,12 +878,18 @@ namespace Microsoft.FSharp.Collections and [] SeqComponent<'T,'U> () = abstract ProcessNext : input:'T -> bool abstract OnComplete : unit -> unit + + // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip + // and it can only do it at the start of a sequence + abstract Skipping : unit -> bool abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> default __.OnComplete () = () + default __.Skipping () = false + default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) @@ -964,6 +970,13 @@ namespace Microsoft.FSharp.Collections let mutable count = 0 + override __.Skipping () = + if count < skipCount then + count <- count + 1 + true + else + false + override __.ProcessNext (input:'T) : bool = if count < skipCount then count <- count + 1 @@ -1204,6 +1217,79 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, this.FactoryCompose next)) + // 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. + type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, result:Result<'U>) = + inherit ComposedEnumerator<'U>(result) + + // 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 + let terminatingIdx = + if count.HasValue then + count.Value - 1 + else + System.Int32.MaxValue + + let mutable maybeSkipping = true + let mutable idx = -1 + + let rec moveNext () = + if (not result.Halted) && 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 <- t2u.Skipping () + + if maybeSkipping || t2u.ProcessNext (f idx) then + true + else + moveNext () + elif (not result.Halted) && idx = System.Int32.MaxValue then + raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + else + result.SeqState <- SeqProcessNextStates.Finished + t2u.OnComplete () + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type InitComposingEnumerable<'T,'U>(count:Nullable, f:int->'T, seqComponentFactory:SeqComponentFactory<'T,'U>) = + inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory) + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result, seqComponent = this.CreateSeqComponent () + Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, seqComponent, result)) + + override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new InitComposingEnumerable<'T,'V>(count, f, this.FactoryCompose next)) + + type InitEnumerable<'T>(count:Nullable, f:int->'T) = + inherit ComposableEnumerable<'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 else None) f + + override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = + Helpers.UpcastEnumerable (InitComposingEnumerable<'T,'V>(count, f, next)) + #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions @@ -1226,12 +1312,14 @@ namespace Microsoft.FSharp.Collections let empty<'T> = (EmptyEnumerable :> seq<'T>) [] - let initInfinite f = mkSeq (fun () -> IEnumerator.upto None f) + let initInfinite<'T> (f:int->'T) : IEnumerable<'T> = + SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable (), f)) [] let init count f = if count < 0 then invalidArgInputMustBeNonNegative "count" count - mkSeq (fun () -> IEnumerator.upto (Some (count-1)) f) + elif count = 0 then empty else + SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable count, f)) [] let iter f (source : seq<'T>) = From aa25d0cffe6b4934267180be33dec33a6973ccdd Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 06:00:07 +1100 Subject: [PATCH 019/286] Split Result object in multi-leveled Signal The plan is to then implement fold like functionality in a Tail like object that we can expose out in a public interface, so I'm trying to minimize what would be needed to be visible externally. --- src/fsharp/FSharp.Core/seq.fs | 131 +++++++++++++++++----------------- 1 file changed, 67 insertions(+), 64 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 2c74e6f63ad..9d2342a35ac 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -817,63 +817,57 @@ namespace Microsoft.FSharp.Collections let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - type SeqProcessNextStates = - | NotStarted = 1 - | Finished = 2 - | InProcess = 3 - - type Result<'T>() = + type SeqSignal () = let mutable halted = false - - member val SeqState = SeqProcessNextStates.NotStarted with get, set - member __.StopFurtherProcessing () = halted <- true member __.Halted = halted + type TailSignal<'T> () = + inherit SeqSignal () member val Current = Unchecked.defaultof<'T> with get, set type [] SeqComponentFactory<'T,'U> () = - abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V> + abstract Create<'V> : SeqSignal -> SeqComponent<'U,'V> -> SeqComponent<'T,'V> and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = inherit SeqComponentFactory<'T,'V> () - override __.Create<'W> (result:Result<'W>) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create result (second.Create result next) + override __.Create<'W> (signal:SeqSignal) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create signal (second.Create signal next) and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next) + override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter + override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map + override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next) + override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next + override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next) + override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (perdicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next) + override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next) and TakeWhileFactory<'T> (perdicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, result, next) + override __.Create<'V> (signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, signal, next) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next) + override __.Create<'V> (signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, signal, next) and [] SeqComponent<'T,'U> () = abstract ProcessNext : input:'T -> bool @@ -1005,7 +999,7 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = + and Take<'T,'V> (takeCount:int, signal:SeqSignal, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>() let mutable count = 0 @@ -1014,10 +1008,10 @@ namespace Microsoft.FSharp.Collections if count < takeCount then count <- count + 1 if count = takeCount then - result.StopFurtherProcessing () + signal.StopFurtherProcessing () next.ProcessNext input else - result.StopFurtherProcessing () + signal.StopFurtherProcessing () false override __.OnComplete () = @@ -1026,25 +1020,34 @@ namespace Microsoft.FSharp.Collections invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) = + and TakeWhile<'T,'V> (predicate:'T->bool, signal:SeqSignal, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>() override __.ProcessNext (input:'T) : bool = if predicate input then next.ProcessNext input else - result.StopFurtherProcessing () + signal.StopFurtherProcessing () false - and Tail<'T> (result:Result<'T>) = + and Tail<'T> (signal:TailSignal<'T>) = inherit SeqComponent<'T,'T>() override __.ProcessNext (input:'T) : bool = - result.Current <- input + signal.Current <- input true + type SeqEnumeratorState = + | NotStarted = 1 + | Finished = 2 + | InProcess = 3 + + type EnumeratorSignal<'T>() = + inherit TailSignal<'T>() + member val EnumeratorState = SeqEnumeratorState.NotStarted with get, set + [] - type ComposedEnumerator<'T>(result:Result<'T>) = + type ComposedEnumerator<'T>(signal:EnumeratorSignal<'T>) = interface IDisposable with member __.Dispose() : unit = () @@ -1055,62 +1058,62 @@ namespace Microsoft.FSharp.Collections interface IEnumerator<'T> with member __.Current = - match result.SeqState with - | SeqProcessNextStates.NotStarted -> notStarted() - | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> result.Current + match signal.EnumeratorState with + | SeqEnumeratorState.NotStarted -> notStarted() + | SeqEnumeratorState.Finished -> alreadyFinished() + | _ -> signal.Current - type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = - inherit ComposedEnumerator<'U>(result) + type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) = + inherit ComposedEnumerator<'U>(signal) let rec moveNext () = - if (not result.Halted) && source.MoveNext () then + if (not signal.Halted) && source.MoveNext () then if t2u.ProcessNext source.Current then true else moveNext () else - result.SeqState <- SeqProcessNextStates.Finished + signal.EnumeratorState <- SeqEnumeratorState.Finished t2u.OnComplete () false interface IEnumerator with member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess + signal.EnumeratorState <- SeqEnumeratorState.InProcess moveNext () interface IDisposable with member __.Dispose() = source.Dispose () - type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = - inherit ComposedEnumerator<'U>(result) + type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) = + inherit ComposedEnumerator<'U>(signal) let mutable idx = 0 let rec moveNext () = - if (not result.Halted) && idx < array.Length then + if (not signal.Halted) && idx < array.Length then idx <- idx+1 if t2u.ProcessNext array.[idx-1] then true else moveNext () else - result.SeqState <- SeqProcessNextStates.Finished + signal.EnumeratorState <- SeqEnumeratorState.Finished t2u.OnComplete () false interface IEnumerator with member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess + signal.EnumeratorState <- SeqEnumeratorState.InProcess moveNext () - type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = - inherit ComposedEnumerator<'U>(result) + type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) = + inherit ComposedEnumerator<'U>(signal) let mutable list = alist let rec moveNext current = - match result.Halted, current with + match signal.Halted, current with | false, head::tail -> if t2u.ProcessNext head then list <- tail @@ -1118,13 +1121,13 @@ namespace Microsoft.FSharp.Collections else moveNext tail | _ -> - result.SeqState <- SeqProcessNextStates.Finished + signal.EnumeratorState <- SeqEnumeratorState.Finished t2u.OnComplete () false interface IEnumerator with member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess + signal.EnumeratorState <- SeqEnumeratorState.InProcess moveNext list [] @@ -1148,17 +1151,17 @@ namespace Microsoft.FSharp.Collections ComposedFactory (seqComponentFactory, next) member __.CreateSeqComponent () = - let result = Result<'U> () - let seqComponent = seqComponentFactory.Create result (Tail result) - result, seqComponent + let signal = EnumeratorSignal<'U> () + let seqComponent = seqComponentFactory.Create signal (Tail signal) + signal, seqComponent type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) = inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory) interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = - let result, seqComponent = this.CreateSeqComponent () - Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), seqComponent, result)) + let signal, seqComponent = this.CreateSeqComponent () + Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), seqComponent, signal)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, this.FactoryCompose next)) @@ -1184,8 +1187,8 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = - let result, seqComponent = this.CreateSeqComponent () - Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, seqComponent, result)) + let signal, seqComponent = this.CreateSeqComponent () + Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, seqComponent, signal)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, this.FactoryCompose next)) @@ -1211,8 +1214,8 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = - let result, seqComponent = this.CreateSeqComponent () - Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, seqComponent, result)) + let signal, seqComponent = this.CreateSeqComponent () + Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, seqComponent, signal)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, this.FactoryCompose next)) @@ -1227,8 +1230,8 @@ namespace Microsoft.FSharp.Collections // 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. - type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, result:Result<'U>) = - inherit ComposedEnumerator<'U>(result) + type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) = + inherit ComposedEnumerator<'U>(signal) // 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 @@ -1242,7 +1245,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = -1 let rec moveNext () = - if (not result.Halted) && idx < terminatingIdx then + if (not signal.Halted) && idx < terminatingIdx then idx <- idx + 1 if maybeSkipping then @@ -1254,16 +1257,16 @@ namespace Microsoft.FSharp.Collections true else moveNext () - elif (not result.Halted) && idx = System.Int32.MaxValue then + elif (not signal.Halted) && idx = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else - result.SeqState <- SeqProcessNextStates.Finished + signal.EnumeratorState <- SeqEnumeratorState.Finished t2u.OnComplete () false interface IEnumerator with member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess + signal.EnumeratorState <- SeqEnumeratorState.InProcess moveNext () type InitComposingEnumerable<'T,'U>(count:Nullable, f:int->'T, seqComponentFactory:SeqComponentFactory<'T,'U>) = @@ -1271,8 +1274,8 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = - let result, seqComponent = this.CreateSeqComponent () - Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, seqComponent, result)) + let signal, seqComponent = this.CreateSeqComponent () + Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, seqComponent, signal)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.UpcastEnumerable (new InitComposingEnumerable<'T,'V>(count, f, this.FactoryCompose next)) From a9f76259cd2b0d1f4759344156d9301e0e82dcb4 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 06:12:42 +1100 Subject: [PATCH 020/286] Rearranged Enumerator/Enumerable pairs together --- src/fsharp/FSharp.Core/seq.fs | 160 ++++++++++++++++++---------------- 1 file changed, 85 insertions(+), 75 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 9d2342a35ac..d56d658996f 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1046,6 +1046,8 @@ namespace Microsoft.FSharp.Collections inherit TailSignal<'T>() member val EnumeratorState = SeqEnumeratorState.NotStarted with get, set + // ----- base classes for enumerator/enumerable ----- + [] type ComposedEnumerator<'T>(signal:EnumeratorSignal<'T>) = interface IDisposable with @@ -1063,73 +1065,6 @@ namespace Microsoft.FSharp.Collections | SeqEnumeratorState.Finished -> alreadyFinished() | _ -> signal.Current - type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) = - inherit ComposedEnumerator<'U>(signal) - - let rec moveNext () = - if (not signal.Halted) && source.MoveNext () then - if t2u.ProcessNext source.Current then - true - else - moveNext () - else - signal.EnumeratorState <- SeqEnumeratorState.Finished - t2u.OnComplete () - false - - interface IEnumerator with - member __.MoveNext () = - signal.EnumeratorState <- SeqEnumeratorState.InProcess - moveNext () - - interface IDisposable with - member __.Dispose() = source.Dispose () - - type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) = - inherit ComposedEnumerator<'U>(signal) - - let mutable idx = 0 - - let rec moveNext () = - if (not signal.Halted) && idx < array.Length then - idx <- idx+1 - if t2u.ProcessNext array.[idx-1] then - true - else - moveNext () - else - signal.EnumeratorState <- SeqEnumeratorState.Finished - t2u.OnComplete () - false - - interface IEnumerator with - member __.MoveNext () = - signal.EnumeratorState <- SeqEnumeratorState.InProcess - moveNext () - - type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) = - inherit ComposedEnumerator<'U>(signal) - - let mutable list = alist - - let rec moveNext current = - match signal.Halted, current with - | false, head::tail -> - if t2u.ProcessNext head then - list <- tail - true - else - moveNext tail - | _ -> - signal.EnumeratorState <- SeqEnumeratorState.Finished - t2u.OnComplete () - false - - interface IEnumerator with - member __.MoveNext () = - signal.EnumeratorState <- SeqEnumeratorState.InProcess - moveNext list - [] type ComposableEnumerable<'T> () = abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> @@ -1155,6 +1090,30 @@ namespace Microsoft.FSharp.Collections let seqComponent = seqComponentFactory.Create signal (Tail signal) signal, seqComponent + // ----- seq ----- + + type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) = + inherit ComposedEnumerator<'U>(signal) + + let rec moveNext () = + if (not signal.Halted) && source.MoveNext () then + if t2u.ProcessNext source.Current then + true + else + moveNext () + else + signal.EnumeratorState <- SeqEnumeratorState.Finished + t2u.OnComplete () + false + + interface IEnumerator with + member __.MoveNext () = + signal.EnumeratorState <- SeqEnumeratorState.InProcess + moveNext () + + interface IDisposable with + member __.Dispose() = source.Dispose () + type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) = inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory) @@ -1171,17 +1130,41 @@ namespace Microsoft.FSharp.Collections // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder // // let enumerator = enumerable.GetEnumerator () -// let result = Result<'U> () +// let signal = TailSignal<'U> () // -// let components = current.Create result (Tail result) +// let components = seqComponentFactory.Create signal (Tail signal) // // let mutable state = initialState -// while (not result.Halted) && enumerator.MoveNext () do +// while (not signal.Halted) && enumerator.MoveNext () do // if components.ProcessNext (enumerator.Current) then -// state <- folder'.Invoke (state, result.Current) +// state <- folder'.Invoke (state, signal.Current) // // state + // ----- array ----- + + type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) = + inherit ComposedEnumerator<'U>(signal) + + let mutable idx = 0 + + let rec moveNext () = + if (not signal.Halted) && idx < array.Length then + idx <- idx+1 + if t2u.ProcessNext array.[idx-1] then + true + else + moveNext () + else + signal.EnumeratorState <- SeqEnumeratorState.Finished + t2u.OnComplete () + false + + interface IEnumerator with + member __.MoveNext () = + signal.EnumeratorState <- SeqEnumeratorState.InProcess + moveNext () + type SeqArrayEnumerable<'T,'U>(array:array<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) = inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory) @@ -1198,17 +1181,42 @@ namespace Microsoft.FSharp.Collections // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder // // let mutable idx = 0 -// let result = Result<'U> () -// let components = current.Create result (Tail result) +// let signal = TailSignal<'U> () +// let components = seqComponentFactory.Create signal (Tail signal) // // let mutable state = initialState -// while (not result.Halted) && idx < array.Length do +// while (not signal.Halted) && idx < array.Length do // if components.ProcessNext array.[idx] then -// state <- folder'.Invoke(state, result.Current) +// state <- folder'.Invoke(state, signal.Current) // idx <- idx + 1 // // state + // ----- list ----- + + type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) = + inherit ComposedEnumerator<'U>(signal) + + let mutable list = alist + + let rec moveNext current = + match signal.Halted, current with + | false, head::tail -> + if t2u.ProcessNext head then + list <- tail + true + else + moveNext tail + | _ -> + signal.EnumeratorState <- SeqEnumeratorState.Finished + t2u.OnComplete () + false + + interface IEnumerator with + member __.MoveNext () = + signal.EnumeratorState <- SeqEnumeratorState.InProcess + moveNext list + type SeqListEnumerable<'T,'U>(alist:list<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) = inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory) @@ -1220,6 +1228,8 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, this.FactoryCompose next)) + // ----- 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 From 960fa27fbbee1db012b91d908d773a0d696fce69 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 06:32:14 +1100 Subject: [PATCH 021/286] Fix bug in skipping an init seq --- src/fsharp/FSharp.Core/seq.fs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index d56d658996f..ee0f8728139 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1263,7 +1263,9 @@ namespace Microsoft.FSharp.Collections // triggered, we stay triggered. maybeSkipping <- t2u.Skipping () - if maybeSkipping || t2u.ProcessNext (f idx) then + if maybeSkipping then + moveNext () + elif t2u.ProcessNext (f idx) then true else moveNext () From 5088eeffeb246bc615c2c898125f0e140664ad12 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 08:19:24 +1100 Subject: [PATCH 022/286] Restoring to last successful build server build I probably don't have any more time today to bug issues --- src/fsharp/FSharp.Core/seq.fs | 341 +++++++++++----------------------- 1 file changed, 113 insertions(+), 228 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ee0f8728139..89b18b6f2db 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -817,73 +817,73 @@ namespace Microsoft.FSharp.Collections let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - type SeqSignal () = + type SeqProcessNextStates = + | NotStarted = 1 + | Finished = 2 + | InProcess = 3 + + type Result<'T>() = let mutable halted = false + + member val SeqState = SeqProcessNextStates.NotStarted with get, set + member __.StopFurtherProcessing () = halted <- true member __.Halted = halted - type TailSignal<'T> () = - inherit SeqSignal () member val Current = Unchecked.defaultof<'T> with get, set type [] SeqComponentFactory<'T,'U> () = - abstract Create<'V> : SeqSignal -> SeqComponent<'U,'V> -> SeqComponent<'T,'V> + abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V> and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = inherit SeqComponentFactory<'T,'V> () - override __.Create<'W> (signal:SeqSignal) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create signal (second.Create signal next) + override __.Create<'W> (result:Result<'W>) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create result (second.Create result next) and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next) + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next) + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () - override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next) + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (perdicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next) + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next) and TakeWhileFactory<'T> (perdicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, signal, next) + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, result, next) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, signal, next) + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next) and [] SeqComponent<'T,'U> () = abstract ProcessNext : input:'T -> bool abstract OnComplete : unit -> unit - - // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip - // and it can only do it at the start of a sequence - abstract Skipping : unit -> bool abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> default __.OnComplete () = () - default __.Skipping () = false - default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) @@ -964,13 +964,6 @@ namespace Microsoft.FSharp.Collections let mutable count = 0 - override __.Skipping () = - if count < skipCount then - count <- count + 1 - true - else - false - override __.ProcessNext (input:'T) : bool = if count < skipCount then count <- count + 1 @@ -999,7 +992,7 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - and Take<'T,'V> (takeCount:int, signal:SeqSignal, next:SeqComponent<'T,'V>) = + and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>() let mutable count = 0 @@ -1008,10 +1001,10 @@ namespace Microsoft.FSharp.Collections if count < takeCount then count <- count + 1 if count = takeCount then - signal.StopFurtherProcessing () + result.StopFurtherProcessing () next.ProcessNext input else - signal.StopFurtherProcessing () + result.StopFurtherProcessing () false override __.OnComplete () = @@ -1020,36 +1013,25 @@ namespace Microsoft.FSharp.Collections invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - and TakeWhile<'T,'V> (predicate:'T->bool, signal:SeqSignal, next:SeqComponent<'T,'V>) = + and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>() override __.ProcessNext (input:'T) : bool = if predicate input then next.ProcessNext input else - signal.StopFurtherProcessing () + result.StopFurtherProcessing () false - and Tail<'T> (signal:TailSignal<'T>) = + and Tail<'T> (result:Result<'T>) = inherit SeqComponent<'T,'T>() override __.ProcessNext (input:'T) : bool = - signal.Current <- input + result.Current <- input true - type SeqEnumeratorState = - | NotStarted = 1 - | Finished = 2 - | InProcess = 3 - - type EnumeratorSignal<'T>() = - inherit TailSignal<'T>() - member val EnumeratorState = SeqEnumeratorState.NotStarted with get, set - - // ----- base classes for enumerator/enumerable ----- - [] - type ComposedEnumerator<'T>(signal:EnumeratorSignal<'T>) = + type ComposedEnumerator<'T>(result:Result<'T>) = interface IDisposable with member __.Dispose() : unit = () @@ -1060,147 +1042,62 @@ namespace Microsoft.FSharp.Collections interface IEnumerator<'T> with member __.Current = - match signal.EnumeratorState with - | SeqEnumeratorState.NotStarted -> notStarted() - | SeqEnumeratorState.Finished -> alreadyFinished() - | _ -> signal.Current - - [] - type ComposableEnumerable<'T> () = - abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> - - interface IEnumerable with - member this.GetEnumerator () : IEnumerator = - let genericEnumerable = Helpers.UpcastEnumerable this - let genericEnumerator = genericEnumerable.GetEnumerator () - Helpers.UpcastEnumeratorNonGeneric genericEnumerator + match result.SeqState with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> result.Current - interface IEnumerable<'T> with - member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" - - [] - type ComposableEnumerableFactoryHelper<'T,'U> (seqComponentFactory:SeqComponentFactory<'T,'U>) = - inherit ComposableEnumerable<'U>() - - member __.FactoryCompose next = - ComposedFactory (seqComponentFactory, next) - - member __.CreateSeqComponent () = - let signal = EnumeratorSignal<'U> () - let seqComponent = seqComponentFactory.Create signal (Tail signal) - signal, seqComponent - - // ----- seq ----- - - type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) = - inherit ComposedEnumerator<'U>(signal) + type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = + inherit ComposedEnumerator<'U>(result) let rec moveNext () = - if (not signal.Halted) && source.MoveNext () then + if (not result.Halted) && source.MoveNext () then if t2u.ProcessNext source.Current then true else moveNext () else - signal.EnumeratorState <- SeqEnumeratorState.Finished + result.SeqState <- SeqProcessNextStates.Finished t2u.OnComplete () false interface IEnumerator with member __.MoveNext () = - signal.EnumeratorState <- SeqEnumeratorState.InProcess + result.SeqState <- SeqProcessNextStates.InProcess moveNext () interface IDisposable with member __.Dispose() = source.Dispose () - type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) = - inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory) - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let signal, seqComponent = this.CreateSeqComponent () - Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), seqComponent, signal)) - - override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, this.FactoryCompose next)) - -// interface ISeqEnumerable<'U> with -// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = -// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder -// -// let enumerator = enumerable.GetEnumerator () -// let signal = TailSignal<'U> () -// -// let components = seqComponentFactory.Create signal (Tail signal) -// -// let mutable state = initialState -// while (not signal.Halted) && enumerator.MoveNext () do -// if components.ProcessNext (enumerator.Current) then -// state <- folder'.Invoke (state, signal.Current) -// -// state - - // ----- array ----- - - type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) = - inherit ComposedEnumerator<'U>(signal) + type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = + inherit ComposedEnumerator<'U>(result) let mutable idx = 0 let rec moveNext () = - if (not signal.Halted) && idx < array.Length then + if (not result.Halted) && idx < array.Length then idx <- idx+1 if t2u.ProcessNext array.[idx-1] then true else moveNext () else - signal.EnumeratorState <- SeqEnumeratorState.Finished + result.SeqState <- SeqProcessNextStates.Finished t2u.OnComplete () false interface IEnumerator with member __.MoveNext () = - signal.EnumeratorState <- SeqEnumeratorState.InProcess + result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type SeqArrayEnumerable<'T,'U>(array:array<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) = - inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory) - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let signal, seqComponent = this.CreateSeqComponent () - Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, seqComponent, signal)) - - override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, this.FactoryCompose next)) - -// interface ISeqEnumerable<'U> with -// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = -// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder -// -// let mutable idx = 0 -// let signal = TailSignal<'U> () -// let components = seqComponentFactory.Create signal (Tail signal) -// -// let mutable state = initialState -// while (not signal.Halted) && idx < array.Length do -// if components.ProcessNext array.[idx] then -// state <- folder'.Invoke(state, signal.Current) -// idx <- idx + 1 -// -// state - - // ----- list ----- - - type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) = - inherit ComposedEnumerator<'U>(signal) + type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = + inherit ComposedEnumerator<'U>(result) let mutable list = alist let rec moveNext current = - match signal.Halted, current with + match result.Halted, current with | false, head::tail -> if t2u.ProcessNext head then list <- tail @@ -1208,102 +1105,92 @@ namespace Microsoft.FSharp.Collections else moveNext tail | _ -> - signal.EnumeratorState <- SeqEnumeratorState.Finished + result.SeqState <- SeqProcessNextStates.Finished t2u.OnComplete () false interface IEnumerator with member __.MoveNext () = - signal.EnumeratorState <- SeqEnumeratorState.InProcess + result.SeqState <- SeqProcessNextStates.InProcess moveNext list - type SeqListEnumerable<'T,'U>(alist:list<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) = - inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory) + [] + type ComposableEnumerable<'T> () = + abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> + + interface IEnumerable with + member this.GetEnumerator () : IEnumerator = + let genericEnumerable = Helpers.UpcastEnumerable this + let genericEnumerator = genericEnumerable.GetEnumerator () + Helpers.UpcastEnumeratorNonGeneric genericEnumerator + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" + + type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = + inherit ComposableEnumerable<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = - let signal, seqComponent = this.CreateSeqComponent () - Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, seqComponent, signal)) - - override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, this.FactoryCompose next)) - - // ----- 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. - type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) = - inherit ComposedEnumerator<'U>(signal) - - // 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 - let terminatingIdx = - if count.HasValue then - count.Value - 1 - else - System.Int32.MaxValue + let result = Result<'U> () + Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) - let mutable maybeSkipping = true - let mutable idx = -1 - - let rec moveNext () = - if (not signal.Halted) && 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 <- t2u.Skipping () - - if maybeSkipping then - moveNext () - elif t2u.ProcessNext (f idx) then - true - else - moveNext () - elif (not signal.Halted) && idx = System.Int32.MaxValue then - raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) - else - signal.EnumeratorState <- SeqEnumeratorState.Finished - t2u.OnComplete () - false + override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, ComposedFactory (current, next))) - interface IEnumerator with - member __.MoveNext () = - signal.EnumeratorState <- SeqEnumeratorState.InProcess - moveNext () +// interface ISeqEnumerable<'U> with +// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = +// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder +// +// let enumerator = enumerable.GetEnumerator () +// let result = Result<'U> () +// +// let components = current.Create result (Tail result) +// +// let mutable state = initialState +// while (not result.Halted) && enumerator.MoveNext () do +// if components.ProcessNext (enumerator.Current) then +// state <- folder'.Invoke (state, result.Current) +// +// state - type InitComposingEnumerable<'T,'U>(count:Nullable, f:int->'T, seqComponentFactory:SeqComponentFactory<'T,'U>) = - inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory) + type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) = + inherit ComposableEnumerable<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = - let signal, seqComponent = this.CreateSeqComponent () - Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, seqComponent, signal)) + let result = Result<'U> () + Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result)) - override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new InitComposingEnumerable<'T,'V>(count, f, this.FactoryCompose next)) + override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, ComposedFactory (current, next))) - type InitEnumerable<'T>(count:Nullable, f:int->'T) = - inherit ComposableEnumerable<'T>() +// interface ISeqEnumerable<'U> with +// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = +// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder +// +// let mutable idx = 0 +// let result = Result<'U> () +// let components = current.Create result (Tail result) +// +// let mutable state = initialState +// while (not result.Halted) && idx < array.Length do +// if components.ProcessNext array.[idx] then +// state <- folder'.Invoke(state, result.Current) +// idx <- idx + 1 +// +// state - 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 else None) f + type SeqListEnumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) = + inherit ComposableEnumerable<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result)) - override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = - Helpers.UpcastEnumerable (InitComposingEnumerable<'T,'V>(count, f, next)) + override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next))) #if FX_NO_ICLONEABLE @@ -1327,14 +1214,12 @@ namespace Microsoft.FSharp.Collections let empty<'T> = (EmptyEnumerable :> seq<'T>) [] - let initInfinite<'T> (f:int->'T) : IEnumerable<'T> = - SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable (), f)) + let initInfinite f = mkSeq (fun () -> IEnumerator.upto None f) [] let init count f = if count < 0 then invalidArgInputMustBeNonNegative "count" count - elif count = 0 then empty else - SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable count, f)) + mkSeq (fun () -> IEnumerator.upto (Some (count-1)) f) [] let iter f (source : seq<'T>) = From 60fc2a1f3a7b6d28e03a89c9ed568020153e71b3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 13:32:57 +1100 Subject: [PATCH 023/286] init/initInfinite Try again, without any other clutter --- src/fsharp/FSharp.Core/seq.fs | 97 +++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 3 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 89b18b6f2db..027cdbbd5bf 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -879,11 +879,17 @@ namespace Microsoft.FSharp.Collections abstract ProcessNext : input:'T -> bool abstract OnComplete : unit -> unit + // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip + // and it can only do it at the start of a sequence + abstract Skipping : unit -> bool + abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> default __.OnComplete () = () + default __.Skipping () = false + default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) @@ -964,6 +970,13 @@ namespace Microsoft.FSharp.Collections let mutable count = 0 + override __.Skipping () = + if count < skipCount then + count <- count + 1 + true + else + false + override __.ProcessNext (input:'T) : bool = if count < skipCount then count <- count + 1 @@ -1193,6 +1206,82 @@ namespace Microsoft.FSharp.Collections Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next))) + // 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. + type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:Result<'U>) = + inherit ComposedEnumerator<'U>(signal) + + // 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 + let terminatingIdx = + if count.HasValue then + count.Value - 1 + else + System.Int32.MaxValue + + let mutable maybeSkipping = true + let mutable idx = -1 + + let rec moveNext () = + if (not signal.Halted) && 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 <- t2u.Skipping () + + if maybeSkipping then + moveNext () + elif t2u.ProcessNext (f idx) then + true + else + moveNext () + elif (not signal.Halted) && idx = System.Int32.MaxValue then + raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + else + signal.SeqState <- SeqProcessNextStates.Finished + t2u.OnComplete () + false + + interface IEnumerator with + member __.MoveNext () = + signal.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type InitComposingEnumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) = + inherit ComposableEnumerable<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, current.Create result (Tail result), result)) + + override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new InitComposingEnumerable<'T,'V>(count, f, ComposedFactory (current, next))) + + + type InitEnumerable<'T>(count:Nullable, f:int->'T) = + inherit ComposableEnumerable<'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 else None) f + + override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = + Helpers.UpcastEnumerable (InitComposingEnumerable<'T,'V>(count, f, next)) + #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions #else @@ -1214,12 +1303,14 @@ namespace Microsoft.FSharp.Collections let empty<'T> = (EmptyEnumerable :> seq<'T>) [] - let initInfinite f = mkSeq (fun () -> IEnumerator.upto None f) + let initInfinite<'T> (f:int->'T) : IEnumerable<'T> = + SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable (), f)) [] - let init count f = + let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> = if count < 0 then invalidArgInputMustBeNonNegative "count" count - mkSeq (fun () -> IEnumerator.upto (Some (count-1)) f) + elif count = 0 then empty else + SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable count, f)) [] let iter f (source : seq<'T>) = From 848593f7e0083b2284a71c0bd4e3d380b375f548 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 14:12:59 +1100 Subject: [PATCH 024/286] Bug fix; off by 1... --- src/fsharp/FSharp.Core/seq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 027cdbbd5bf..c34a370e500 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1277,7 +1277,7 @@ namespace Microsoft.FSharp.Collections // 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 else None) f + upto (if count.HasValue then Some (count.Value-1) else None) f override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.UpcastEnumerable (InitComposingEnumerable<'T,'V>(count, f, next)) From 78a13664c54bba25d1aa86e0cca41f843c384217 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 16:29:19 +1100 Subject: [PATCH 025/286] Moved Enumerable/Enumerator pairs into modules --- src/fsharp/FSharp.Core/seq.fs | 441 +++++++++++++++++----------------- 1 file changed, 223 insertions(+), 218 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index c34a370e500..39c3a0fdbb5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1043,244 +1043,249 @@ namespace Microsoft.FSharp.Collections result.Current <- input true - [] - type ComposedEnumerator<'T>(result:Result<'T>) = - interface IDisposable with - member __.Dispose() : unit = () - - interface IEnumerator with - member this.Current : obj = box ((Helpers.UpcastEnumerator 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 = - match result.SeqState with - | SeqProcessNextStates.NotStarted -> notStarted() - | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> result.Current - - type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = - inherit ComposedEnumerator<'U>(result) - - let rec moveNext () = - if (not result.Halted) && source.MoveNext () then - if t2u.ProcessNext source.Current then - true + module Base = + [] + type Enumerator<'T>(result:Result<'T>) = + interface IDisposable with + member __.Dispose() : unit = () + + interface IEnumerator with + member this.Current : obj = box ((Helpers.UpcastEnumerator 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 = + match result.SeqState with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> result.Current + + + [] + type Enumerable<'T> () = + abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> + + interface IEnumerable with + member this.GetEnumerator () : IEnumerator = + let genericEnumerable = Helpers.UpcastEnumerable this + let genericEnumerator = genericEnumerable.GetEnumerator () + Helpers.UpcastEnumeratorNonGeneric genericEnumerator + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" + + module Enumerable = + type Enumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = + inherit Base.Enumerator<'U>(result) + + let rec moveNext () = + if (not result.Halted) && source.MoveNext () then + if t2u.ProcessNext source.Current then + true + else + moveNext () else + result.SeqState <- SeqProcessNextStates.Finished + t2u.OnComplete () + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess moveNext () - else - result.SeqState <- SeqProcessNextStates.Finished - t2u.OnComplete () - false - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () + interface IDisposable with + member __.Dispose() = source.Dispose () - interface IDisposable with - member __.Dispose() = source.Dispose () - type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = - inherit ComposedEnumerator<'U>(result) + type Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = + inherit Base.Enumerable<'U>() - let mutable idx = 0 + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Helpers.UpcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) - let rec moveNext () = - if (not result.Halted) && idx < array.Length then - idx <- idx+1 - if t2u.ProcessNext array.[idx-1] then - true + override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory (current, next))) + + // interface ISeqEnumerable<'U> with + // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = + // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + // + // let enumerator = enumerable.GetEnumerator () + // let result = Result<'U> () + // + // let components = current.Create result (Tail result) + // + // let mutable state = initialState + // while (not result.Halted) && enumerator.MoveNext () do + // if components.ProcessNext (enumerator.Current) then + // state <- folder'.Invoke (state, result.Current) + // + // state + + module Array = + type Enumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = + inherit Base.Enumerator<'U>(result) + + let mutable idx = 0 + + let rec moveNext () = + if (not result.Halted) && idx < array.Length then + idx <- idx+1 + if t2u.ProcessNext array.[idx-1] then + true + else + moveNext () else + result.SeqState <- SeqProcessNextStates.Finished + t2u.OnComplete () + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess moveNext () - else - result.SeqState <- SeqProcessNextStates.Finished - t2u.OnComplete () - false - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () + type Enumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) = + inherit Base.Enumerable<'U>() - type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = - inherit ComposedEnumerator<'U>(result) + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Helpers.UpcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail result), result)) - let mutable list = alist + override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory (current, next))) - let rec moveNext current = - match result.Halted, current with - | false, head::tail -> - if t2u.ProcessNext head then - list <- tail - true - else - moveNext tail - | _ -> - result.SeqState <- SeqProcessNextStates.Finished - t2u.OnComplete () - false + // interface ISeqEnumerable<'U> with + // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = + // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + // + // let mutable idx = 0 + // let result = Result<'U> () + // let components = current.Create result (Tail result) + // + // let mutable state = initialState + // while (not result.Halted) && idx < array.Length do + // if components.ProcessNext array.[idx] then + // state <- folder'.Invoke(state, result.Current) + // idx <- idx + 1 + // + // state - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext list - - [] - type ComposableEnumerable<'T> () = - abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> - - interface IEnumerable with - member this.GetEnumerator () : IEnumerator = - let genericEnumerable = Helpers.UpcastEnumerable this - let genericEnumerator = genericEnumerable.GetEnumerator () - Helpers.UpcastEnumeratorNonGeneric genericEnumerator - - interface IEnumerable<'T> with - member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" - - type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = - inherit ComposableEnumerable<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) - - override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, ComposedFactory (current, next))) - -// interface ISeqEnumerable<'U> with -// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = -// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder -// -// let enumerator = enumerable.GetEnumerator () -// let result = Result<'U> () -// -// let components = current.Create result (Tail result) -// -// let mutable state = initialState -// while (not result.Halted) && enumerator.MoveNext () do -// if components.ProcessNext (enumerator.Current) then -// state <- folder'.Invoke (state, result.Current) -// -// state - - type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) = - inherit ComposableEnumerable<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result)) - - override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, ComposedFactory (current, next))) - -// interface ISeqEnumerable<'U> with -// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = -// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder -// -// let mutable idx = 0 -// let result = Result<'U> () -// let components = current.Create result (Tail result) -// -// let mutable state = initialState -// while (not result.Halted) && idx < array.Length do -// if components.ProcessNext array.[idx] then -// state <- folder'.Invoke(state, result.Current) -// idx <- idx + 1 -// -// state - - type SeqListEnumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) = - inherit ComposableEnumerable<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result)) - - override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next))) - - - // 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. - type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:Result<'U>) = - inherit ComposedEnumerator<'U>(signal) - - // 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 - let terminatingIdx = - if count.HasValue then - count.Value - 1 - else - System.Int32.MaxValue + module List = + type Enumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = + inherit Base.Enumerator<'U>(result) - let mutable maybeSkipping = true - let mutable idx = -1 + let mutable list = alist - let rec moveNext () = - if (not signal.Halted) && idx < terminatingIdx then - idx <- idx + 1 + let rec moveNext current = + match result.Halted, current with + | false, head::tail -> + if t2u.ProcessNext head then + list <- tail + true + else + moveNext tail + | _ -> + result.SeqState <- SeqProcessNextStates.Finished + t2u.OnComplete () + false - if maybeSkipping then - // Skip can only is only checked at the start of the sequence, so once - // triggered, we stay triggered. - maybeSkipping <- t2u.Skipping () - - if maybeSkipping then - moveNext () - elif t2u.ProcessNext (f idx) then - true + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext list + + type Enumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) = + inherit Base.Enumerable<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Helpers.UpcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail result), result)) + + override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory (current, next))) + + 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. + type Enumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:Result<'U>) = + inherit Base.Enumerator<'U>(signal) + + // 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 + let terminatingIdx = + if count.HasValue then + count.Value - 1 else - moveNext () - elif (not signal.Halted) && idx = System.Int32.MaxValue then - raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) - else - signal.SeqState <- SeqProcessNextStates.Finished - t2u.OnComplete () - false + System.Int32.MaxValue - interface IEnumerator with - member __.MoveNext () = - signal.SeqState <- SeqProcessNextStates.InProcess - moveNext () + let mutable maybeSkipping = true + let mutable idx = -1 + + let rec moveNext () = + if (not signal.Halted) && idx < terminatingIdx then + idx <- idx + 1 - type InitComposingEnumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) = - inherit ComposableEnumerable<'U>() + if maybeSkipping then + // Skip can only is only checked at the start of the sequence, so once + // triggered, we stay triggered. + maybeSkipping <- t2u.Skipping () + + if maybeSkipping then + moveNext () + elif t2u.ProcessNext (f idx) then + true + else + moveNext () + elif (not signal.Halted) && idx = System.Int32.MaxValue then + raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + else + signal.SeqState <- SeqProcessNextStates.Finished + t2u.OnComplete () + false + + interface IEnumerator with + member __.MoveNext () = + signal.SeqState <- SeqProcessNextStates.InProcess + moveNext () - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, current.Create result (Tail result), result)) + type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) = + inherit Base.Enumerable<'U>() - override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new InitComposingEnumerable<'T,'V>(count, f, ComposedFactory (current, next))) + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Helpers.UpcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail result), result)) + override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next))) - type InitEnumerable<'T>(count:Nullable, f:int->'T) = - inherit ComposableEnumerable<'T>() + type EnumerableDecider<'T>(count:Nullable, f:int->'T) = + inherit Base.Enumerable<'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 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 - override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = - Helpers.UpcastEnumerable (InitComposingEnumerable<'T,'V>(count, f, next)) + override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = + Helpers.UpcastEnumerable (Enumerable<'T,'V>(count, f, next)) #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions @@ -1304,13 +1309,13 @@ namespace Microsoft.FSharp.Collections [] let initInfinite<'T> (f:int->'T) : IEnumerable<'T> = - SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable (), f)) + SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable (), f)) [] let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> = if count < 0 then invalidArgInputMustBeNonNegative "count" count elif count = 0 then empty else - SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable count, f)) + SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable count, f)) [] let iter f (source : seq<'T>) = @@ -1406,10 +1411,10 @@ namespace Microsoft.FSharp.Collections let private seqFactory createSeqComponent (source:seq<'T>) = checkNonNull "source" source match source with - | :? SeqComposer.ComposableEnumerable<'T> as s -> s.Compose createSeqComponent - | :? array<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent)) - | :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent)) - | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent)) + | :? SeqComposer.Base.Enumerable<'T> as s -> s.Compose createSeqComponent + | :? array<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Array.Enumerable<_,_>(a, createSeqComponent)) + | :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.List.Enumerable<_,_>(a, createSeqComponent)) + | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Enumerable.Enumerable<_,_>(source, createSeqComponent)) [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = From b88dd4e5a4d3d56a5c7b8b247092d0393d06e989 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 19:09:42 +1100 Subject: [PATCH 026/286] map2 --- src/fsharp/FSharp.Core/seq.fs | 65 ++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 39c3a0fdbb5..3fb1ed974af 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -108,25 +108,6 @@ namespace Microsoft.FSharp.Collections interface System.IDisposable with member this.Dispose() = this.Dispose() - let map2 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) : IEnumerator<_>= - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - upcast - { new MapEnumerator<_>() with - member this.DoMoveNext curr = - let n1 = e1.MoveNext() - let n2 = e2.MoveNext() - if n1 && n2 then - curr <- f.Invoke(e1.Current, e2.Current) - true - else - false - member this.Dispose() = - try - e1.Dispose() - finally - e2.Dispose() - } - let mapi2 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) : IEnumerator<_> = let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) let i = ref (-1) @@ -851,6 +832,14 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map + and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = + inherit SeqComponentFactory<'First,'U> () + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map2First (map, input2, result, next) + + and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = + inherit SeqComponentFactory<'Second,'U> () + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'Second,'V> = upcast Map2Second (map, input1, result, next) + and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next) @@ -929,6 +918,38 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'First,'V>() + + let input2 = enumerable2.GetEnumerator () + let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map + + override __.ProcessNext (input:'First) : bool = + if input2.MoveNext () then + Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) + else + result.StopFurtherProcessing () + false + + override __.OnComplete () = + input2.Dispose () + + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'Second,'V>() + + let input1 = enumerable1.GetEnumerator () + let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map + + override __.ProcessNext (input:'Second) : bool = + if input1.MoveNext () then + Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) + else + result.StopFurtherProcessing () + false + + override __.OnComplete () = + input1.Dispose () + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) = inherit SeqComponent<'T,'V>() @@ -1438,10 +1459,12 @@ namespace Microsoft.FSharp.Collections revamp2 (IEnumerator.mapi2 f) source1 source2 [] - let map2 f source1 source2 = + let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = checkNonNull "source1" source1 checkNonNull "source2" source2 - revamp2 (IEnumerator.map2 f) source1 source2 + match source1 with + | :? SeqComposer.Base.Enumerable<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2)) + | _ -> source2 |> seqFactory (SeqComposer.Map2SecondFactory (f, source1)) [] let map3 f source1 source2 source3 = From 2f91fb3997577628328221dc577fec52c9b90e84 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 19:29:55 +1100 Subject: [PATCH 027/286] Fix OnComplete/OnDispose Hmmm... not 100% happy with this because it requires all links in the chain to ensure that that follow the protocol, but it isn't too bad I guess... --- src/fsharp/FSharp.Core/seq.fs | 125 ++++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 52 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 3fb1ed974af..ce9cdd1dc04 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -785,6 +785,10 @@ namespace Microsoft.FSharp.Collections module SeqComposer = open IEnumerator + type ISeqComponent = + abstract OnComplete : unit -> unit + abstract OnDispose : unit -> unit + module Helpers = // used for performance reasons; these are not recursive calls, so should be safe let inline avoidTailCall x = @@ -797,6 +801,7 @@ namespace Microsoft.FSharp.Collections let inline UpcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) + let inline UpcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) type SeqProcessNextStates = | NotStarted = 1 @@ -813,6 +818,11 @@ namespace Microsoft.FSharp.Collections member val Current = Unchecked.defaultof<'T> with get, set + let seqComponentTail = + { new ISeqComponent with + member __.OnComplete() = () + member __.OnDispose() = () } + type [] SeqComponentFactory<'T,'U> () = abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V> @@ -864,9 +874,8 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'T> () override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next) - and [] SeqComponent<'T,'U> () = + and [] SeqComponent<'T,'U> (next:ISeqComponent) = abstract ProcessNext : input:'T -> bool - abstract OnComplete : unit -> unit // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip // and it can only do it at the start of a sequence @@ -875,7 +884,9 @@ namespace Microsoft.FSharp.Collections abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> - default __.OnComplete () = () + interface ISeqComponent with + member __.OnComplete () = next.OnComplete () + member __.OnDispose () = next.OnDispose () default __.Skipping () = false @@ -883,7 +894,7 @@ namespace Microsoft.FSharp.Collections default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqComponent<'U,'V>) = - inherit SeqComponent<'T,'V>() + inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = match choose input with @@ -891,7 +902,7 @@ namespace Microsoft.FSharp.Collections | None -> false and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) = - inherit SeqComponent<'T,'V>() + inherit SeqComponent<'T,'V>(next) override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) @@ -902,7 +913,7 @@ namespace Microsoft.FSharp.Collections false and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqComponent<'U,'V>) = - inherit SeqComponent<'T,'V>() + inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = if filter input then @@ -911,7 +922,7 @@ namespace Microsoft.FSharp.Collections false and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) = - inherit SeqComponent<'T,'V>() + inherit SeqComponent<'T,'V>(next) override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) @@ -919,7 +930,7 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext (map input)) and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = - inherit SeqComponent<'First,'V>() + inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -931,11 +942,13 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing () false - override __.OnComplete () = - input2.Dispose () + interface ISeqComponent with + override __.OnDispose () = + input2.Dispose () + (Helpers.UpcastISeqComponent next).OnDispose () and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) = - inherit SeqComponent<'Second,'V>() + inherit SeqComponent<'Second,'V>(next) let input1 = enumerable1.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -947,11 +960,13 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing () false - override __.OnComplete () = - input1.Dispose () + interface ISeqComponent with + override __.OnDispose () = + input1.Dispose () + (Helpers.UpcastISeqComponent next).OnDispose () and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) = - inherit SeqComponent<'T,'V>() + inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = let u = map input @@ -961,7 +976,7 @@ namespace Microsoft.FSharp.Collections false and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqComponent<'U,'V>) = - inherit SeqComponent<'T,'V>() + inherit SeqComponent<'T,'V>(next) let mutable idx = 0 let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi @@ -971,7 +986,7 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) = - inherit SeqComponent<'T,'V>() + inherit SeqComponent<'T,'V>(next) let mutable isFirst = true let mutable lastValue = Unchecked.defaultof<'T> @@ -987,7 +1002,7 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext currentPair) and Skip<'T,'V> (skipCount:int, next:SeqComponent<'T,'V>) = - inherit SeqComponent<'T,'V>() + inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -1005,14 +1020,16 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - override __.OnComplete () = - if count < skipCount then - let x = skipCount - count - invalidOpFmt "tried to skip {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + interface ISeqComponent with + override __.OnComplete () = + if count < skipCount then + let x = skipCount - count + invalidOpFmt "tried to skip {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + (Helpers.UpcastISeqComponent next).OnComplete () and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) = - inherit SeqComponent<'T,'V>() + inherit SeqComponent<'T,'V>(next) let mutable skip = true @@ -1027,7 +1044,7 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext input) and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = - inherit SeqComponent<'T,'V>() + inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -1041,14 +1058,16 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing () false - override __.OnComplete () = - if count < takeCount then - let x = takeCount - count - invalidOpFmt "tried to take {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + interface ISeqComponent with + override __.OnComplete () = + if count < takeCount then + let x = takeCount - count + invalidOpFmt "tried to take {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + (Helpers.UpcastISeqComponent next).OnComplete () and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) = - inherit SeqComponent<'T,'V>() + inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = if predicate input then @@ -1058,7 +1077,7 @@ namespace Microsoft.FSharp.Collections false and Tail<'T> (result:Result<'T>) = - inherit SeqComponent<'T,'T>() + inherit SeqComponent<'T,'T>(seqComponentTail) override __.ProcessNext (input:'T) : bool = result.Current <- input @@ -1066,9 +1085,10 @@ namespace Microsoft.FSharp.Collections module Base = [] - type Enumerator<'T>(result:Result<'T>) = + type Enumerator<'T>(result:Result<'T>, seqComponent:ISeqComponent) = interface IDisposable with - member __.Dispose() : unit = () + member __.Dispose() : unit = + seqComponent.OnDispose () interface IEnumerator with member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current @@ -1097,18 +1117,18 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" module Enumerable = - type Enumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = - inherit Base.Enumerator<'U>(result) + type Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + inherit Base.Enumerator<'U>(result, seqComponent) let rec moveNext () = if (not result.Halted) && source.MoveNext () then - if t2u.ProcessNext source.Current then + if seqComponent.ProcessNext source.Current then true else moveNext () else result.SeqState <- SeqProcessNextStates.Finished - t2u.OnComplete () + (Helpers.UpcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -1117,8 +1137,9 @@ namespace Microsoft.FSharp.Collections moveNext () interface IDisposable with - member __.Dispose() = source.Dispose () - + member __.Dispose() = + source.Dispose () + (Helpers.UpcastISeqComponent seqComponent).OnDispose () type Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = inherit Base.Enumerable<'U>() @@ -1148,21 +1169,21 @@ namespace Microsoft.FSharp.Collections // state module Array = - type Enumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = - inherit Base.Enumerator<'U>(result) + type Enumerator<'T,'U>(array:array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + inherit Base.Enumerator<'U>(result, seqComponent) let mutable idx = 0 let rec moveNext () = if (not result.Halted) && idx < array.Length then idx <- idx+1 - if t2u.ProcessNext array.[idx-1] then + if seqComponent.ProcessNext array.[idx-1] then true else moveNext () else result.SeqState <- SeqProcessNextStates.Finished - t2u.OnComplete () + (Helpers.UpcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -1198,22 +1219,22 @@ namespace Microsoft.FSharp.Collections // state module List = - type Enumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) = - inherit Base.Enumerator<'U>(result) + type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + inherit Base.Enumerator<'U>(result, seqComponent) let mutable list = alist let rec moveNext current = match result.Halted, current with | false, head::tail -> - if t2u.ProcessNext head then + if seqComponent.ProcessNext head then list <- tail true else moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - t2u.OnComplete () + (Helpers.UpcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -1243,8 +1264,8 @@ namespace Microsoft.FSharp.Collections // 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. - type Enumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:Result<'U>) = - inherit Base.Enumerator<'U>(signal) + type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) = + inherit Base.Enumerator<'U>(signal, seqComponent) // 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 @@ -1264,11 +1285,11 @@ namespace Microsoft.FSharp.Collections if maybeSkipping then // Skip can only is only checked at the start of the sequence, so once // triggered, we stay triggered. - maybeSkipping <- t2u.Skipping () + maybeSkipping <- seqComponent.Skipping () if maybeSkipping then moveNext () - elif t2u.ProcessNext (f idx) then + elif seqComponent.ProcessNext (f idx) then true else moveNext () @@ -1276,7 +1297,7 @@ namespace Microsoft.FSharp.Collections raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else signal.SeqState <- SeqProcessNextStates.Finished - t2u.OnComplete () + (Helpers.UpcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with From 3069b61dc2838a6ed163877cb766adb51e63986b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 10 Oct 2016 19:35:48 +1100 Subject: [PATCH 028/286] Seq.append This implemention performs vastly better than the previous implementation, which appeared to be more interested in being theoretically important than actually being a reasonable implementation. Anyway, the previous version blew up with stack overflow if you appended too many things, which the new version doesn't. --- src/fsharp/FSharp.Core/seq.fs | 238 ++++++++++------------------------ 1 file changed, 72 insertions(+), 166 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ce9cdd1dc04..bb248dd1469 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -318,149 +318,6 @@ namespace Microsoft.FSharp.Collections f() } - // Use generators for some implementations of IEnumerables. - // - module Generator = - - open System.Collections - open System.Collections.Generic - - [] - type Step<'T> = - | Stop - | Yield of 'T - | Goto of Generator<'T> - - and Generator<'T> = - abstract Apply: (unit -> Step<'T>) - abstract Disposer: (unit -> unit) option - - let disposeG (g:Generator<'T>) = - match g.Disposer with - | None -> () - | Some f -> f() - - let appG (g:Generator<_>) = - //System.Console.WriteLine("{0}.appG", box g) - let res = g.Apply() - match res with - | Goto(next) -> - Goto(next) - | Yield _ -> - res - | Stop -> - //System.Console.WriteLine("appG: Stop") - disposeG g - res - - // Binding. - // - // We use a type definition to apply a local dynamic optimization. - // We automatically right-associate binding, i.e. push the continuations to the right. - // That is, bindG (bindG G1 cont1) cont2 --> bindG G1 (cont1 o cont2) - // This makes constructs such as the following linear rather than quadratic: - // - // let rec rwalk n = { if n > 0 then - // yield! rwalk (n-1) - // yield n } - - type GenerateThen<'T>(g:Generator<'T>, cont : unit -> Generator<'T>) = - member self.Generator = g - member self.Cont = cont - interface Generator<'T> with - member x.Apply = (fun () -> - match appG g with - | Stop -> - // OK, move onto the generator given by the continuation - Goto(cont()) - - | Yield _ as res -> - res - - | Goto next -> - Goto(GenerateThen<_>.Bind(next,cont))) - member x.Disposer = - g.Disposer - - - static member Bind (g:Generator<'T>, cont) = - match g with - | :? GenerateThen<'T> as g -> GenerateThen<_>.Bind(g.Generator,(fun () -> GenerateThen<_>.Bind (g.Cont(), cont))) - | g -> (new GenerateThen<'T>(g, cont) :> Generator<'T>) - - - let bindG g cont = GenerateThen<_>.Bind(g,cont) - - - // Internal type. Drive an underlying generator. Crucially when the generator returns - // a new generator we simply update our current generator and continue. Thus the enumerator - // effectively acts as a reference cell holding the current generator. This means that - // infinite or large generation chains (e.g. caused by long sequences of append's, including - // possible delay loops) can be referenced via a single enumerator. - // - // A classic case where this arises in this sort of sequence expression: - // let rec data s = { yield s; - // yield! data (s + random()) } - // - // This translates to - // let rec data s = Seq.delay (fun () -> Seq.append (Seq.singleton s) (Seq.delay (fun () -> data (s+random())))) - // - // When you unwind through all the Seq, IEnumerator and Generator objects created, - // you get (data s).GetEnumerator being an "GenerateFromEnumerator(EnumeratorWrappingLazyGenerator(...))" for the append. - // After one element is yielded, we move on to the generator for the inner delay, which in turn - // comes back to be a "GenerateFromEnumerator(EnumeratorWrappingLazyGenerator(...))". - // - // Defined as a type so we can optimize Enumerator/Generator chains in enumerateFromLazyGenerator - // and GenerateFromEnumerator. - - [] - type EnumeratorWrappingLazyGenerator<'T>(g:Generator<'T>) = - let mutable g = g - let mutable curr = None - let mutable finished = false - member e.Generator = g - interface IEnumerator<'T> with - member x.Current= match curr with Some(v) -> v | None -> raise <| System.InvalidOperationException (SR.GetString(SR.moveNextNotCalledOrFinished)) - interface System.Collections.IEnumerator with - member x.Current = box (x :> IEnumerator<_>).Current - member x.MoveNext() = - not finished && - (match appG g with - | Stop -> - curr <- None - finished <- true - false - | Yield(v) -> - curr <- Some(v) - true - | Goto(next) -> - (g <- next) - (x :> IEnumerator).MoveNext()) - member x.Reset() = IEnumerator.noReset() - interface System.IDisposable with - member x.Dispose() = - if not finished then disposeG g - - // Internal type, used to optimize Enumerator/Generator chains - type LazyGeneratorWrappingEnumerator<'T>(e:System.Collections.Generic.IEnumerator<'T>) = - member g.Enumerator = e - interface Generator<'T> with - member g.Apply = (fun () -> - if e.MoveNext() then - Yield(e.Current) - else - Stop) - member g.Disposer= Some(e.Dispose) - - let EnumerateFromGenerator(g:Generator<'T>) = - match g with - | :? LazyGeneratorWrappingEnumerator<'T> as g -> g.Enumerator - | _ -> (new EnumeratorWrappingLazyGenerator<_>(g) :> System.Collections.Generic.IEnumerator<_>) - - let GenerateFromEnumerator (e:System.Collections.Generic.IEnumerator<'T>) = - match e with - | :? EnumeratorWrappingLazyGenerator<'T> as e -> e.Generator - | _ -> (new LazyGeneratorWrappingEnumerator<'T>(e) :> Generator<'T>) namespace Microsoft.FSharp.Core.CompilerServices @@ -1083,9 +940,9 @@ namespace Microsoft.FSharp.Collections result.Current <- input true - module Base = + module Enumerable = [] - type Enumerator<'T>(result:Result<'T>, seqComponent:ISeqComponent) = + type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) = interface IDisposable with member __.Dispose() : unit = seqComponent.OnDispose () @@ -1102,10 +959,11 @@ namespace Microsoft.FSharp.Collections | SeqProcessNextStates.Finished -> alreadyFinished() | _ -> result.Current - - [] - type Enumerable<'T> () = + and [] EnumerableBase<'T> () = abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> + abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> + + default this.Append source = Helpers.UpcastEnumerable (AppendEnumerable [this; source]) interface IEnumerable with member this.GetEnumerator () : IEnumerator = @@ -1116,9 +974,8 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" - module Enumerable = - type Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = - inherit Base.Enumerator<'U>(result, seqComponent) + and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, seqComponent) let rec moveNext () = if (not result.Halted) && source.MoveNext () then @@ -1141,8 +998,8 @@ namespace Microsoft.FSharp.Collections source.Dispose () (Helpers.UpcastISeqComponent seqComponent).OnDispose () - type Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = - inherit Base.Enumerable<'U>() + and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = + inherit EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = @@ -1168,9 +1025,59 @@ namespace Microsoft.FSharp.Collections // // state + and AppendEnumerator<'T> (sources:list>) = + let sources = sources |> List.rev + + let mutable state = SeqProcessNextStates.NotStarted + let mutable remaining = sources.Tail + let mutable active = sources.Head.GetEnumerator () + + let rec moveNext () = + if active.MoveNext () then true + else + match remaining with + | [] -> false + | hd :: tl -> + active.Dispose () + active <- hd.GetEnumerator () + remaining <- tl + + moveNext () + + interface IEnumerator<'T> with + member __.Current = + match state with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> active.Current + + interface IEnumerator with + member __.Current = (Helpers.UpcastEnumeratorNonGeneric active).Current + member __.MoveNext () = + state <- SeqProcessNextStates.InProcess + moveNext () + member __.Reset () = noReset () + + interface IDisposable with + member __.Dispose() = + active.Dispose () + + and AppendEnumerable<'T> (sources:list>) = + inherit EnumerableBase<'T>() + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = + Helpers.UpcastEnumerator (new AppendEnumerator<_> (sources)) + + override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = + Helpers.UpcastEnumerable (Enumerable<'T,'V>(this, next)) + + override this.Append source = + Helpers.UpcastEnumerable (AppendEnumerable (source :: sources)) + module Array = type Enumerator<'T,'U>(array:array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = - inherit Base.Enumerator<'U>(result, seqComponent) + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable idx = 0 @@ -1192,7 +1099,7 @@ namespace Microsoft.FSharp.Collections moveNext () type Enumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) = - inherit Base.Enumerable<'U>() + inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = @@ -1220,7 +1127,7 @@ namespace Microsoft.FSharp.Collections module List = type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = - inherit Base.Enumerator<'U>(result, seqComponent) + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable list = alist @@ -1243,7 +1150,7 @@ namespace Microsoft.FSharp.Collections moveNext list type Enumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) = - inherit Base.Enumerable<'U>() + inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = @@ -1265,7 +1172,7 @@ namespace Microsoft.FSharp.Collections // I have had to add an extra function that is used in Skip to determine if we are touching // Current or not. type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) = - inherit Base.Enumerator<'U>(signal, seqComponent) + inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) // 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 @@ -1306,7 +1213,7 @@ namespace Microsoft.FSharp.Collections moveNext () type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) = - inherit Base.Enumerable<'U>() + inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = @@ -1317,7 +1224,7 @@ namespace Microsoft.FSharp.Collections Helpers.UpcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next))) type EnumerableDecider<'T>(count:Nullable, f:int->'T) = - inherit Base.Enumerable<'T>() + inherit Enumerable.EnumerableBase<'T>() interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = @@ -1453,7 +1360,7 @@ namespace Microsoft.FSharp.Collections let private seqFactory createSeqComponent (source:seq<'T>) = checkNonNull "source" source match source with - | :? SeqComposer.Base.Enumerable<'T> as s -> s.Compose createSeqComponent + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose createSeqComponent | :? array<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Array.Enumerable<_,_>(a, createSeqComponent)) | :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.List.Enumerable<_,_>(a, createSeqComponent)) | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Enumerable.Enumerable<_,_>(source, createSeqComponent)) @@ -1484,7 +1391,7 @@ namespace Microsoft.FSharp.Collections checkNonNull "source1" source1 checkNonNull "source2" source2 match source1 with - | :? SeqComposer.Base.Enumerable<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2)) + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2)) | _ -> source2 |> seqFactory (SeqComposer.Map2SecondFactory (f, source1)) [] @@ -1629,9 +1536,6 @@ namespace Microsoft.FSharp.Collections state <- f.Invoke(state, e.Current) state - let fromGenerator f = mkSeq(fun () -> Generator.EnumerateFromGenerator (f())) - let toGenerator (ie : seq<_>) = Generator.GenerateFromEnumerator (ie.GetEnumerator()) - [] let replicate count x = System.Linq.Enumerable.Repeat(x,count) @@ -1640,7 +1544,9 @@ namespace Microsoft.FSharp.Collections let append (source1: seq<'T>) (source2: seq<'T>) = checkNonNull "source1" source1 checkNonNull "source2" source2 - fromGenerator(fun () -> Generator.bindG (toGenerator source1) (fun () -> toGenerator source2)) + match source1 with + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Append source2 + | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Enumerable.AppendEnumerable<_>([source2; source1])) [] From e7a4efdcdf69297b244802e5d70dfea0cd6e170e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 10 Oct 2016 19:42:40 +1100 Subject: [PATCH 029/286] minor perf; assume "InProcess" --- src/fsharp/FSharp.Core/seq.fs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index bb248dd1469..02aa5abdc0d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -661,9 +661,9 @@ namespace Microsoft.FSharp.Collections let inline UpcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) type SeqProcessNextStates = + | InProcess = 0 | NotStarted = 1 | Finished = 2 - | InProcess = 3 type Result<'T>() = let mutable halted = false @@ -954,10 +954,12 @@ namespace Microsoft.FSharp.Collections interface IEnumerator<'T> with member __.Current = - match result.SeqState with - | SeqProcessNextStates.NotStarted -> notStarted() - | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> result.Current + if result.SeqState = SeqProcessNextStates.InProcess then result.Current + else + match result.SeqState with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> failwith "library implementation error: all states should have been handled" and [] EnumerableBase<'T> () = abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> @@ -1046,10 +1048,12 @@ namespace Microsoft.FSharp.Collections interface IEnumerator<'T> with member __.Current = - match state with - | SeqProcessNextStates.NotStarted -> notStarted() - | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> active.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 __.Current = (Helpers.UpcastEnumeratorNonGeneric active).Current From bede7fde90d38e3b1e4c4851e8170fadc891aaa3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 10 Oct 2016 19:46:35 +1100 Subject: [PATCH 030/286] Bug fix; ensure exception protocol is followed --- src/fsharp/FSharp.Core/seq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 02aa5abdc0d..37d3ba5f8bd 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1056,7 +1056,7 @@ namespace Microsoft.FSharp.Collections | _ -> failwith "library implementation error: all states should have been handled" interface IEnumerator with - member __.Current = (Helpers.UpcastEnumeratorNonGeneric active).Current + member this.Current = box ((Helpers.UpcastEnumerator this)).Current member __.MoveNext () = state <- SeqProcessNextStates.InProcess moveNext () From 052119d18d867faeb398d06d906cfa2255ffd22f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 11 Oct 2016 19:32:19 +1100 Subject: [PATCH 031/286] Seq.fold --- src/fsharp/FSharp.Core/seq.fs | 156 ++++++++++++++++++++++++---------- 1 file changed, 113 insertions(+), 43 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 37d3ba5f8bd..72d0a46061a 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -964,6 +964,7 @@ namespace Microsoft.FSharp.Collections and [] EnumerableBase<'T> () = abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> + abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State default this.Append source = Helpers.UpcastEnumerable (AppendEnumerable [this; source]) @@ -1011,21 +1012,20 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.UpcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory (current, next))) - // interface ISeqEnumerable<'U> with - // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = - // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - // - // let enumerator = enumerable.GetEnumerator () - // let result = Result<'U> () - // - // let components = current.Create result (Tail result) - // - // let mutable state = initialState - // while (not result.Halted) && enumerator.MoveNext () do - // if components.ProcessNext (enumerator.Current) then - // state <- folder'.Invoke (state, result.Current) - // - // state + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let enumerator = enumerable.GetEnumerator () + let result = Result<'U> () + + let components = current.Create result (Tail result) + + let mutable state = initialState + while (not result.Halted) && (enumerator.MoveNext ()) do + if components.ProcessNext (enumerator.Current) then + state <- folder'.Invoke (state, result.Current) + + state and AppendEnumerator<'T> (sources:list>) = let sources = sources |> List.rev @@ -1079,6 +1079,18 @@ namespace Microsoft.FSharp.Collections override this.Append source = Helpers.UpcastEnumerable (AppendEnumerable (source :: sources)) + override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let enumerable = Helpers.UpcastEnumerable (AppendEnumerable sources) + let enumerator = enumerable.GetEnumerator () + + let mutable state = initialState + while enumerator.MoveNext () do + state <- folder'.Invoke (state, enumerator.Current) + + state + module Array = type Enumerator<'T,'U>(array:array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) @@ -1113,21 +1125,20 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.UpcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory (current, next))) - // interface ISeqEnumerable<'U> with - // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = - // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - // - // let mutable idx = 0 - // let result = Result<'U> () - // let components = current.Create result (Tail result) - // - // let mutable state = initialState - // while (not result.Halted) && idx < array.Length do - // if components.ProcessNext array.[idx] then - // state <- folder'.Invoke(state, result.Current) - // idx <- idx + 1 - // - // state + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let mutable idx = 0 + let result = Result<'U> () + let components = current.Create result (Tail result) + + let mutable state = initialState + while (not result.Halted) && (idx < array.Length) do + if components.ProcessNext array.[idx] then + state <- folder'.Invoke (state, result.Current) + idx <- idx + 1 + + state module List = type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = @@ -1164,6 +1175,24 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.UpcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory (current, next))) + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let result = Result<'U> () + let components = current.Create result (Tail result) + + let rec fold state lst = + match result.Halted, lst with + | true, _ + | false, [] -> state + | false, hd :: tl -> + if components.ProcessNext hd then + fold (folder'.Invoke (state, result.Current)) tl + else + fold state tl + + fold initialState alist + 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. @@ -1175,16 +1204,20 @@ namespace Microsoft.FSharp.Collections // 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. - type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) + 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, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) + let terminatingIdx = - if count.HasValue then - count.Value - 1 - else - System.Int32.MaxValue + getTerminatingIdx count let mutable maybeSkipping = true let mutable idx = -1 @@ -1227,6 +1260,29 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.UpcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next))) + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let result = Result<'U> () + let components = current.Create result (Tail result) + + let mutable idx = -1 + let terminatingIdx = getTerminatingIdx count + + let mutable maybeSkipping = true + + let mutable state = initialState + while (not result.Halted) && (idx < terminatingIdx) do + if maybeSkipping then + maybeSkipping <- components.Skipping () + + if (not maybeSkipping) && (components.ProcessNext (f (idx+1))) then + state <- folder'.Invoke (state, result.Current) + + idx <- idx + 1 + + state + type EnumerableDecider<'T>(count:Nullable, f:int->'T) = inherit Enumerable.EnumerableBase<'T>() @@ -1240,6 +1296,17 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.UpcastEnumerable (Enumerable<'T,'V>(count, f, next)) + override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let enumerator = (Helpers.UpcastEnumerable this).GetEnumerator () + + let mutable state = initialState + while enumerator.MoveNext () do + state <- folder'.Invoke (state, enumerator.Current) + + state + #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions #else @@ -1504,14 +1571,17 @@ namespace Microsoft.FSharp.Collections state [] - let fold<'T,'State> f (x:'State) (source : seq<'T>) = + let fold<'T,'State> f (x:'State) (source:seq<'T>) = checkNonNull "source" source - use e = source.GetEnumerator() - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let mutable state = x - while e.MoveNext() do - state <- f.Invoke(state, e.Current) - state + match source with + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Fold f x + | _ -> + use e = source.GetEnumerator() + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) + let mutable state = x + while e.MoveNext() do + state <- f.Invoke(state, e.Current) + state [] let fold2<'T1,'T2,'State> f (state:'State) (source1: seq<'T1>) (source2: seq<'T2>) = From cea835c65ec92f1b41cb665504d5aed5db52cd2b Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 11 Oct 2016 16:28:24 -0400 Subject: [PATCH 032/286] fix typo --- src/fsharp/FSharp.Core/seq.fs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 72d0a46061a..75ad5f301e6 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -719,13 +719,13 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'T> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next) - and SkipWhileFactory<'T> (perdicate:'T->bool) = + and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next) + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (predicate, next) - and TakeWhileFactory<'T> (perdicate:'T->bool) = + and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, result, next) + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (predicate, result, next) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () From dfef8a621192cd7cc818a365a388b11125bc403a Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 11 Oct 2016 21:16:38 -0400 Subject: [PATCH 033/286] truncate --- src/fsharp/FSharp.Core/seq.fs | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 75ad5f301e6..9b8d0e933ad 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -730,6 +730,10 @@ namespace Microsoft.FSharp.Collections and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next) + + and TruncateFactory<'T> (count:int) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Truncate (count, result, next) and [] SeqComponent<'T,'U> (next:ISeqComponent) = abstract ProcessNext : input:'T -> bool @@ -940,6 +944,21 @@ namespace Microsoft.FSharp.Collections result.Current <- input true + and Truncate<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let mutable count = 0 + + override __.ProcessNext (input:'T) : bool = + if count < takeCount then + count <- count + 1 + if count = takeCount then + result.StopFurtherProcessing () + next.ProcessNext input + else + result.StopFurtherProcessing () + false + module Enumerable = [] type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) = @@ -1711,12 +1730,7 @@ namespace Microsoft.FSharp.Collections [] let truncate n (source: seq<'T>) = - checkNonNull "source" source - seq { let i = ref 0 - use ie = source.GetEnumerator() - while !i < n && ie.MoveNext() do - i := !i + 1 - yield ie.Current } + source |> seqFactory (SeqComposer.TruncateFactory n) [] let pairwise<'T> (source:seq<'T>) : seq<'T*'T> = From 051fff5a90f2f2815ba7fb8bdb1e8889d923ee5c Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 11 Oct 2016 22:36:09 -0400 Subject: [PATCH 034/286] using inheritance for take --- src/fsharp/FSharp.Core/seq.fs | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 9b8d0e933ad..9336b1bfd7f 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -905,24 +905,12 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext input) and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let mutable count = 0 - - override __.ProcessNext (input:'T) : bool = - if count < takeCount then - count <- count + 1 - if count = takeCount then - result.StopFurtherProcessing () - next.ProcessNext input - else - result.StopFurtherProcessing () - false + inherit Truncate<'T, 'V>(takeCount, result, next) interface ISeqComponent with - override __.OnComplete () = - if count < takeCount then - let x = takeCount - count + override this.OnComplete () = + if this.Count < takeCount then + let x = takeCount - this.Count invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] (Helpers.UpcastISeqComponent next).OnComplete () @@ -944,15 +932,17 @@ namespace Microsoft.FSharp.Collections result.Current <- input true - and Truncate<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = + and Truncate<'T,'V> (truncateCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable count = 0 + member __.Count = count + override __.ProcessNext (input:'T) : bool = - if count < takeCount then + if count < truncateCount then count <- count + 1 - if count = takeCount then + if count = truncateCount then result.StopFurtherProcessing () next.ProcessNext input else From 162fd0e1968ff25899bdb9a9eec790a3164c0710 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 12 Oct 2016 19:08:05 +1100 Subject: [PATCH 035/286] Carry on disposing under exceptions --- src/fsharp/FSharp.Core/seq.fs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 9336b1bfd7f..80fdf298d39 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -805,8 +805,10 @@ namespace Microsoft.FSharp.Collections interface ISeqComponent with override __.OnDispose () = - input2.Dispose () - (Helpers.UpcastISeqComponent next).OnDispose () + try + input2.Dispose () + finally + (Helpers.UpcastISeqComponent next).OnDispose () and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) = inherit SeqComponent<'Second,'V>(next) @@ -823,8 +825,10 @@ namespace Microsoft.FSharp.Collections interface ISeqComponent with override __.OnDispose () = - input1.Dispose () - (Helpers.UpcastISeqComponent next).OnDispose () + try + input1.Dispose () + finally + (Helpers.UpcastISeqComponent next).OnDispose () and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) = inherit SeqComponent<'T,'V>(next) @@ -1007,8 +1011,10 @@ namespace Microsoft.FSharp.Collections interface IDisposable with member __.Dispose() = - source.Dispose () - (Helpers.UpcastISeqComponent seqComponent).OnDispose () + try + source.Dispose () + finally + (Helpers.UpcastISeqComponent seqComponent).OnDispose () and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = inherit EnumerableBase<'U>() From c5f850c13bd42002a50cb848b822570cb26ee944 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 12 Oct 2016 20:23:43 +1100 Subject: [PATCH 036/286] bug fix: "truncate 0" was causing MoveNext on underlying seq --- src/fsharp/FSharp.Core/seq.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 80fdf298d39..e8792358d98 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1726,6 +1726,7 @@ namespace Microsoft.FSharp.Collections [] let truncate n (source: seq<'T>) = + if n <= 0 then empty else source |> seqFactory (SeqComposer.TruncateFactory n) [] From 85dfa258b26a82ff0c3e61cdc79018b6b7310667 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 12 Oct 2016 21:46:26 -0400 Subject: [PATCH 037/286] distinct/distinctby --- src/fsharp/FSharp.Core/seq.fs | 42 ++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index e8792358d98..880d1488319 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -690,6 +690,14 @@ namespace Microsoft.FSharp.Collections and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next) + + and DistinctFactory<'T when 'T: equality> () = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Distinct (next) + + and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast DistinctBy (keyFunction, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () @@ -762,6 +770,28 @@ namespace Microsoft.FSharp.Collections | Some value -> Helpers.avoidTailCall (next.ProcessNext value) | None -> false + and Distinct<'T,'V when 'T: equality> (next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) + + override __.ProcessNext (input:'T) : bool = + if hashSet.Add input then + Helpers.avoidTailCall (next.ProcessNext input) + else + false + + and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) + + override __.ProcessNext (input:'T) : bool = + if hashSet.Add(keyFunction input) then + Helpers.avoidTailCall (next.ProcessNext input) + else + false + and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -1939,19 +1969,11 @@ namespace Microsoft.FSharp.Collections [] let distinct source = - checkNonNull "source" source - seq { let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) - for v in source do - if hashSet.Add(v) then - yield v } + source |> seqFactory (SeqComposer.DistinctFactory ()) [] let distinctBy keyf source = - checkNonNull "source" source - seq { let hashSet = HashSet<_>(HashIdentity.Structural<_>) - for v in source do - if hashSet.Add(keyf v) then - yield v } + source |> seqFactory (SeqComposer.DistinctByFactory keyf) [] let sortBy keyf source = From 2c2dc54297462c0acb9065e389104907469916db Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 13 Oct 2016 06:19:09 -0400 Subject: [PATCH 038/286] except --- src/fsharp/FSharp.Core/seq.fs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 880d1488319..126c5376e0a 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -698,6 +698,10 @@ namespace Microsoft.FSharp.Collections and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqComponentFactory<'T,'T> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast DistinctBy (keyFunction, next) + + and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Except (itemsToExclude, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () @@ -792,6 +796,17 @@ namespace Microsoft.FSharp.Collections else false + and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) + + override __.ProcessNext (input:'T) : bool = + if cached.Value.Add input then + Helpers.avoidTailCall (next.ProcessNext input) + else + false + and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -2306,17 +2321,7 @@ namespace Microsoft.FSharp.Collections [] let except (itemsToExclude: seq<'T>) (source: seq<'T>) = checkNonNull "itemsToExclude" itemsToExclude - checkNonNull "source" source - - seq { - use e = source.GetEnumerator() - if e.MoveNext() then - let cached = HashSet(itemsToExclude, HashIdentity.Structural) - let next = e.Current - if (cached.Add next) then yield next - while e.MoveNext() do - let next = e.Current - if (cached.Add next) then yield next } + source |> seqFactory (SeqComposer.ExceptFactory itemsToExclude) [] let chunkBySize chunkSize (source : seq<_>) = From 5ce582e51796cf9ae565dd9ff15986e2140bc72d Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 13 Oct 2016 21:55:52 -0400 Subject: [PATCH 039/286] indexed --- src/fsharp/FSharp.Core/seq.fs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 126c5376e0a..26ff381d641 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1538,8 +1538,7 @@ namespace Microsoft.FSharp.Collections [] let indexed source = - checkNonNull "source" source - mapi (fun i x -> i,x) source + source |> seqFactory (SeqComposer.MapiFactory (fun i x -> i,x) ) [] let zip source1 source2 = From 15fb50fcf391760c6f1a732f493ed6beb04a6f7c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 10 Oct 2016 19:35:48 +1100 Subject: [PATCH 040/286] Seq.append This implemention performs vastly better than the previous implementation, which appeared to be more interested in being theoretically important than actually being a reasonable implementation. Anyway, the previous version blew up with stack overflow if you appended too many things, which the new version doesn't. --- src/fsharp/FSharp.Core/seq.fs | 44 ++++++----------------------------- 1 file changed, 7 insertions(+), 37 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 26ff381d641..85bf3f897a1 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -981,23 +981,6 @@ namespace Microsoft.FSharp.Collections result.Current <- input true - and Truncate<'T,'V> (truncateCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let mutable count = 0 - - member __.Count = count - - override __.ProcessNext (input:'T) : bool = - if count < truncateCount then - count <- count + 1 - if count = truncateCount then - result.StopFurtherProcessing () - next.ProcessNext input - else - result.StopFurtherProcessing () - false - module Enumerable = [] type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) = @@ -1022,7 +1005,6 @@ namespace Microsoft.FSharp.Collections and [] EnumerableBase<'T> () = abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> - abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State default this.Append source = Helpers.UpcastEnumerable (AppendEnumerable [this; source]) @@ -1108,15 +1090,13 @@ namespace Microsoft.FSharp.Collections 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" + match state with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> active.Current interface IEnumerator with - member this.Current = box ((Helpers.UpcastEnumerator this)).Current + member __.Current = (Helpers.UpcastEnumeratorNonGeneric active).Current member __.MoveNext () = state <- SeqProcessNextStates.InProcess moveNext () @@ -1139,18 +1119,6 @@ namespace Microsoft.FSharp.Collections override this.Append source = Helpers.UpcastEnumerable (AppendEnumerable (source :: sources)) - override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let enumerable = Helpers.UpcastEnumerable (AppendEnumerable sources) - let enumerator = enumerable.GetEnumerator () - - let mutable state = initialState - while enumerator.MoveNext () do - state <- folder'.Invoke (state, enumerator.Current) - - state - module Array = type Enumerator<'T,'U>(array:array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) @@ -1264,6 +1232,8 @@ namespace Microsoft.FSharp.Collections // 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. + type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) let getTerminatingIdx (count:Nullable) = // we are offset by 1 to allow for values going up to System.Int32.MaxValue From f329c6ad30c386b7825f81fd63d19218b465d0ba Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 13 Oct 2016 22:53:06 -0400 Subject: [PATCH 041/286] zip/zip3 --- src/fsharp/FSharp.Core/seq.fs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 85bf3f897a1..80e26ab4715 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1512,15 +1512,10 @@ namespace Microsoft.FSharp.Collections [] let zip source1 source2 = - checkNonNull "source1" source1 - checkNonNull "source2" source2 map2 (fun x y -> x,y) source1 source2 [] 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 959fa2c27a78b7cb8d0e81bd4d6d3c2edf314670 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:31:04 +1100 Subject: [PATCH 042/286] Removed old choose function --- src/fsharp/FSharp.Core/seq.fs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 80e26ab4715..f2f94170a65 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -151,24 +151,6 @@ namespace Microsoft.FSharp.Collections e3.Dispose() } - let choose f (e : IEnumerator<'T>) = - let started = ref false - let curr = ref None - let get() = check !started; (match !curr with None -> alreadyFinished() | Some x -> x) - { new IEnumerator<'U> with - member x.Current = get() - interface IEnumerator with - member x.Current = box (get()) - member x.MoveNext() = - if not !started then started := true - curr := None - while ((!curr).IsNone && e.MoveNext()) do - curr := f e.Current - Option.isSome !curr - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = e.Dispose() } - let unfold f x : IEnumerator<_> = let state = ref x upcast From 5e4a4b48689a76f7b9af96bd3e467ab6a8218da8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:46:05 +1100 Subject: [PATCH 043/286] localizing upto This is retained for compatibility --- src/fsharp/FSharp.Core/seq.fs | 99 ++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index f2f94170a65..b10f4542798 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -165,55 +165,6 @@ namespace Microsoft.FSharp.Collections member this.Dispose() = () } - let upto lastOption f = - match lastOption with - | Some b when b<0 -> Empty() // a request for -ve length returns empty sequence - | _ -> - let unstarted = -1 // index value means unstarted (and no valid index) - let completed = -2 // index value means completed (and no valid index) - let unreachable = -3 // index is unreachable from 0,1,2,3,... - let finalIndex = match lastOption with - | Some b -> b // here b>=0, a valid end value. - | None -> unreachable // run "forever", well as far as Int32.MaxValue since indexing with a bounded type. - // The Current value for a valid index is "f i". - // Lazy<_> values are used as caches, to store either the result or an exception if thrown. - // These "Lazy<_>" caches are created only on the first call to current and forced immediately. - // The lazy creation of the cache nodes means enumerations that skip many Current values are not delayed by GC. - // For example, the full enumeration of Seq.initInfinite in the tests. - // state - let index = ref unstarted - // a Lazy node to cache the result/exception - let current = ref (Unchecked.defaultof<_>) - let setIndex i = index := i; current := (Unchecked.defaultof<_>) // cache node unprimed, initialised on demand. - let getCurrent() = - if !index = unstarted then notStarted() - if !index = completed then alreadyFinished() - match box !current with - | null -> current := Lazy<_>.Create(fun () -> f !index) - | _ -> () - // forced or re-forced immediately. - (!current).Force() - { new IEnumerator<'U> with - member x.Current = getCurrent() - interface IEnumerator with - member x.Current = box (getCurrent()) - member x.MoveNext() = - if !index = completed then - false - elif !index = unstarted then - setIndex 0 - true - else ( - if !index = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) - if !index = finalIndex then - false - else - setIndex (!index + 1) - true - ) - member self.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = () } let readAndClear r = lock r (fun () -> match !r with None -> None | Some _ as res -> r := None; res) @@ -1295,6 +1246,56 @@ namespace Microsoft.FSharp.Collections state + let upto lastOption f = + match lastOption with + | Some b when b<0 -> Empty() // a request for -ve length returns empty sequence + | _ -> + let unstarted = -1 // index value means unstarted (and no valid index) + let completed = -2 // index value means completed (and no valid index) + let unreachable = -3 // index is unreachable from 0,1,2,3,... + let finalIndex = match lastOption with + | Some b -> b // here b>=0, a valid end value. + | None -> unreachable // run "forever", well as far as Int32.MaxValue since indexing with a bounded type. + // The Current value for a valid index is "f i". + // Lazy<_> values are used as caches, to store either the result or an exception if thrown. + // These "Lazy<_>" caches are created only on the first call to current and forced immediately. + // The lazy creation of the cache nodes means enumerations that skip many Current values are not delayed by GC. + // For example, the full enumeration of Seq.initInfinite in the tests. + // state + let index = ref unstarted + // a Lazy node to cache the result/exception + let current = ref (Unchecked.defaultof<_>) + let setIndex i = index := i; current := (Unchecked.defaultof<_>) // cache node unprimed, initialised on demand. + let getCurrent() = + if !index = unstarted then notStarted() + if !index = completed then alreadyFinished() + match box !current with + | null -> current := Lazy<_>.Create(fun () -> f !index) + | _ -> () + // forced or re-forced immediately. + (!current).Force() + { new IEnumerator<'U> with + member x.Current = getCurrent() + interface IEnumerator with + member x.Current = box (getCurrent()) + member x.MoveNext() = + if !index = completed then + false + elif !index = unstarted then + setIndex 0 + true + else ( + if !index = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + if !index = finalIndex then + false + else + setIndex (!index + 1) + true + ) + member self.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = () } + type EnumerableDecider<'T>(count:Nullable, f:int->'T) = inherit Enumerable.EnumerableBase<'T>() From 410ea2796107969eb8b99b2bc5ef9a580c004fd0 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:52:39 +1100 Subject: [PATCH 044/286] cleaning up SeqComposer.Helpers - better comments - consistent casing --- src/fsharp/FSharp.Core/seq.fs | 97 +++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 43 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index b10f4542798..26ca6bca341 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -581,17 +581,16 @@ namespace Microsoft.FSharp.Collections module Helpers = // used for performance reasons; these are not recursive calls, so should be safe - let inline avoidTailCall x = - match x with - | true -> true - | false -> false + // ** it should be noted that potential changes to the f# compiler may render this function + // ineffictive ** + let inline avoidTailCall boolean = match boolean with true -> true | false -> false - let inline ComposeFilter f g x = f x && g x - - let inline UpcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) - let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) - let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline UpcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) + // 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 upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) + let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) + let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) + let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) type SeqProcessNextStates = | InProcess = 0 @@ -786,7 +785,7 @@ namespace Microsoft.FSharp.Collections try input2.Dispose () finally - (Helpers.UpcastISeqComponent next).OnDispose () + (Helpers.upcastISeqComponent next).OnDispose () and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) = inherit SeqComponent<'Second,'V>(next) @@ -806,7 +805,7 @@ namespace Microsoft.FSharp.Collections try input1.Dispose () finally - (Helpers.UpcastISeqComponent next).OnDispose () + (Helpers.upcastISeqComponent next).OnDispose () and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) = inherit SeqComponent<'T,'V>(next) @@ -869,7 +868,7 @@ namespace Microsoft.FSharp.Collections let x = skipCount - count invalidOpFmt "tried to skip {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.UpcastISeqComponent next).OnComplete () + (Helpers.upcastISeqComponent next).OnComplete () and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -895,7 +894,7 @@ namespace Microsoft.FSharp.Collections let x = takeCount - this.Count invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.UpcastISeqComponent next).OnComplete () + (Helpers.upcastISeqComponent next).OnComplete () and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -922,7 +921,7 @@ namespace Microsoft.FSharp.Collections seqComponent.OnDispose () interface IEnumerator with - member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current + member this.Current : obj = box ((Helpers.upcastEnumerator this)).Current member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)" member __.Reset () : unit = noReset () @@ -939,13 +938,13 @@ namespace Microsoft.FSharp.Collections abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> - default this.Append source = Helpers.UpcastEnumerable (AppendEnumerable [this; source]) + default this.Append source = Helpers.upcastEnumerable (AppendEnumerable [this; source]) interface IEnumerable with member this.GetEnumerator () : IEnumerator = - let genericEnumerable = Helpers.UpcastEnumerable this + let genericEnumerable = Helpers.upcastEnumerable this let genericEnumerator = genericEnumerable.GetEnumerator () - Helpers.UpcastEnumeratorNonGeneric genericEnumerator + Helpers.upcastEnumeratorNonGeneric genericEnumerator interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" @@ -961,7 +960,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.UpcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -974,7 +973,7 @@ namespace Microsoft.FSharp.Collections try source.Dispose () finally - (Helpers.UpcastISeqComponent seqComponent).OnDispose () + (Helpers.upcastISeqComponent seqComponent).OnDispose () and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = inherit EnumerableBase<'U>() @@ -982,10 +981,10 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.UpcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory (current, next))) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1029,7 +1028,7 @@ namespace Microsoft.FSharp.Collections | _ -> active.Current interface IEnumerator with - member __.Current = (Helpers.UpcastEnumeratorNonGeneric active).Current + member this.Current = box ((Helpers.upcastEnumerator this)).Current member __.MoveNext () = state <- SeqProcessNextStates.InProcess moveNext () @@ -1044,13 +1043,25 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - Helpers.UpcastEnumerator (new AppendEnumerator<_> (sources)) + Helpers.upcastEnumerator (new AppendEnumerator<_> (sources)) override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = - Helpers.UpcastEnumerable (Enumerable<'T,'V>(this, next)) + Helpers.upcastEnumerable (Enumerable<'T,'V>(this, next)) override this.Append source = - Helpers.UpcastEnumerable (AppendEnumerable (source :: sources)) + Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) + + override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) + let enumerator = enumerable.GetEnumerator () + + let mutable state = initialState + while enumerator.MoveNext () do + state <- folder'.Invoke (state, enumerator.Current) + + state module Array = type Enumerator<'T,'U>(array:array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = @@ -1067,7 +1078,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.UpcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -1081,10 +1092,10 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.UpcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory (current, next))) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1117,7 +1128,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (Helpers.UpcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -1131,10 +1142,10 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.UpcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory (current, next))) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1204,7 +1215,7 @@ namespace Microsoft.FSharp.Collections raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else signal.SeqState <- SeqProcessNextStates.Finished - (Helpers.UpcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -1218,10 +1229,10 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.UpcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next))) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1307,12 +1318,12 @@ namespace Microsoft.FSharp.Collections upto (if count.HasValue then Some (count.Value-1) else None) f override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = - Helpers.UpcastEnumerable (Enumerable<'T,'V>(count, f, next)) + Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - let enumerator = (Helpers.UpcastEnumerable this).GetEnumerator () + let enumerator = (Helpers.upcastEnumerable this).GetEnumerator () let mutable state = initialState while enumerator.MoveNext () do @@ -1342,13 +1353,13 @@ namespace Microsoft.FSharp.Collections [] let initInfinite<'T> (f:int->'T) : IEnumerable<'T> = - SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable (), f)) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable (), f)) [] let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> = if count < 0 then invalidArgInputMustBeNonNegative "count" count elif count = 0 then empty else - SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable count, f)) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable count, f)) [] let iter f (source : seq<'T>) = @@ -1445,9 +1456,9 @@ namespace Microsoft.FSharp.Collections checkNonNull "source" source match source with | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose createSeqComponent - | :? array<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Array.Enumerable<_,_>(a, createSeqComponent)) - | :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.List.Enumerable<_,_>(a, createSeqComponent)) - | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Enumerable.Enumerable<_,_>(source, createSeqComponent)) + | :? array<'T> as a -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<_,_>(a, createSeqComponent)) + | :? list<'T> as a -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.List.Enumerable<_,_>(a, createSeqComponent)) + | _ -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Enumerable.Enumerable<_,_>(source, createSeqComponent)) [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = @@ -1627,7 +1638,7 @@ namespace Microsoft.FSharp.Collections checkNonNull "source2" source2 match source1 with | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Append source2 - | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Enumerable.AppendEnumerable<_>([source2; source1])) + | _ -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Enumerable.AppendEnumerable<_>([source2; source1])) [] From 7b27bc2910aec4c97204f31847d3ae728ebe552b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:59:00 +1100 Subject: [PATCH 045/286] Seq.map3 --- src/fsharp/FSharp.Core/seq.fs | 54 +++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 26ca6bca341..44fe0e8243a 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -127,30 +127,6 @@ namespace Microsoft.FSharp.Collections e2.Dispose() } - let map3 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) (e3 : IEnumerator<_>) : IEnumerator<_> = - let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) - upcast - { new MapEnumerator<_>() with - member this.DoMoveNext curr = - let n1 = e1.MoveNext() - let n2 = e2.MoveNext() - let n3 = e3.MoveNext() - - if n1 && n2 && n3 then - curr <- f.Invoke(e1.Current, e2.Current, e3.Current) - true - else - false - member this.Dispose() = - try - e1.Dispose() - finally - try - e2.Dispose() - finally - e3.Dispose() - } - let unfold f x : IEnumerator<_> = let state = ref x upcast @@ -651,6 +627,10 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'Second,'U> () override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'Second,'V> = upcast Map2Second (map, input1, result, next) + and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = + inherit SeqComponentFactory<'First,'U> () + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map3 (map, input2, input3, result, next) + and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next) @@ -807,6 +787,30 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:Result<'V>, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'First,'V>(next) + + let input2 = enumerable2.GetEnumerator () + let input3 = enumerable3.GetEnumerator () + let map' = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt map + + override __.ProcessNext (input:'First) : bool = + if input2.MoveNext () && input3.MoveNext () then + Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) + else + result.StopFurtherProcessing () + false + + interface ISeqComponent with + override __.OnDispose () = + try + input2.Dispose () + finally + try + input3.Dispose () + finally + (Helpers.upcastISeqComponent next).OnDispose () + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) = inherit SeqComponent<'T,'V>(next) @@ -1494,7 +1498,7 @@ namespace Microsoft.FSharp.Collections checkNonNull "source1" source1 checkNonNull "source2" source2 checkNonNull "source3" source3 - revamp3 (IEnumerator.map3 f) source1 source2 source3 + source1 |> seqFactory (SeqComposer.Map3Factory (f, source2, source3)) [] let choose f source = From 078aada50c53f45fb90f422eb0df7645609618fa Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 06:06:25 +1100 Subject: [PATCH 046/286] Seq.mapi2 --- src/fsharp/FSharp.Core/seq.fs | 47 ++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 44fe0e8243a..ebc895a11c7 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -108,25 +108,6 @@ namespace Microsoft.FSharp.Collections interface System.IDisposable with member this.Dispose() = this.Dispose() - let mapi2 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) : IEnumerator<_> = - let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) - let i = ref (-1) - upcast - { new MapEnumerator<_>() with - member this.DoMoveNext curr = - i := !i + 1 - if (e1.MoveNext() && e2.MoveNext()) then - curr <- f.Invoke(!i, e1.Current, e2.Current) - true - else - false - member this.Dispose() = - try - e1.Dispose() - finally - e2.Dispose() - } - let unfold f x : IEnumerator<_> = let state = ref x upcast @@ -635,6 +616,10 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next) + and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = + inherit SeqComponentFactory<'First,'U> () + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Mapi2 (map, input2, result, next) + and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next @@ -831,6 +816,28 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'First,'V>(next) + + let mutable idx = 0 + let input2 = enumerable2.GetEnumerator () + let mapi2' = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt map + + override __.ProcessNext (input:'First) : bool = + if input2.MoveNext () then + idx <- idx + 1 + Helpers.avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) + else + result.StopFurtherProcessing () + false + + interface ISeqComponent with + override __.OnDispose () = + try + input2.Dispose () + finally + (Helpers.upcastISeqComponent next).OnDispose () + and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -1483,7 +1490,7 @@ namespace Microsoft.FSharp.Collections let mapi2 f source1 source2 = checkNonNull "source1" source1 checkNonNull "source2" source2 - revamp2 (IEnumerator.mapi2 f) source1 source2 + source1 |> seqFactory (SeqComposer.Mapi2Factory (f, source2)) [] let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = From b8ab75b3f2873cf5d945e318b09fda4b53678795 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 06:09:39 +1100 Subject: [PATCH 047/286] Simplified map2 - removing the check of both types --- src/fsharp/FSharp.Core/seq.fs | 34 ++++------------------------------ 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ebc895a11c7..7d79af75777 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -600,13 +600,9 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map - and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = + and Map2Factory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map2First (map, input2, result, next) - - and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = - inherit SeqComponentFactory<'Second,'U> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'Second,'V> = upcast Map2Second (map, input1, result, next) + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map2 (map, input2, result, next) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () @@ -732,7 +728,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = + and Map2<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -752,26 +748,6 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) = - inherit SeqComponent<'Second,'V>(next) - - let input1 = enumerable1.GetEnumerator () - let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map - - override __.ProcessNext (input:'Second) : bool = - if input1.MoveNext () then - Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) - else - result.StopFurtherProcessing () - false - - interface ISeqComponent with - override __.OnDispose () = - try - input1.Dispose () - finally - (Helpers.upcastISeqComponent next).OnDispose () - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:Result<'V>, next:SeqComponent<'U,'V>) = inherit SeqComponent<'First,'V>(next) @@ -1496,9 +1472,7 @@ namespace Microsoft.FSharp.Collections let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = checkNonNull "source1" source1 checkNonNull "source2" source2 - match source1 with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2)) - | _ -> source2 |> seqFactory (SeqComposer.Map2SecondFactory (f, source1)) + source1 |> seqFactory (SeqComposer.Map2Factory (f, source2)) [] let map3 f source1 source2 source3 = From 0fab9e46d276f992c5be99110e9fa5f65250c28c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 10:15:33 +1100 Subject: [PATCH 048/286] Seq.unfold --- src/fsharp/FSharp.Core/seq.fs | 109 +++++++++++++++++----------------- 1 file changed, 53 insertions(+), 56 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 7d79af75777..c7fd9688589 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -70,59 +70,6 @@ namespace Microsoft.FSharp.Collections if index = 0 then e.Current else nth (index-1) e - [] - type MapEnumeratorState = - | NotStarted - | InProcess - | Finished - - [] - type MapEnumerator<'T> () = - let mutable state = NotStarted - [] - val mutable private curr : 'T - - member this.GetCurrent () = - match state with - | NotStarted -> notStarted() - | Finished -> alreadyFinished() - | InProcess -> () - this.curr - - abstract DoMoveNext : byref<'T> -> bool - abstract Dispose : unit -> unit - - interface IEnumerator<'T> with - member this.Current = this.GetCurrent() - - interface IEnumerator with - member this.Current = box(this.GetCurrent()) - member this.MoveNext () = - state <- InProcess - if this.DoMoveNext(&this.curr) then - true - else - state <- Finished - false - member this.Reset() = noReset() - interface System.IDisposable with - member this.Dispose() = this.Dispose() - - let unfold f x : IEnumerator<_> = - let state = ref x - upcast - { new MapEnumerator<_>() with - member this.DoMoveNext curr = - match f !state with - | None -> false - | Some(r,s) -> - curr <- r - state := s - true - member this.Dispose() = () - } - - let readAndClear r = lock r (fun () -> match !r with None -> None | Some _ as res -> r := None; res) @@ -1152,6 +1099,56 @@ namespace Microsoft.FSharp.Collections fold initialState alist + module Unfold = + type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) + + let mutable current = state + + let rec moveNext () = + match generator current with + | None -> false + | Some (item, nextState) -> + current <- nextState + if seqComponent.ProcessNext item then + true + else + moveNext () + + interface IEnumerator with + member __.MoveNext () = + signal.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:SeqComponentFactory<'T,'U>) = + inherit Enumerable.EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (Tail result), result)) + + override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory (current, next))) + + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let result = Result<'U> () + let components = current.Create result (Tail result) + + let rec fold state current = + match result.Halted, generator current with + | true, _ + | false, None -> state + | false, Some (item, next) -> + if components.ProcessNext item then + fold (folder'.Invoke (state, result.Current)) next + else + fold state next + + fold initialState 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. @@ -1246,7 +1243,7 @@ namespace Microsoft.FSharp.Collections let upto lastOption f = match lastOption with - | Some b when b<0 -> Empty() // a request for -ve length returns empty sequence + | 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) @@ -1326,14 +1323,14 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers let mkDelayedSeq (f: unit -> IEnumerable<'T>) = mkSeq (fun () -> f().GetEnumerator()) - let mkUnfoldSeq f x = mkSeq (fun () -> IEnumerator.unfold f x) let inline indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) [] let delay f = mkDelayedSeq f [] - let unfold f x = mkUnfoldSeq f x + let unfold (generator:'State->option<'T * 'State>) (state:'State) : seq<'T> = + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Unfold.Enumerable<'T,'T,'State>(generator, state, SeqComposer.MapFactory id)) [] let empty<'T> = (EmptyEnumerable :> seq<'T>) From 66116941410c2bddd87266c79be750b3bab41a84 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 10:35:24 +1100 Subject: [PATCH 049/286] Added an IdentityFactory Identity can be used to wrap basic containers into SeqComposer compatible types, but can safely be removed when composing the components. --- src/fsharp/FSharp.Core/seq.fs | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index c7fd9688589..67966c3b780 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -518,11 +518,24 @@ namespace Microsoft.FSharp.Collections type [] SeqComponentFactory<'T,'U> () = abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V> + abstract IsIdentity : bool - and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = + default __.IsIdentity = false + + and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = inherit SeqComponentFactory<'T,'V> () override __.Create<'W> (result:Result<'W>) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create result (second.Create result next) + static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = + let castToTV (factory:obj) = + match factory with + | :? SeqComponentFactory<'T,'V> as result -> result + | _ -> failwith "library implementation error: they types must match when paired with identity" + + if first.IsIdentity then castToTV second + elif second.IsIdentity then castToTV first + else upcast ComposedFactory(first, second) + and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next) @@ -543,6 +556,11 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'T> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter + and IdentityFactory<'T> () = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateMap id + override __.IsIdentity = true + and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map @@ -918,7 +936,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1029,7 +1047,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory.Combine current next)) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1079,7 +1097,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1129,7 +1147,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (Tail result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1216,7 +1234,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1330,7 +1348,7 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : seq<'T> = - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Unfold.Enumerable<'T,'T,'State>(generator, state, SeqComposer.MapFactory id)) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Unfold.Enumerable<'T,'T,'State>(generator, state, SeqComposer.IdentityFactory ())) [] let empty<'T> = (EmptyEnumerable :> seq<'T>) From caec7a3132e03cce40f171d76561ec976690608d Mon Sep 17 00:00:00 2001 From: liboz Date: Fri, 14 Oct 2016 20:13:25 -0400 Subject: [PATCH 050/286] Made map2 more complex (reverted from commit ceaed6cd7cb9f842fb9b47440bff7cedeed74629) Also removed some extra null checks --- src/fsharp/FSharp.Core/seq.fs | 37 ++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 67966c3b780..1cc4923316f 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -565,9 +565,13 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map - and Map2Factory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = + and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map2 (map, input2, result, next) + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map2First (map, input2, result, next) + + and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = + inherit SeqComponentFactory<'Second,'U> () + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'Second,'V> = upcast Map2Second (map, input1, result, next) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () @@ -693,7 +697,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -713,6 +717,26 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'Second,'V>(next) + + let input1 = enumerable1.GetEnumerator () + let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map + + override __.ProcessNext (input:'Second) : bool = + if input1.MoveNext () then + Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) + else + result.StopFurtherProcessing () + false + + interface ISeqComponent with + override __.OnDispose () = + try + input1.Dispose () + finally + (Helpers.upcastISeqComponent next).OnDispose () + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:Result<'V>, next:SeqComponent<'U,'V>) = inherit SeqComponent<'First,'V>(next) @@ -1479,19 +1503,18 @@ namespace Microsoft.FSharp.Collections [] let mapi2 f source1 source2 = - checkNonNull "source1" source1 checkNonNull "source2" source2 source1 |> seqFactory (SeqComposer.Mapi2Factory (f, source2)) [] let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = - checkNonNull "source1" source1 checkNonNull "source2" source2 - source1 |> seqFactory (SeqComposer.Map2Factory (f, source2)) + match source1 with + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2)) + | _ -> source2 |> seqFactory (SeqComposer.Map2SecondFactory (f, source1)) [] let map3 f source1 source2 source3 = - checkNonNull "source1" source1 checkNonNull "source2" source2 checkNonNull "source3" source3 source1 |> seqFactory (SeqComposer.Map3Factory (f, source2, source3)) From ca3e10513677ebb04cfd4f05f0e03ea8b70bafef Mon Sep 17 00:00:00 2001 From: liboz Date: Fri, 14 Oct 2016 20:31:55 -0400 Subject: [PATCH 051/286] fixed to removing the right null check --- src/fsharp/FSharp.Core/seq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 1cc4923316f..f464e41b94b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1508,7 +1508,7 @@ namespace Microsoft.FSharp.Collections [] let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = - checkNonNull "source2" source2 + checkNonNull "source1" source1 match source1 with | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2)) | _ -> source2 |> seqFactory (SeqComposer.Map2SecondFactory (f, source1)) From 521f2ac6c7b97b367d1776987c5c00ed23576dca Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 15 Oct 2016 00:06:36 -0400 Subject: [PATCH 052/286] seq.tail and a fix to takewhile to use avoidtailcall --- src/fsharp/FSharp.Core/seq.fs | 68 ++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index f464e41b94b..b00bf073567 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -605,6 +605,10 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'T> () override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next) + and TailFactory<'T> () = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Tail<'T,'V> (next) + and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Truncate (count, result, next) @@ -877,7 +881,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if predicate input then - next.ProcessNext input + Helpers.avoidTailCall (next.ProcessNext input) else result.StopFurtherProcessing () false @@ -889,6 +893,41 @@ namespace Microsoft.FSharp.Collections result.Current <- input true + and Tail<'T, 'V> (next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let mutable first = true + + override __.ProcessNext (input:'T) : bool = + if first then + first <- false + false + else + Helpers.avoidTailCall (next.ProcessNext input) + + interface ISeqComponent with + override this.OnComplete () = + if first then + invalidArg "source" (SR.GetString(SR.notEnoughElements)) + (Helpers.upcastISeqComponent next).OnComplete () + + and Truncate<'T,'V> (truncateCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let mutable count = 0 + + member __.Count = count + + override __.ProcessNext (input:'T) : bool = + if count < truncateCount then + count <- count + 1 + if count = truncateCount then + result.StopFurtherProcessing () + next.ProcessNext input + else + result.StopFurtherProcessing () + false + module Enumerable = [] type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) = @@ -957,7 +996,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) @@ -968,7 +1007,7 @@ namespace Microsoft.FSharp.Collections let enumerator = enumerable.GetEnumerator () let result = Result<'U> () - let components = current.Create result (Tail result) + let components = current.Create result (Tail<'U> result) let mutable state = initialState while (not result.Halted) && (enumerator.MoveNext ()) do @@ -1068,7 +1107,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory.Combine current next)) @@ -1078,7 +1117,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = 0 let result = Result<'U> () - let components = current.Create result (Tail result) + let components = current.Create result (Tail<'U> result) let mutable state = initialState while (not result.Halted) && (idx < array.Length) do @@ -1118,7 +1157,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) @@ -1127,7 +1166,7 @@ namespace Microsoft.FSharp.Collections let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let result = Result<'U> () - let components = current.Create result (Tail result) + let components = current.Create result (Tail<'U> result) let rec fold state lst = match result.Halted, lst with @@ -1168,7 +1207,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (Tail<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) @@ -1177,7 +1216,7 @@ namespace Microsoft.FSharp.Collections let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let result = Result<'U> () - let components = current.Create result (Tail result) + let components = current.Create result (Tail<'U> result) let rec fold state current = match result.Halted, generator current with @@ -1255,7 +1294,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) @@ -1264,7 +1303,7 @@ namespace Microsoft.FSharp.Collections let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let result = Result<'U> () - let components = current.Create result (Tail result) + let components = current.Create result (Tail<'U> result) let mutable idx = -1 let terminatingIdx = getTerminatingIdx count @@ -2230,12 +2269,7 @@ namespace Microsoft.FSharp.Collections [] let tail (source: seq<'T>) = - checkNonNull "source" source - seq { use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" (SR.GetString(SR.notEnoughElements)) - while e.MoveNext() do - yield e.Current } + source |> seqFactory (SeqComposer.TailFactory ()) [] let last (source : seq<_>) = From bd4686a695d3dc18eadb7907cbe656d5109d37db Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 16:57:55 +1100 Subject: [PATCH 053/286] Seq.ofArray --- src/fsharp/FSharp.Core/seq.fs | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index b00bf073567..6ffd0e00a39 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -101,31 +101,6 @@ namespace Microsoft.FSharp.Collections interface System.IDisposable with member x.Dispose() = dispose() } - [] - type ArrayEnumerator<'T>(arr: 'T array) = - let mutable curr = -1 - let mutable len = arr.Length - member x.Get() = - if curr >= 0 then - if curr >= len then alreadyFinished() - else arr.[curr] - else - notStarted() - interface IEnumerator<'T> with - member x.Current = x.Get() - interface System.Collections.IEnumerator with - member x.MoveNext() = - if curr >= len then false - else - curr <- curr + 1 - (curr < len) - member x.Current = box(x.Get()) - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = () - - let ofArray arr = (new ArrayEnumerator<'T>(arr) :> IEnumerator<'T>) - [] type Singleton<'T>(v:'T) = let mutable started = false @@ -1738,7 +1713,7 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source : 'T array) = checkNonNull "source" source - mkSeq (fun () -> IEnumerator.ofArray source) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory ())) [] let toArray (source : seq<'T>) = From afaf0666944dae99c351e60e08a13974bc4f49f4 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 18:25:43 +1100 Subject: [PATCH 054/286] Seq.rev --- src/fsharp/FSharp.Core/seq.fs | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 6ffd0e00a39..7079db5a55c 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1054,10 +1054,19 @@ namespace Microsoft.FSharp.Collections state module Array = - type Enumerator<'T,'U>(array:array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U>(lazyArray:Lazy>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable idx = 0 + let mutable array = Unchecked.defaultof<_> + + let mutable initMoveNext = Unchecked.defaultof<_> + do + initMoveNext <- + fun () -> + result.SeqState <- SeqProcessNextStates.InProcess + array <- lazyArray.Value + initMoveNext <- ignore let rec moveNext () = if (not result.Halted) && idx < array.Length then @@ -1073,19 +1082,22 @@ namespace Microsoft.FSharp.Collections interface IEnumerator with member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess + initMoveNext () moveNext () - type Enumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) = + type Enumerable<'T,'U>(lazyArray:Lazy>, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() + new(array:array<'T>, current:SeqComponentFactory<'T,'U>) = + Enumerable<'T,'U>((Lazy.CreateFromValue array), current) + interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(lazyArray, current.Create result (Tail<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory.Combine current next)) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(lazyArray, ComposedFactory.Combine current next)) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1094,6 +1106,7 @@ namespace Microsoft.FSharp.Collections let result = Result<'U> () let components = current.Create result (Tail<'U> result) + let array = lazyArray.Value let mutable state = initialState while (not result.Halted) && (idx < array.Length) do if components.ProcessNext array.[idx] then @@ -2284,10 +2297,12 @@ namespace Microsoft.FSharp.Collections [] let rev source = checkNonNull "source" source - mkDelayedSeq (fun () -> + let reverseViaArray = lazy ( let array = source |> toArray Array.Reverse array - array :> seq<_>) + array + ) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(reverseViaArray, SeqComposer.IdentityFactory ())) [] let permute f (source : seq<_>) = From 67864f9fd73a206afae0a8eb7473c9212c97b266 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 18:48:47 +1100 Subject: [PATCH 055/286] Added brackets to disambiguate Lazy --- src/fsharp/FSharp.Core/seq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 7079db5a55c..15699de59d1 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1089,7 +1089,7 @@ namespace Microsoft.FSharp.Collections inherit Enumerable.EnumerableBase<'U>() new(array:array<'T>, current:SeqComponentFactory<'T,'U>) = - Enumerable<'T,'U>((Lazy.CreateFromValue array), current) + Enumerable<'T,'U>((Lazy<_>.CreateFromValue array), current) interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = From 645cbad040e773a61d8736ad34931336c23401f0 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 19:02:09 +1100 Subject: [PATCH 056/286] Seq.permute --- src/fsharp/FSharp.Core/seq.fs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 15699de59d1..9f934c8a37e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2297,18 +2297,14 @@ namespace Microsoft.FSharp.Collections [] let rev source = checkNonNull "source" source - let reverseViaArray = lazy ( - let array = source |> toArray - Array.Reverse array - array - ) - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(reverseViaArray, SeqComposer.IdentityFactory ())) + let lazyReverseViaArray = lazy (let array = source |> toArray in Array.Reverse array; array) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazyReverseViaArray, SeqComposer.IdentityFactory ())) [] - let permute f (source : seq<_>) = + let permute f (source:seq<_>) = checkNonNull "source" source - mkDelayedSeq (fun () -> - source |> toArray |> Array.permute f :> seq<_>) + let lazyPermuteViaArray = lazy (source |> toArray |> Array.permute f) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazyPermuteViaArray, SeqComposer.IdentityFactory ())) [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = From 1f7d4e0915e54156ed4729997d38c37186f6baa8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 19:07:03 +1100 Subject: [PATCH 057/286] Seq.sort(By|With|ByDescending|Descending)? --- src/fsharp/FSharp.Core/seq.fs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 9f934c8a37e..ad8b2b0d63b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2001,26 +2001,20 @@ namespace Microsoft.FSharp.Collections [] let sortBy keyf source = checkNonNull "source" source - mkDelayedSeq (fun () -> - let array = source |> toArray - Array.stableSortInPlaceBy keyf array - array :> seq<_>) + let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlaceBy keyf array; array) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazySortViaArray, SeqComposer.IdentityFactory ())) [] let sort source = checkNonNull "source" source - mkDelayedSeq (fun () -> - let array = source |> toArray - Array.stableSortInPlace array - array :> seq<_>) + let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlace array; array) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazySortViaArray, SeqComposer.IdentityFactory ())) [] let sortWith f source = checkNonNull "source" source - mkDelayedSeq (fun () -> - let array = source |> toArray - Array.stableSortInPlaceWith f array - array :> seq<_>) + let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlaceWith f array; array) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazySortViaArray, SeqComposer.IdentityFactory ())) [] let inline sortByDescending keyf source = From 7c238b00366101a8ce8ccc905db1bcafb75244e1 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 19:24:50 +1100 Subject: [PATCH 058/286] Factory helper create methods for less clutter --- src/fsharp/FSharp.Core/seq.fs | 39 ++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ad8b2b0d63b..576ba32426d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1053,6 +1053,9 @@ namespace Microsoft.FSharp.Collections state + let create enumerable current = + Helpers.upcastEnumerable (Enumerable(enumerable, current)) + module Array = type Enumerator<'T,'U>(lazyArray:Lazy>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) @@ -1088,9 +1091,6 @@ namespace Microsoft.FSharp.Collections type Enumerable<'T,'U>(lazyArray:Lazy>, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() - new(array:array<'T>, current:SeqComponentFactory<'T,'U>) = - Enumerable<'T,'U>((Lazy<_>.CreateFromValue array), current) - interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1115,6 +1115,18 @@ namespace Microsoft.FSharp.Collections state + let createLazy (lazyArray:Lazy>) (current:SeqComponentFactory<'T,'U>) = + Helpers.upcastEnumerable (Enumerable(lazyArray, current)) + + let create (array:array<'T>) (current:SeqComponentFactory<'T,'U>) = + createLazy (Lazy<_>.CreateFromValue array) current + + let createLazyId (lazyArray:Lazy>) = + createLazy lazyArray (IdentityFactory ()) + + let createId (array:array<'T>) = + create array (IdentityFactory ()) + module List = type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) @@ -1168,6 +1180,9 @@ namespace Microsoft.FSharp.Collections fold initialState alist + let create alist current = + Helpers.upcastEnumerable (Enumerable(alist, current)) + module Unfold = type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) @@ -1509,9 +1524,9 @@ namespace Microsoft.FSharp.Collections checkNonNull "source" source match source with | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose createSeqComponent - | :? array<'T> as a -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<_,_>(a, createSeqComponent)) - | :? list<'T> as a -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.List.Enumerable<_,_>(a, createSeqComponent)) - | _ -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Enumerable.Enumerable<_,_>(source, createSeqComponent)) + | :? array<'T> as a -> SeqComposer.Array.create a createSeqComponent + | :? list<'T> as a -> SeqComposer.List.create a createSeqComponent + | _ -> SeqComposer.Enumerable.create source createSeqComponent [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = @@ -1726,7 +1741,7 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source : 'T array) = checkNonNull "source" source - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory ())) + SeqComposer.Array.createId source [] let toArray (source : seq<'T>) = @@ -2002,19 +2017,19 @@ namespace Microsoft.FSharp.Collections let sortBy keyf source = checkNonNull "source" source let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlaceBy keyf array; array) - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazySortViaArray, SeqComposer.IdentityFactory ())) + SeqComposer.Array.createLazyId lazySortViaArray [] let sort source = checkNonNull "source" source let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlace array; array) - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazySortViaArray, SeqComposer.IdentityFactory ())) + SeqComposer.Array.createLazyId lazySortViaArray [] let sortWith f source = checkNonNull "source" source let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlaceWith f array; array) - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazySortViaArray, SeqComposer.IdentityFactory ())) + SeqComposer.Array.createLazyId lazySortViaArray [] let inline sortByDescending keyf source = @@ -2292,13 +2307,13 @@ namespace Microsoft.FSharp.Collections let rev source = checkNonNull "source" source let lazyReverseViaArray = lazy (let array = source |> toArray in Array.Reverse array; array) - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazyReverseViaArray, SeqComposer.IdentityFactory ())) + SeqComposer.Array.createLazyId lazyReverseViaArray [] let permute f (source:seq<_>) = checkNonNull "source" source let lazyPermuteViaArray = lazy (source |> toArray |> Array.permute f) - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazyPermuteViaArray, SeqComposer.IdentityFactory ())) + SeqComposer.Array.createLazyId lazyPermuteViaArray [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = From 97469fad874cef77ce27f6203a7a6615827fc609 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 05:10:24 +1100 Subject: [PATCH 059/286] Replaced Lazy<'T> with (unit->'T) The use of lazy changed the seq's funcitonality, as it would have only been calculated once, even if the sequence was iterated again. --- src/fsharp/FSharp.Core/seq.fs | 57 ++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 576ba32426d..d4129d303c1 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1057,7 +1057,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (Enumerable(enumerable, current)) module Array = - type Enumerator<'T,'U>(lazyArray:Lazy>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable idx = 0 @@ -1068,7 +1068,7 @@ namespace Microsoft.FSharp.Collections initMoveNext <- fun () -> result.SeqState <- SeqProcessNextStates.InProcess - array <- lazyArray.Value + array <- delayedArray () initMoveNext <- ignore let rec moveNext () = @@ -1088,16 +1088,16 @@ namespace Microsoft.FSharp.Collections initMoveNext () moveNext () - type Enumerable<'T,'U>(lazyArray:Lazy>, current:SeqComponentFactory<'T,'U>) = + type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(lazyArray, current.Create result (Tail<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (Tail<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(lazyArray, ComposedFactory.Combine current next)) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1106,7 +1106,7 @@ namespace Microsoft.FSharp.Collections let result = Result<'U> () let components = current.Create result (Tail<'U> result) - let array = lazyArray.Value + let array = delayedArray () let mutable state = initialState while (not result.Halted) && (idx < array.Length) do if components.ProcessNext array.[idx] then @@ -1115,14 +1115,14 @@ namespace Microsoft.FSharp.Collections state - let createLazy (lazyArray:Lazy>) (current:SeqComponentFactory<'T,'U>) = - Helpers.upcastEnumerable (Enumerable(lazyArray, current)) + let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = + Helpers.upcastEnumerable (Enumerable(delayedArray, current)) let create (array:array<'T>) (current:SeqComponentFactory<'T,'U>) = - createLazy (Lazy<_>.CreateFromValue array) current + createDelayed (fun () -> array) current - let createLazyId (lazyArray:Lazy>) = - createLazy lazyArray (IdentityFactory ()) + let createDelayedId (delayedArray:unit -> array<'T>) = + createDelayed delayedArray (IdentityFactory ()) let createId (array:array<'T>) = create array (IdentityFactory ()) @@ -2016,20 +2016,29 @@ namespace Microsoft.FSharp.Collections [] let sortBy keyf source = checkNonNull "source" source - let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlaceBy keyf array; array) - SeqComposer.Array.createLazyId lazySortViaArray + let delayedSort () = + let array = source |> toArray + Array.stableSortInPlaceBy keyf array + array + SeqComposer.Array.createDelayedId delayedSort [] let sort source = checkNonNull "source" source - let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlace array; array) - SeqComposer.Array.createLazyId lazySortViaArray + let delayedSort () = + let array = source |> toArray + Array.stableSortInPlace array + array + SeqComposer.Array.createDelayedId delayedSort [] let sortWith f source = checkNonNull "source" source - let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlaceWith f array; array) - SeqComposer.Array.createLazyId lazySortViaArray + let delayedSort () = + let array = source |> toArray + Array.stableSortInPlaceWith f array + array + SeqComposer.Array.createDelayedId delayedSort [] let inline sortByDescending keyf source = @@ -2306,14 +2315,20 @@ namespace Microsoft.FSharp.Collections [] let rev source = checkNonNull "source" source - let lazyReverseViaArray = lazy (let array = source |> toArray in Array.Reverse array; array) - SeqComposer.Array.createLazyId lazyReverseViaArray + let delayedReverse () = + let array = source |> toArray + Array.Reverse array + array + SeqComposer.Array.createDelayedId delayedReverse [] let permute f (source:seq<_>) = checkNonNull "source" source - let lazyPermuteViaArray = lazy (source |> toArray |> Array.permute f) - SeqComposer.Array.createLazyId lazyPermuteViaArray + let delayedPermute () = + source + |> toArray + |> Array.permute f + SeqComposer.Array.createDelayedId delayedPermute [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = From 50b7c834f3d55c47ffb2fc4c91fc3970337b22be Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 05:15:23 +1100 Subject: [PATCH 060/286] Renamed Tail to SetResult to disambiguate --- src/fsharp/FSharp.Core/seq.fs | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index d4129d303c1..c4a536b9190 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -861,13 +861,6 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing () false - and Tail<'T> (result:Result<'T>) = - inherit SeqComponent<'T,'T>(seqComponentTail) - - override __.ProcessNext (input:'T) : bool = - result.Current <- input - true - and Tail<'T, 'V> (next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -903,6 +896,14 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing () false + // SetResult<> is used at the end of the chain of SeqComponents to assign the final value + type SetResult<'T> (result:Result<'T>) = + inherit SeqComponent<'T,'T>(seqComponentTail) + + override __.ProcessNext (input:'T) : bool = + result.Current <- input + true + module Enumerable = [] type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) = @@ -971,7 +972,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) @@ -982,7 +983,7 @@ namespace Microsoft.FSharp.Collections let enumerator = enumerable.GetEnumerator () let result = Result<'U> () - let components = current.Create result (Tail<'U> result) + let components = current.Create result (SetResult<'U> result) let mutable state = initialState while (not result.Halted) && (enumerator.MoveNext ()) do @@ -1094,7 +1095,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (Tail<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) @@ -1104,7 +1105,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = 0 let result = Result<'U> () - let components = current.Create result (Tail<'U> result) + let components = current.Create result (SetResult<'U> result) let array = delayedArray () let mutable state = initialState @@ -1157,7 +1158,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) @@ -1166,7 +1167,7 @@ namespace Microsoft.FSharp.Collections let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let result = Result<'U> () - let components = current.Create result (Tail<'U> result) + let components = current.Create result (SetResult<'U> result) let rec fold state lst = match result.Halted, lst with @@ -1210,7 +1211,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (Tail<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (SetResult<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) @@ -1219,7 +1220,7 @@ namespace Microsoft.FSharp.Collections let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let result = Result<'U> () - let components = current.Create result (Tail<'U> result) + let components = current.Create result (SetResult<'U> result) let rec fold state current = match result.Halted, generator current with @@ -1297,7 +1298,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (SetResult<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) @@ -1306,7 +1307,7 @@ namespace Microsoft.FSharp.Collections let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let result = Result<'U> () - let components = current.Create result (Tail<'U> result) + let components = current.Create result (SetResult<'U> result) let mutable idx = -1 let terminatingIdx = getTerminatingIdx count From 6e4f4007f002bc759068412b35072fdfa9f7cb46 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 06:11:37 +1100 Subject: [PATCH 061/286] Added Iter --- src/fsharp/FSharp.Core/seq.fs | 91 ++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index c4a536b9190..fed38254f67 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -926,8 +926,9 @@ namespace Microsoft.FSharp.Collections | _ -> failwith "library implementation error: all states should have been handled" and [] EnumerableBase<'T> () = - abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> - abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> + abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> + abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> + abstract member Iter : f:('T->unit) -> unit default this.Append source = Helpers.upcastEnumerable (AppendEnumerable [this; source]) @@ -977,6 +978,16 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) + override this.Iter (f:'U->unit) : unit = + let enumerator = enumerable.GetEnumerator () + let result = Result<'U> () + + let components = current.Create result (SetResult<'U> result) + + while (not result.Halted) && (enumerator.MoveNext ()) do + if components.ProcessNext (enumerator.Current) then + f result.Current + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1042,6 +1053,13 @@ namespace Microsoft.FSharp.Collections override this.Append source = Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) + override this.Iter (f:'T->unit) : unit = + let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) + let enumerator = enumerable.GetEnumerator () + + while enumerator.MoveNext () do + f enumerator.Current + override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1100,6 +1118,17 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) + override this.Iter (f:'U->unit) : unit = + let mutable idx = 0 + let result = Result<'U> () + let components = current.Create result (SetResult<'U> result) + + let array = delayedArray () + while (not result.Halted) && (idx < array.Length) do + if components.ProcessNext array.[idx] then + f result.Current + idx <- idx + 1 + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1163,6 +1192,23 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) + override this.Iter (f:'U->unit) : unit = + let result = Result<'U> () + let components = current.Create result (SetResult<'U> result) + + let rec fold lst = + match result.Halted, lst with + | true, _ + | false, [] -> () + | false, hd :: tl -> + if components.ProcessNext hd then + f result.Current + fold tl + else + fold tl + + fold alist + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1216,6 +1262,23 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) + override this.Iter (f:'U->unit) : unit = + let result = Result<'U> () + let components = current.Create result (SetResult<'U> result) + + let rec fold current = + match result.Halted, generator current with + | true, _ + | false, None -> () + | false, Some (item, next) -> + if components.ProcessNext item then + f result.Current + fold next + else + fold next + + fold state + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1303,6 +1366,24 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) + override this.Iter (iter:'U->unit) : unit = + let result = Result<'U> () + let components = current.Create result (SetResult<'U> result) + + let mutable idx = -1 + let terminatingIdx = getTerminatingIdx count + + let mutable maybeSkipping = true + + while (not result.Halted) && (idx < terminatingIdx) do + if maybeSkipping then + maybeSkipping <- components.Skipping () + + if (not maybeSkipping) && (components.ProcessNext (f (idx+1))) then + iter result.Current + + idx <- idx + 1 + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1389,6 +1470,12 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) + override this.Iter (f:'T->unit): unit = + let enumerator = (Helpers.upcastEnumerable this).GetEnumerator () + + while enumerator.MoveNext () do + f enumerator.Current + override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder From 19cca577535fd71ebdafbaa9d234b8b6f722348e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 06:16:48 +1100 Subject: [PATCH 062/286] Seq.iter & Seq.average --- src/fsharp/FSharp.Core/seq.fs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index fed38254f67..490d1fe808f 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1520,9 +1520,13 @@ namespace Microsoft.FSharp.Collections [] let iter f (source : seq<'T>) = checkNonNull "source" source - use e = source.GetEnumerator() - while e.MoveNext() do - f e.Current + checkNonNull "source" source + match source with + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Iter f + | _ -> + use e = source.GetEnumerator() + while e.MoveNext() do + f e.Current [] let item i (source : seq<'T>) = @@ -2192,12 +2196,11 @@ namespace Microsoft.FSharp.Collections [] let inline average (source: seq< ^a>) : ^a = checkNonNull "source" source - use e = source.GetEnumerator() let mutable acc = LanguagePrimitives.GenericZero< ^a> let mutable count = 0 - while e.MoveNext() do - acc <- Checked.(+) acc e.Current - count <- count + 1 + source |> iter (fun current -> + acc <- Checked.(+) acc current + count <- count + 1) if count = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString LanguagePrimitives.DivideByInt< ^a> acc count From a668e86074682c01f0aed59034838b55a114075e Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 15 Oct 2016 11:34:13 -0400 Subject: [PATCH 063/286] making identity more efficient --- src/fsharp/FSharp.Core/seq.fs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 490d1fe808f..ddcae31e883 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -533,7 +533,7 @@ namespace Microsoft.FSharp.Collections and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateMap id + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Identity (next) override __.IsIdentity = true and MapFactory<'T,'U> (map:'T->'U) = @@ -668,6 +668,12 @@ namespace Microsoft.FSharp.Collections else false + and Identity<'T,'V> (next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + override __.ProcessNext (input:'T) : bool = + Helpers.avoidTailCall (next.ProcessNext input) + and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) = inherit SeqComponent<'T,'V>(next) From 93281857405307d8b8738d5d236fdbf2df35c5d5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 10:09:42 +1100 Subject: [PATCH 064/286] Updated NoNeedToTailcall for Seq.iter changes --- .../analyses/tailcalls.NoNeedToTailcall.output.test.bsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl index 785a337a2f4..983ebaa85f5 100644 --- a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl +++ b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl @@ -41,7 +41,7 @@ value simpleLibraryCall9 at line 63 does not make a critical tailcall value simpleLibraryCall10 at line 65 may make a critical tailcall value simpleLibraryCall11 at line 66 does not make a critical tailcall value simpleLibraryCall12 at line 67 does not make a critical tailcall -value simpleLibraryCall13 at line 68 does not make a critical tailcall +value simpleLibraryCall13 at line 68 may make a critical tailcall value simpleLibraryUse14 at line 69 does not make a critical tailcall value simpleLibraryUse15 at line 70 does not make a critical tailcall value simpleLibraryUse16 at line 71 does not make a critical tailcall From bba16fee5c4dbf0f1faed09c2e556086e74e412d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 18:11:25 +1100 Subject: [PATCH 065/286] Added OnComplete calls to Iter and Folds --- src/fsharp/FSharp.Core/seq.fs | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ddcae31e883..956b92f2871 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -994,6 +994,9 @@ namespace Microsoft.FSharp.Collections if components.ProcessNext (enumerator.Current) then f result.Current + (Helpers.upcastISeqComponent components).OnComplete () + + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1006,6 +1009,8 @@ namespace Microsoft.FSharp.Collections while (not result.Halted) && (enumerator.MoveNext ()) do if components.ProcessNext (enumerator.Current) then state <- folder'.Invoke (state, result.Current) + + (Helpers.upcastISeqComponent components).OnComplete () state @@ -1135,6 +1140,9 @@ namespace Microsoft.FSharp.Collections f result.Current idx <- idx + 1 + (Helpers.upcastISeqComponent components).OnComplete () + + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1149,6 +1157,8 @@ namespace Microsoft.FSharp.Collections state <- folder'.Invoke (state, result.Current) idx <- idx + 1 + (Helpers.upcastISeqComponent components).OnComplete () + state let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = @@ -1205,7 +1215,7 @@ namespace Microsoft.FSharp.Collections let rec fold lst = match result.Halted, lst with | true, _ - | false, [] -> () + | false, [] -> (Helpers.upcastISeqComponent components).OnComplete () | false, hd :: tl -> if components.ProcessNext hd then f result.Current @@ -1224,7 +1234,9 @@ namespace Microsoft.FSharp.Collections let rec fold state lst = match result.Halted, lst with | true, _ - | false, [] -> state + | false, [] -> + (Helpers.upcastISeqComponent components).OnComplete () + state | false, hd :: tl -> if components.ProcessNext hd then fold (folder'.Invoke (state, result.Current)) tl @@ -1275,7 +1287,7 @@ namespace Microsoft.FSharp.Collections let rec fold current = match result.Halted, generator current with | true, _ - | false, None -> () + | false, None -> (Helpers.upcastISeqComponent components).OnComplete () | false, Some (item, next) -> if components.ProcessNext item then f result.Current @@ -1294,7 +1306,9 @@ namespace Microsoft.FSharp.Collections let rec fold state current = match result.Halted, generator current with | true, _ - | false, None -> state + | false, None -> + (Helpers.upcastISeqComponent components).OnComplete () + state | false, Some (item, next) -> if components.ProcessNext item then fold (folder'.Invoke (state, result.Current)) next @@ -1390,6 +1404,8 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 + (Helpers.upcastISeqComponent components).OnComplete () + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1410,6 +1426,8 @@ namespace Microsoft.FSharp.Collections state <- folder'.Invoke (state, result.Current) idx <- idx + 1 + + (Helpers.upcastISeqComponent components).OnComplete () state From c32d8b8ac67e464e2eca1277f3f185441906b31e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 17 Oct 2016 20:17:23 +1100 Subject: [PATCH 066/286] Experimental ForEach Currently this is only implemented on Array. This adds some public surface to the SeqComposer which may be removed. --- src/fsharp/FSharp.Core/seq.fs | 237 ++++++++++++++++++++++----------- src/fsharp/FSharp.Core/seq.fsi | 21 +++ 2 files changed, 182 insertions(+), 76 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 956b92f2871..f95a1799cd5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -448,9 +448,6 @@ namespace Microsoft.FSharp.Collections [] [] module Seq = -// type ISeqEnumerable<'T> = -// abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State - module SeqComposer = open IEnumerator @@ -458,6 +455,32 @@ namespace Microsoft.FSharp.Collections abstract OnComplete : unit -> unit abstract OnDispose : unit -> unit + type ISeqPipeline = + abstract StopFurtherProcessing : unit -> unit + + [] + type SeqConsumer<'T,'U> () = + abstract ProcessNext : input:'T -> bool + + interface ISeqComponent with + member __.OnComplete() = () + member __.OnDispose() = () + + type Fold<'T> (folder:'T->'T->'T, initialState:'T) = + inherit SeqConsumer<'T,'T>() + + let folder = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(folder) + + let mutable folded = initialState + override __.ProcessNext input = + folded <- folder.Invoke (folded, input) + true + member __.Folded = folded + + [] + type SeqEnumerable<'T>() = + abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:(ISeqPipeline->'a) -> 'a + module Helpers = // 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 @@ -471,20 +494,6 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) - type SeqProcessNextStates = - | InProcess = 0 - | NotStarted = 1 - | Finished = 2 - - type Result<'T>() = - let mutable halted = false - - member val SeqState = SeqProcessNextStates.NotStarted with get, set - - member __.StopFurtherProcessing () = halted <- true - member __.Halted = halted - - member val Current = Unchecked.defaultof<'T> with get, set let seqComponentTail = { new ISeqComponent with @@ -492,14 +501,15 @@ namespace Microsoft.FSharp.Collections member __.OnDispose() = () } type [] SeqComponentFactory<'T,'U> () = - abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V> + abstract Create<'V> : ISeqPipeline -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> abstract IsIdentity : bool default __.IsIdentity = false and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = inherit SeqComponentFactory<'T,'V> () - override __.Create<'W> (result:Result<'W>) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create result (second.Create result next) + override __.Create<'W> (result:ISeqPipeline) (next:SeqConsumer<'V,'W>) : SeqConsumer<'T,'W> = + first.Create result (second.Create result next) static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = let castToTV (factory:obj) = @@ -513,83 +523,89 @@ namespace Microsoft.FSharp.Collections and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Choose (filter, next) and DistinctFactory<'T when 'T: equality> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Distinct (next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast DistinctBy (keyFunction, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Except (itemsToExclude, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = + match next with + | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter + | _ -> upcast Filter (filter, next) and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Identity (next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Identity (next) override __.IsIdentity = true and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = + match next with + | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map + | _ -> upcast Map<_,_,_> (map, next) and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map2First (map, input2, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = inherit SeqComponentFactory<'Second,'U> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'Second,'V> = upcast Map2Second (map, input1, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map3 (map, input2, input3, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next) and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Mapi2 (map, input2, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T*'T,'V>) : SeqConsumer<'T,'V> = upcast Pairwise next and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (predicate, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (predicate, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Take (count, result, next) and TailFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Tail<'T,'V> (next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Truncate (count, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next) and [] SeqComponent<'T,'U> (next:ISeqComponent) = - abstract ProcessNext : input:'T -> bool + inherit SeqConsumer<'T,'U>() // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip // and it can only do it at the start of a sequence @@ -607,7 +623,7 @@ namespace Microsoft.FSharp.Collections default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) - and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqComponent<'U,'V>) = + and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -615,7 +631,7 @@ namespace Microsoft.FSharp.Collections | Some value -> Helpers.avoidTailCall (next.ProcessNext value) | None -> false - and Distinct<'T,'V when 'T: equality> (next:SeqComponent<'T,'V>) = + and Distinct<'T,'V when 'T: equality> (next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) @@ -626,7 +642,7 @@ namespace Microsoft.FSharp.Collections else false - and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqComponent<'T,'V>) = + and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) @@ -637,7 +653,7 @@ namespace Microsoft.FSharp.Collections else false - and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqComponent<'T,'V>) = + and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) @@ -648,7 +664,7 @@ namespace Microsoft.FSharp.Collections else false - and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) = + and Filter<'T,'V> (filter:'T->bool, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) @@ -659,7 +675,7 @@ namespace Microsoft.FSharp.Collections else false - and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqComponent<'U,'V>) = + and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -668,13 +684,13 @@ namespace Microsoft.FSharp.Collections else false - and Identity<'T,'V> (next:SeqComponent<'T,'V>) = + and Identity<'T,'V> (next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext input) - and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) = + and Map<'T,'U,'V> (map:'T->'U, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) @@ -682,7 +698,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -702,7 +718,7 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) = + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'Second,'V>(next) let input1 = enumerable1.GetEnumerator () @@ -722,7 +738,7 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:Result<'V>, next:SeqComponent<'U,'V>) = + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -746,7 +762,7 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) = + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -756,7 +772,7 @@ namespace Microsoft.FSharp.Collections else false - and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqComponent<'U,'V>) = + and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) let mutable idx = 0 @@ -766,7 +782,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'First,'V>(next) let mutable idx = 0 @@ -788,7 +804,7 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) = + and Pairwise<'T,'V> (next:SeqConsumer<'T*'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable isFirst = true @@ -804,7 +820,7 @@ namespace Microsoft.FSharp.Collections lastValue <- input Helpers.avoidTailCall (next.ProcessNext currentPair) - and Skip<'T,'V> (skipCount:int, next:SeqComponent<'T,'V>) = + and Skip<'T,'V> (skipCount:int, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -831,7 +847,7 @@ namespace Microsoft.FSharp.Collections [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] (Helpers.upcastISeqComponent next).OnComplete () - and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) = + and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable skip = true @@ -846,7 +862,7 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = + and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>) = inherit Truncate<'T, 'V>(takeCount, result, next) interface ISeqComponent with @@ -857,7 +873,7 @@ namespace Microsoft.FSharp.Collections [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] (Helpers.upcastISeqComponent next).OnComplete () - and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) = + and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -867,7 +883,7 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing () false - and Tail<'T, 'V> (next:SeqComponent<'T,'V>) = + and Tail<'T, 'V> (next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable first = true @@ -885,7 +901,7 @@ namespace Microsoft.FSharp.Collections invalidArg "source" (SR.GetString(SR.notEnoughElements)) (Helpers.upcastISeqComponent next).OnComplete () - and Truncate<'T,'V> (truncateCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = + and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -902,9 +918,24 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing () false + type SeqProcessNextStates = + | InProcess = 0 + | NotStarted = 1 + | Finished = 2 + + type Result<'T>() = + let mutable halted = false + + member val Current = Unchecked.defaultof<'T> with get, set + member val SeqState = SeqProcessNextStates.NotStarted with get, set + member __.Halted = halted + + interface ISeqPipeline with + member __.StopFurtherProcessing () = halted <- true + // SetResult<> is used at the end of the chain of SeqComponents to assign the final value type SetResult<'T> (result:Result<'T>) = - inherit SeqComponent<'T,'T>(seqComponentTail) + inherit SeqConsumer<'T,'T>() override __.ProcessNext (input:'T) : bool = result.Current <- input @@ -932,6 +963,8 @@ namespace Microsoft.FSharp.Collections | _ -> failwith "library implementation error: all states should have been handled" and [] EnumerableBase<'T> () = + inherit SeqEnumerable<'T>() + abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> abstract member Iter : f:('T->unit) -> unit @@ -947,7 +980,8 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" - and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + + and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqConsumer<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, seqComponent) let rec moveNext () = @@ -984,6 +1018,8 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.Iter (f:'U->unit) : unit = let enumerator = enumerable.GetEnumerator () let result = Result<'U> () @@ -1064,6 +1100,8 @@ namespace Microsoft.FSharp.Collections override this.Append source = Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = ignore f; failwith "TBD" + override this.Iter (f:'T->unit) : unit = let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) let enumerator = enumerable.GetEnumerator () @@ -1087,7 +1125,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (Enumerable(enumerable, current)) module Array = - type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:SeqConsumer<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable idx = 0 @@ -1129,6 +1167,25 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + let mutable idx = 0 + let mutable halted = false + + let pipeline = + { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + + let result = f pipeline + let consumer = current.Create pipeline result + + let array = delayedArray () + while (not halted) && (idx < array.Length) do + consumer.ProcessNext array.[idx] |> ignore + idx <- idx + 1 + + (Helpers.upcastISeqComponent consumer).OnComplete () + + result + override this.Iter (f:'U->unit) : unit = let mutable idx = 0 let result = Result<'U> () @@ -1174,7 +1231,7 @@ namespace Microsoft.FSharp.Collections create array (IdentityFactory ()) module List = - type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqConsumer<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable list = alist @@ -1208,6 +1265,8 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.Iter (f:'U->unit) : unit = let result = Result<'U> () let components = current.Create result (SetResult<'U> result) @@ -1249,7 +1308,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (Enumerable(alist, current)) module Unfold = - type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) = + type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:SeqConsumer<'T,'U>, signal:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) let mutable current = state @@ -1280,6 +1339,8 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.Iter (f:'U->unit) : unit = let result = Result<'U> () let components = current.Create result (SetResult<'U> result) @@ -1339,9 +1400,17 @@ namespace Microsoft.FSharp.Collections else System.Int32.MaxValue - type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) = + let makeIsSkipping (consumer:SeqConsumer<'T,'U>) = + match consumer with + | :? SeqComponent<'T,'U> as c -> c.Skipping + | _ -> fun () -> false + + type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqConsumer<'T,'U>, signal:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) + let isSkipping = + makeIsSkipping seqComponent + let terminatingIdx = getTerminatingIdx count @@ -1355,7 +1424,7 @@ namespace Microsoft.FSharp.Collections if maybeSkipping then // Skip can only is only checked at the start of the sequence, so once // triggered, we stay triggered. - maybeSkipping <- seqComponent.Skipping () + maybeSkipping <- isSkipping () if maybeSkipping then moveNext () @@ -1386,18 +1455,23 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.Iter (iter:'U->unit) : unit = let result = Result<'U> () let components = current.Create result (SetResult<'U> result) let mutable idx = -1 let terminatingIdx = getTerminatingIdx count - + + let isSkipping = + makeIsSkipping components + let mutable maybeSkipping = true while (not result.Halted) && (idx < terminatingIdx) do if maybeSkipping then - maybeSkipping <- components.Skipping () + maybeSkipping <- isSkipping () if (not maybeSkipping) && (components.ProcessNext (f (idx+1))) then iter result.Current @@ -1415,12 +1489,15 @@ namespace Microsoft.FSharp.Collections let mutable idx = -1 let terminatingIdx = getTerminatingIdx count + let isSkipping = + makeIsSkipping components + let mutable maybeSkipping = true let mutable state = initialState while (not result.Halted) && (idx < terminatingIdx) do if maybeSkipping then - maybeSkipping <- components.Skipping () + maybeSkipping <- isSkipping () if (not maybeSkipping) && (components.ProcessNext (f (idx+1))) then state <- folder'.Invoke (state, result.Current) @@ -1494,6 +1571,8 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = ignore f; failwith "TBD" + override this.Iter (f:'T->unit): unit = let enumerator = (Helpers.upcastEnumerable this).GetEnumerator () @@ -2202,12 +2281,18 @@ namespace Microsoft.FSharp.Collections else mkDelayedSeq (fun () -> countByRefType keyf source) [] - let inline sum (source: seq< ^a>) : ^a = - use e = source.GetEnumerator() - let mutable acc = LanguagePrimitives.GenericZero< ^a> - while e.MoveNext() do - acc <- Checked.(+) acc e.Current - acc + let inline sum (source:seq<'a>) : 'a = + match source with + | :? SeqComposer.SeqEnumerable<'a> as s -> + let summer = SeqComposer.Fold (Checked.(+), LanguagePrimitives.GenericZero) + s.ForEach (fun _ -> summer) |> ignore + summer.Folded + | _ -> + use e = source.GetEnumerator() + let mutable acc = LanguagePrimitives.GenericZero< ^a> + while e.MoveNext() do + acc <- Checked.(+) acc e.Current + acc [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index f05e9db76dd..6b7bf918cd4 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -13,6 +13,27 @@ namespace Microsoft.FSharp.Collections [] [] module Seq = + module SeqComposer = + type ISeqComponent = + abstract OnComplete : unit -> unit + abstract OnDispose : unit -> unit + + type ISeqPipeline = + abstract StopFurtherProcessing : unit -> unit + + [] + type SeqConsumer<'T,'U> = + abstract ProcessNext : input:'T -> bool + interface ISeqComponent + + type Fold<'T> = + inherit SeqConsumer<'T,'T> + new : folder:('T->'T->'T) * initialState:'T -> Fold<'T> + member Folded : 'T + + [] + type SeqEnumerable<'T> = + abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:(ISeqPipeline->'a) -> 'a /// Returns a new sequence that contains the cartesian product of the two input sequences. /// The first sequence. From 0409181368b68a4262ddc5402ecd37aab0faf0d8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 18:25:12 +1100 Subject: [PATCH 067/286] Fixed signature file, so can now use object expression --- src/fsharp/FSharp.Core/seq.fs | 21 ++++++++++----------- src/fsharp/FSharp.Core/seq.fsi | 9 ++++++--- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index f95a1799cd5..de4e61eb4ad 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -466,16 +466,11 @@ namespace Microsoft.FSharp.Collections member __.OnComplete() = () member __.OnDispose() = () - type Fold<'T> (folder:'T->'T->'T, initialState:'T) = + [] + type AccumulatingConsumer<'T, 'U>(initialState:'U) = inherit SeqConsumer<'T,'T>() - let folder = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(folder) - - let mutable folded = initialState - override __.ProcessNext input = - folded <- folder.Invoke (folded, input) - true - member __.Folded = folded + member val Accumulator = initialState with get, set [] type SeqEnumerable<'T>() = @@ -2284,9 +2279,13 @@ namespace Microsoft.FSharp.Collections let inline sum (source:seq<'a>) : 'a = match source with | :? SeqComposer.SeqEnumerable<'a> as s -> - let summer = SeqComposer.Fold (Checked.(+), LanguagePrimitives.GenericZero) - s.ForEach (fun _ -> summer) |> ignore - summer.Folded + let total = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with + override this.ProcessNext value = + this.Accumulator <- Checked.(+) this.Accumulator value + true }) + total.Accumulator | _ -> use e = source.GetEnumerator() let mutable acc = LanguagePrimitives.GenericZero< ^a> diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 6b7bf918cd4..161cdcdc1aa 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -23,13 +23,16 @@ namespace Microsoft.FSharp.Collections [] type SeqConsumer<'T,'U> = + new : unit -> SeqConsumer<'T,'U> abstract ProcessNext : input:'T -> bool interface ISeqComponent - type Fold<'T> = + [] + type AccumulatingConsumer<'T,'U> = inherit SeqConsumer<'T,'T> - new : folder:('T->'T->'T) * initialState:'T -> Fold<'T> - member Folded : 'T + new : initialState:'U -> AccumulatingConsumer<'T,'U> + member Accumulator : 'U + member Accumulator : 'U with set [] type SeqEnumerable<'T> = From 37090a5f66a15762b250e1b0e51448a50c338d72 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 19:50:47 +1100 Subject: [PATCH 068/286] Provided all ForEach implementations --- src/fsharp/FSharp.Core/seq.fs | 121 ++++++++++++++++++++++++++++++++-- 1 file changed, 115 insertions(+), 6 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index de4e61eb4ad..f1789c5ce59 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -488,6 +488,7 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) + let inline upcastSeqConsumer (t:#SeqConsumer<'a,'b>) : SeqConsumer<'a,'b> = (# "" t : SeqConsumer<'a,'b> #) let seqComponentTail = @@ -1013,7 +1014,21 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + let mutable halted = false + let pipeline = + { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + + let result = f pipeline + let consumer = current.Create pipeline result + + use enumerator = enumerable.GetEnumerator () + while (not halted) && (enumerator.MoveNext ()) do + consumer.ProcessNext enumerator.Current |> ignore + + (Helpers.upcastISeqComponent consumer).OnComplete () + + result override this.Iter (f:'U->unit) : unit = let enumerator = enumerable.GetEnumerator () @@ -1095,7 +1110,23 @@ namespace Microsoft.FSharp.Collections override this.Append source = Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = ignore f; failwith "TBD" + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = + let mutable halted = false + let pipeline = + { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + + let result = f pipeline + let consumer = Helpers.upcastSeqConsumer result + + let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) + use enumerator = enumerable.GetEnumerator () + + while enumerator.MoveNext () do + consumer.ProcessNext enumerator.Current |> ignore + + (Helpers.upcastISeqComponent consumer).OnComplete () + + result override this.Iter (f:'T->unit) : unit = let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) @@ -1260,7 +1291,25 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + let mutable halted = false + let pipeline = + { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + + let result = f pipeline + let consumer = current.Create pipeline result + + let rec iterate lst = + match halted, lst with + | true, _ + | false, [] -> (Helpers.upcastISeqComponent consumer).OnComplete () + | false, hd :: tl -> + consumer.ProcessNext hd |> ignore + iterate tl + + iterate alist + + result override this.Iter (f:'U->unit) : unit = let result = Result<'U> () @@ -1334,7 +1383,25 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + let mutable halted = false + let pipeline = + { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + + let result = f pipeline + let consumer = current.Create pipeline result + + let rec iterate current = + match halted, generator current with + | true, _ + | false, None -> (Helpers.upcastISeqComponent consumer).OnComplete () + | false, Some (item, next) -> + consumer.ProcessNext item |> ignore + iterate next + + iterate state + + result override this.Iter (f:'U->unit) : unit = let result = Result<'U> () @@ -1450,7 +1517,34 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.ForEach (createResult:ISeqPipeline->#SeqConsumer<'U,'U>) = + let mutable halted = false + let pipeline = + { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + + let result = createResult pipeline + let consumer = current.Create pipeline result + + let mutable idx = -1 + let terminatingIdx = getTerminatingIdx count + + let isSkipping = + makeIsSkipping consumer + + let mutable maybeSkipping = true + + while (not halted) && (idx < terminatingIdx) do + if maybeSkipping then + maybeSkipping <- isSkipping () + + if (not maybeSkipping) then + consumer.ProcessNext (f (idx+1)) |> ignore + + idx <- idx + 1 + + (Helpers.upcastISeqComponent consumer).OnComplete () + + result override this.Iter (iter:'U->unit) : unit = let result = Result<'U> () @@ -1566,7 +1660,22 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = ignore f; failwith "TBD" + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = + let mutable halted = false + let pipeline = + { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + + let result = f pipeline + let consumer = Helpers.upcastSeqConsumer result + + use enumerator = (Helpers.upcastEnumerable this).GetEnumerator () + + while enumerator.MoveNext () do + consumer.ProcessNext enumerator.Current |> ignore + + (Helpers.upcastISeqComponent consumer).OnComplete () + + result override this.Iter (f:'T->unit): unit = let enumerator = (Helpers.upcastEnumerable this).GetEnumerator () From 5d329551c59bb4d8992eb217cf4d8eef02a3893e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 19:56:59 +1100 Subject: [PATCH 069/286] Removed Fold --- src/fsharp/FSharp.Core/seq.fs | 138 +++------------------------------- 1 file changed, 9 insertions(+), 129 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index f1789c5ce59..8df8d1b3d3d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1042,24 +1042,6 @@ namespace Microsoft.FSharp.Collections (Helpers.upcastISeqComponent components).OnComplete () - - override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let enumerator = enumerable.GetEnumerator () - let result = Result<'U> () - - let components = current.Create result (SetResult<'U> result) - - let mutable state = initialState - while (not result.Halted) && (enumerator.MoveNext ()) do - if components.ProcessNext (enumerator.Current) then - state <- folder'.Invoke (state, result.Current) - - (Helpers.upcastISeqComponent components).OnComplete () - - state - and AppendEnumerator<'T> (sources:list>) = let sources = sources |> List.rev @@ -1135,18 +1117,6 @@ namespace Microsoft.FSharp.Collections while enumerator.MoveNext () do f enumerator.Current - override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) - let enumerator = enumerable.GetEnumerator () - - let mutable state = initialState - while enumerator.MoveNext () do - state <- folder'.Invoke (state, enumerator.Current) - - state - let create enumerable current = Helpers.upcastEnumerable (Enumerable(enumerable, current)) @@ -1225,25 +1195,6 @@ namespace Microsoft.FSharp.Collections (Helpers.upcastISeqComponent components).OnComplete () - - override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let mutable idx = 0 - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let array = delayedArray () - let mutable state = initialState - while (not result.Halted) && (idx < array.Length) do - if components.ProcessNext array.[idx] then - state <- folder'.Invoke (state, result.Current) - idx <- idx + 1 - - (Helpers.upcastISeqComponent components).OnComplete () - - state - let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = Helpers.upcastEnumerable (Enumerable(delayedArray, current)) @@ -1328,26 +1279,6 @@ namespace Microsoft.FSharp.Collections fold alist - override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let rec fold state lst = - match result.Halted, lst with - | true, _ - | false, [] -> - (Helpers.upcastISeqComponent components).OnComplete () - state - | false, hd :: tl -> - if components.ProcessNext hd then - fold (folder'.Invoke (state, result.Current)) tl - else - fold state tl - - fold initialState alist - let create alist current = Helpers.upcastEnumerable (Enumerable(alist, current)) @@ -1420,26 +1351,6 @@ namespace Microsoft.FSharp.Collections fold state - override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let rec fold state current = - match result.Halted, generator current with - | true, _ - | false, None -> - (Helpers.upcastISeqComponent components).OnComplete () - state - | false, Some (item, next) -> - if components.ProcessNext item then - fold (folder'.Invoke (state, result.Current)) next - else - fold state next - - fold initialState 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. @@ -1569,34 +1480,6 @@ namespace Microsoft.FSharp.Collections (Helpers.upcastISeqComponent components).OnComplete () - override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let mutable idx = -1 - let terminatingIdx = getTerminatingIdx count - - let isSkipping = - makeIsSkipping components - - let mutable maybeSkipping = true - - let mutable state = initialState - while (not result.Halted) && (idx < terminatingIdx) do - if maybeSkipping then - maybeSkipping <- isSkipping () - - if (not maybeSkipping) && (components.ProcessNext (f (idx+1))) then - state <- folder'.Invoke (state, result.Current) - - idx <- idx + 1 - - (Helpers.upcastISeqComponent components).OnComplete () - - state - 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" @@ -1683,17 +1566,6 @@ namespace Microsoft.FSharp.Collections while enumerator.MoveNext () do f enumerator.Current - override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let enumerator = (Helpers.upcastEnumerable this).GetEnumerator () - - let mutable state = initialState - while enumerator.MoveNext () do - state <- folder'.Invoke (state, enumerator.Current) - - state - #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions #else @@ -1956,7 +1828,15 @@ namespace Microsoft.FSharp.Collections let fold<'T,'State> f (x:'State) (source:seq<'T>) = checkNonNull "source" source match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Fold f x + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) + let total = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'State> (x) with + override this.ProcessNext value = + this.Accumulator <- f.Invoke (this.Accumulator, value) + true }) + total.Accumulator | _ -> use e = source.GetEnumerator() let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) From c18465f2eb12fec314c57277ccb0b5396e0e1e30 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 20:01:20 +1100 Subject: [PATCH 070/286] Remove Iter --- src/fsharp/FSharp.Core/seq.fs | 103 ++-------------------------------- 1 file changed, 5 insertions(+), 98 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 8df8d1b3d3d..0aa5f40c43d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -963,7 +963,6 @@ namespace Microsoft.FSharp.Collections abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> - abstract member Iter : f:('T->unit) -> unit default this.Append source = Helpers.upcastEnumerable (AppendEnumerable [this; source]) @@ -1030,18 +1029,6 @@ namespace Microsoft.FSharp.Collections result - override this.Iter (f:'U->unit) : unit = - let enumerator = enumerable.GetEnumerator () - let result = Result<'U> () - - let components = current.Create result (SetResult<'U> result) - - while (not result.Halted) && (enumerator.MoveNext ()) do - if components.ProcessNext (enumerator.Current) then - f result.Current - - (Helpers.upcastISeqComponent components).OnComplete () - and AppendEnumerator<'T> (sources:list>) = let sources = sources |> List.rev @@ -1110,13 +1097,6 @@ namespace Microsoft.FSharp.Collections result - override this.Iter (f:'T->unit) : unit = - let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) - let enumerator = enumerable.GetEnumerator () - - while enumerator.MoveNext () do - f enumerator.Current - let create enumerable current = Helpers.upcastEnumerable (Enumerable(enumerable, current)) @@ -1182,19 +1162,6 @@ namespace Microsoft.FSharp.Collections result - override this.Iter (f:'U->unit) : unit = - let mutable idx = 0 - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let array = delayedArray () - while (not result.Halted) && (idx < array.Length) do - if components.ProcessNext array.[idx] then - f result.Current - idx <- idx + 1 - - (Helpers.upcastISeqComponent components).OnComplete () - let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = Helpers.upcastEnumerable (Enumerable(delayedArray, current)) @@ -1262,23 +1229,6 @@ namespace Microsoft.FSharp.Collections result - override this.Iter (f:'U->unit) : unit = - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let rec fold lst = - match result.Halted, lst with - | true, _ - | false, [] -> (Helpers.upcastISeqComponent components).OnComplete () - | false, hd :: tl -> - if components.ProcessNext hd then - f result.Current - fold tl - else - fold tl - - fold alist - let create alist current = Helpers.upcastEnumerable (Enumerable(alist, current)) @@ -1334,23 +1284,6 @@ namespace Microsoft.FSharp.Collections result - override this.Iter (f:'U->unit) : unit = - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let rec fold current = - match result.Halted, generator current with - | true, _ - | false, None -> (Helpers.upcastISeqComponent components).OnComplete () - | false, Some (item, next) -> - if components.ProcessNext item then - f result.Current - fold next - else - fold next - - fold 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. @@ -1457,29 +1390,6 @@ namespace Microsoft.FSharp.Collections result - override this.Iter (iter:'U->unit) : unit = - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let mutable idx = -1 - let terminatingIdx = getTerminatingIdx count - - let isSkipping = - makeIsSkipping components - - let mutable maybeSkipping = true - - while (not result.Halted) && (idx < terminatingIdx) do - if maybeSkipping then - maybeSkipping <- isSkipping () - - if (not maybeSkipping) && (components.ProcessNext (f (idx+1))) then - iter result.Current - - idx <- idx + 1 - - (Helpers.upcastISeqComponent components).OnComplete () - 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" @@ -1560,12 +1470,6 @@ namespace Microsoft.FSharp.Collections result - override this.Iter (f:'T->unit): unit = - let enumerator = (Helpers.upcastEnumerable this).GetEnumerator () - - while enumerator.MoveNext () do - f enumerator.Current - #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions #else @@ -1598,10 +1502,13 @@ namespace Microsoft.FSharp.Collections [] let iter f (source : seq<'T>) = - checkNonNull "source" source checkNonNull "source" source match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Iter f + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> + s.ForEach (fun _ -> + { new SeqComposer.SeqConsumer<'T,'T> () with + override this.ProcessNext value = + f value; true }) |> ignore | _ -> use e = source.GetEnumerator() while e.MoveNext() do From 9fad988768a8ea5adc5d7a8d43a0c9c00b13e4c3 Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 18 Oct 2016 20:18:13 -0400 Subject: [PATCH 071/286] sumby, average, averageby, max, maxby, min, minby --- src/fsharp/FSharp.Core/seq.fs | 268 +++++++++++++++++++++++++--------- 1 file changed, 196 insertions(+), 72 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 0aa5f40c43d..557f7b59e75 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2191,66 +2191,150 @@ namespace Microsoft.FSharp.Collections [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = - use e = source.GetEnumerator() - let mutable acc = LanguagePrimitives.GenericZero< ^U> - while e.MoveNext() do - acc <- Checked.(+) acc (f e.Current) - acc + match source with + | :? SeqComposer.SeqEnumerable<'T> as s -> + let total = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + override this.ProcessNext value = + this.Accumulator <- Checked.(+) this.Accumulator (f value) + true }) + total.Accumulator + | _ -> + use e = source.GetEnumerator() + let mutable acc = LanguagePrimitives.GenericZero< ^U> + while e.MoveNext() do + acc <- Checked.(+) acc (f e.Current) + acc [] let inline average (source: seq< ^a>) : ^a = - checkNonNull "source" source - let mutable acc = LanguagePrimitives.GenericZero< ^a> - let mutable count = 0 - source |> iter (fun current -> - acc <- Checked.(+) acc current - count <- count + 1) - if count = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - LanguagePrimitives.DivideByInt< ^a> acc count + match source with + | :? SeqComposer.SeqEnumerable<'a> as s -> + let mutable count = 0 + let total = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with + override this.ProcessNext value = + this.Accumulator <- Checked.(+) this.Accumulator value + count <- count + 1 + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if count = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + LanguagePrimitives.DivideByInt< ^a> total.Accumulator count + | _ -> + checkNonNull "source" source + let mutable acc = LanguagePrimitives.GenericZero< ^a> + let mutable count = 0 + source |> iter (fun current -> + acc <- Checked.(+) acc current + count <- count + 1) + if count = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + LanguagePrimitives.DivideByInt< ^a> acc count [] let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = - checkNonNull "source" source - use e = source.GetEnumerator() - let mutable acc = LanguagePrimitives.GenericZero< ^U> - let mutable count = 0 - while e.MoveNext() do - acc <- Checked.(+) acc (f e.Current) - count <- count + 1 - if count = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - LanguagePrimitives.DivideByInt< ^U> acc count + match source with + | :? SeqComposer.SeqEnumerable<'T> as s -> + let mutable count = 0 + let total = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + override this.ProcessNext value = + this.Accumulator <- Checked.(+) this.Accumulator (f value) + count <- count + 1 + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if count = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + LanguagePrimitives.DivideByInt< ^U> total.Accumulator count + | _ -> + checkNonNull "source" source + use e = source.GetEnumerator() + let mutable acc = LanguagePrimitives.GenericZero< ^U> + let mutable count = 0 + while e.MoveNext() do + acc <- Checked.(+) acc (f e.Current) + count <- count + 1 + if count = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + LanguagePrimitives.DivideByInt< ^U> acc count [] let inline min (source: seq<_>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let mutable acc = e.Current - while e.MoveNext() do - let curr = e.Current - if curr < acc then - acc <- curr - acc + match source with + | :? SeqComposer.SeqEnumerable<'T> as s -> + let mutable first = false + let min = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + if value < this.Accumulator then + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + min.Accumulator + | _ -> + checkNonNull "source" source + use e = source.GetEnumerator() + if not (e.MoveNext()) then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + let mutable acc = e.Current + while e.MoveNext() do + let curr = e.Current + if curr < acc then + acc <- curr + acc [] let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let first = e.Current - let mutable acc = f first - let mutable accv = first - while e.MoveNext() do - let currv = e.Current - let curr = f currv - if curr < acc then - acc <- curr - accv <- currv - accv + match source with + | :? SeqComposer.SeqEnumerable<'T> as s -> + let mutable first = false + let mutable acc = Unchecked.defaultof<'U> + let min = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + let currValue = value + let curr = f currValue + if curr < acc then + acc <- curr + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + min.Accumulator + | _ -> + checkNonNull "source" source + use e = source.GetEnumerator() + if not (e.MoveNext()) then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + let first = e.Current + let mutable acc = f first + let mutable accv = first + while e.MoveNext() do + let currv = e.Current + let curr = f currv + if curr < acc then + acc <- curr + accv <- currv + accv (* [] @@ -2271,33 +2355,73 @@ namespace Microsoft.FSharp.Collections *) [] let inline max (source: seq<_>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let mutable acc = e.Current - while e.MoveNext() do - let curr = e.Current - if curr > acc then - acc <- curr - acc + match source with + | :? SeqComposer.SeqEnumerable<'T> as s -> + let mutable first = false + let max = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + if value > this.Accumulator then + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + max.Accumulator + | _ -> + checkNonNull "source" source + use e = source.GetEnumerator() + if not (e.MoveNext()) then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + let mutable acc = e.Current + while e.MoveNext() do + let curr = e.Current + if curr > acc then + acc <- curr + acc [] let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let first = e.Current - let mutable acc = f first - let mutable accv = first - while e.MoveNext() do - let currv = e.Current - let curr = f currv - if curr > acc then - acc <- curr - accv <- currv - accv + match source with + | :? SeqComposer.SeqEnumerable<'T> as s -> + let mutable first = false + let mutable acc = Unchecked.defaultof<'U> + let min = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + let currValue = value + let curr = f currValue + if curr > acc then + acc <- curr + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + min.Accumulator + | _ -> + checkNonNull "source" source + use e = source.GetEnumerator() + if not (e.MoveNext()) then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + let first = e.Current + let mutable acc = f first + let mutable accv = first + while e.MoveNext() do + let currv = e.Current + let curr = f currv + if curr > acc then + acc <- curr + accv <- currv + accv (* From 55753e1d6f5900a5b882cb566712d036ec7414fc Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 19 Oct 2016 18:20:55 +1100 Subject: [PATCH 072/286] Removed overzelous upcastSeqConsumer PE verify says no. --- src/fsharp/FSharp.Core/seq.fs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 557f7b59e75..6e297614043 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -488,8 +488,6 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) - let inline upcastSeqConsumer (t:#SeqConsumer<'a,'b>) : SeqConsumer<'a,'b> = (# "" t : SeqConsumer<'a,'b> #) - let seqComponentTail = { new ISeqComponent with @@ -1085,7 +1083,7 @@ namespace Microsoft.FSharp.Collections { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } let result = f pipeline - let consumer = Helpers.upcastSeqConsumer result + let consumer : SeqConsumer<'T,'T> = upcast result let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) use enumerator = enumerable.GetEnumerator () @@ -1459,7 +1457,7 @@ namespace Microsoft.FSharp.Collections { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } let result = f pipeline - let consumer = Helpers.upcastSeqConsumer result + let consumer : SeqConsumer<'T,'T> = upcast result use enumerator = (Helpers.upcastEnumerable this).GetEnumerator () From b922ec233ca6bedfa3e33f7a12f3c5e5ea815d3c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 19 Oct 2016 21:39:49 +1100 Subject: [PATCH 073/286] Appease the NoNeedToTailcall file --- .../analyses/tailcalls.NoNeedToTailcall.output.test.bsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl index 983ebaa85f5..785a337a2f4 100644 --- a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl +++ b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl @@ -41,7 +41,7 @@ value simpleLibraryCall9 at line 63 does not make a critical tailcall value simpleLibraryCall10 at line 65 may make a critical tailcall value simpleLibraryCall11 at line 66 does not make a critical tailcall value simpleLibraryCall12 at line 67 does not make a critical tailcall -value simpleLibraryCall13 at line 68 may make a critical tailcall +value simpleLibraryCall13 at line 68 does not make a critical tailcall value simpleLibraryUse14 at line 69 does not make a critical tailcall value simpleLibraryUse15 at line 70 does not make a critical tailcall value simpleLibraryUse16 at line 71 does not make a critical tailcall From 5f5ff86d57f8b8fb86a686c95f1d5f0167e46581 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 18:27:37 -0400 Subject: [PATCH 074/286] toComposer and implementing sum --- src/fsharp/FSharp.Core/seq.fs | 24 +++++++++++++----------- src/fsharp/FSharp.Core/seq.fsi | 10 ++++++++++ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 6e297614043..eaaf1475f8b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2168,24 +2168,26 @@ namespace Microsoft.FSharp.Collections #endif then mkDelayedSeq (fun () -> countByValueType keyf source) else mkDelayedSeq (fun () -> countByRefType keyf source) + + [] + let toComposer (source:seq<'T>): SeqComposer.SeqEnumerable<'T> = + checkNonNull "source" source + match source with + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(s, (SeqComposer.IdentityFactory())) + | :? array<'T> as a -> upcast SeqComposer.Array.Enumerable((fun () -> a), (SeqComposer.IdentityFactory())) + | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, (SeqComposer.IdentityFactory())) + | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, (SeqComposer.IdentityFactory())) [] let inline sum (source:seq<'a>) : 'a = - match source with - | :? SeqComposer.SeqEnumerable<'a> as s -> - let total = - s.ForEach (fun _ -> + let newSource = toComposer source + let total = + newSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Accumulator <- Checked.(+) this.Accumulator value true }) - total.Accumulator - | _ -> - use e = source.GetEnumerator() - let mutable acc = LanguagePrimitives.GenericZero< ^a> - while e.MoveNext() do - acc <- Checked.(+) acc e.Current - acc + total.Accumulator [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 161cdcdc1aa..cdcd83cd3a9 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -1146,6 +1146,16 @@ namespace Microsoft.FSharp.Collections [] val inline sortByDescending : projection:('T -> 'Key) -> source:seq<'T> -> seq<'T> when 'Key : comparison + /// Builds an SeqEnumerable from the given collection. + /// + /// The input sequence. + /// + /// The result SeqEnumerable. + /// + /// Thrown when the input sequence is null. + [] + val toComposer : source:seq<'T> -> SeqComposer.SeqEnumerable<'T> + /// Returns the sum of the elements in the sequence. /// /// The elements are summed using the + operator and Zero property associated with the generated type. From 0edb2e247e55f17ce88c9eddcf1366e7326e102d Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 18:48:31 -0400 Subject: [PATCH 075/286] singleton identityfactory --- src/fsharp/FSharp.Core/seq.fs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index eaaf1475f8b..2a30a5b3856 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -543,6 +543,8 @@ namespace Microsoft.FSharp.Collections override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Identity (next) override __.IsIdentity = true + static member IdentityFactory = IdentityFactory<'T>() + and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = @@ -1167,10 +1169,10 @@ namespace Microsoft.FSharp.Collections createDelayed (fun () -> array) current let createDelayedId (delayedArray:unit -> array<'T>) = - createDelayed delayedArray (IdentityFactory ()) + createDelayed delayedArray IdentityFactory.IdentityFactory let createId (array:array<'T>) = - create array (IdentityFactory ()) + create array IdentityFactory.IdentityFactory module List = type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqConsumer<'T,'U>, result:Result<'U>) = @@ -1483,7 +1485,7 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : seq<'T> = - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Unfold.Enumerable<'T,'T,'State>(generator, state, SeqComposer.IdentityFactory ())) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Unfold.Enumerable<'T,'T,'State>(generator, state, SeqComposer.IdentityFactory.IdentityFactory)) [] let empty<'T> = (EmptyEnumerable :> seq<'T>) @@ -2173,10 +2175,10 @@ namespace Microsoft.FSharp.Collections let toComposer (source:seq<'T>): SeqComposer.SeqEnumerable<'T> = checkNonNull "source" source match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(s, (SeqComposer.IdentityFactory())) - | :? array<'T> as a -> upcast SeqComposer.Array.Enumerable((fun () -> a), (SeqComposer.IdentityFactory())) - | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, (SeqComposer.IdentityFactory())) - | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, (SeqComposer.IdentityFactory())) + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(s, SeqComposer.IdentityFactory.IdentityFactory) + | :? array<'T> as a -> upcast SeqComposer.Array.Enumerable((fun () -> a), SeqComposer.IdentityFactory.IdentityFactory) + | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, SeqComposer.IdentityFactory.IdentityFactory) + | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory.IdentityFactory) [] let inline sum (source:seq<'a>) : 'a = From 4aa792e0b2a40b427075e4937edccddd696abbed Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 18:54:59 -0400 Subject: [PATCH 076/286] using tocomposer --- src/fsharp/FSharp.Core/seq.fs | 313 +++++++++++++--------------------- 1 file changed, 115 insertions(+), 198 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 2a30a5b3856..80d05f48142 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2182,9 +2182,9 @@ namespace Microsoft.FSharp.Collections [] let inline sum (source:seq<'a>) : 'a = - let newSource = toComposer source + let composedSource = toComposer source let total = - newSource.ForEach (fun _ -> + composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Accumulator <- Checked.(+) this.Accumulator value @@ -2193,151 +2193,95 @@ namespace Microsoft.FSharp.Collections [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = - match source with - | :? SeqComposer.SeqEnumerable<'T> as s -> - let total = - s.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with - override this.ProcessNext value = - this.Accumulator <- Checked.(+) this.Accumulator (f value) - true }) - total.Accumulator - | _ -> - use e = source.GetEnumerator() - let mutable acc = LanguagePrimitives.GenericZero< ^U> - while e.MoveNext() do - acc <- Checked.(+) acc (f e.Current) - acc + let composedSource = toComposer source + let total = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + override this.ProcessNext value = + this.Accumulator <- Checked.(+) this.Accumulator (f value) + true }) + total.Accumulator [] let inline average (source: seq< ^a>) : ^a = - match source with - | :? SeqComposer.SeqEnumerable<'a> as s -> - let mutable count = 0 - let total = - s.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with - override this.ProcessNext value = - this.Accumulator <- Checked.(+) this.Accumulator value - count <- count + 1 - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if count = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - LanguagePrimitives.DivideByInt< ^a> total.Accumulator count - | _ -> - checkNonNull "source" source - let mutable acc = LanguagePrimitives.GenericZero< ^a> - let mutable count = 0 - source |> iter (fun current -> - acc <- Checked.(+) acc current - count <- count + 1) - if count = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - LanguagePrimitives.DivideByInt< ^a> acc count + let composedSource = toComposer source + + let mutable count = 0 + let total = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with + override this.ProcessNext value = + this.Accumulator <- Checked.(+) this.Accumulator value + count <- count + 1 + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if count = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + LanguagePrimitives.DivideByInt< ^a> total.Accumulator count [] let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = - match source with - | :? SeqComposer.SeqEnumerable<'T> as s -> - let mutable count = 0 - let total = - s.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with - override this.ProcessNext value = - this.Accumulator <- Checked.(+) this.Accumulator (f value) - count <- count + 1 - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if count = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - LanguagePrimitives.DivideByInt< ^U> total.Accumulator count - | _ -> - checkNonNull "source" source - use e = source.GetEnumerator() - let mutable acc = LanguagePrimitives.GenericZero< ^U> - let mutable count = 0 - while e.MoveNext() do - acc <- Checked.(+) acc (f e.Current) - count <- count + 1 - if count = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - LanguagePrimitives.DivideByInt< ^U> acc count + let composedSource = toComposer source + let mutable count = 0 + let total = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + override this.ProcessNext value = + this.Accumulator <- Checked.(+) this.Accumulator (f value) + count <- count + 1 + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if count = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + LanguagePrimitives.DivideByInt< ^U> total.Accumulator count [] let inline min (source: seq<_>) = - match source with - | :? SeqComposer.SeqEnumerable<'T> as s -> - let mutable first = false - let min = - s.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - first <- false - if value < this.Accumulator then - this.Accumulator <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - min.Accumulator - | _ -> - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let mutable acc = e.Current - while e.MoveNext() do - let curr = e.Current - if curr < acc then - acc <- curr - acc + let composedSource = toComposer source + + let mutable first = false + let min = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + if value < this.Accumulator then + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + min.Accumulator [] let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = - match source with - | :? SeqComposer.SeqEnumerable<'T> as s -> - let mutable first = false - let mutable acc = Unchecked.defaultof<'U> - let min = - s.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - first <- false - let currValue = value - let curr = f currValue - if curr < acc then - acc <- curr - this.Accumulator <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - min.Accumulator - | _ -> - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let first = e.Current - let mutable acc = f first - let mutable accv = first - while e.MoveNext() do - let currv = e.Current - let curr = f currv - if curr < acc then - acc <- curr - accv <- currv - accv + let composedSource = toComposer source + let mutable first = false + let mutable acc = Unchecked.defaultof<'U> + let min = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + let currValue = value + let curr = f currValue + if curr < acc then + acc <- curr + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + min.Accumulator (* [] let inline minValBy (f : 'T -> 'U) (source: seq<'T>) : 'U = @@ -2357,74 +2301,47 @@ namespace Microsoft.FSharp.Collections *) [] let inline max (source: seq<_>) = - match source with - | :? SeqComposer.SeqEnumerable<'T> as s -> - let mutable first = false - let max = - s.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - first <- false - if value > this.Accumulator then - this.Accumulator <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - max.Accumulator - | _ -> - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let mutable acc = e.Current - while e.MoveNext() do - let curr = e.Current - if curr > acc then - acc <- curr - acc + let composedSource = toComposer source + + let mutable first = false + let max = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + if value > this.Accumulator then + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + max.Accumulator [] let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = - match source with - | :? SeqComposer.SeqEnumerable<'T> as s -> - let mutable first = false - let mutable acc = Unchecked.defaultof<'U> - let min = - s.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - first <- false - let currValue = value - let curr = f currValue - if curr > acc then - acc <- curr - this.Accumulator <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - min.Accumulator - | _ -> - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let first = e.Current - let mutable acc = f first - let mutable accv = first - while e.MoveNext() do - let currv = e.Current - let curr = f currv - if curr > acc then - acc <- curr - accv <- currv - accv + let composedSource = toComposer source + let mutable first = false + let mutable acc = Unchecked.defaultof<'U> + let min = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + let currValue = value + let curr = f currValue + if curr > acc then + acc <- curr + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + min.Accumulator (* [] From 680d6ae4b7ff796af706122f3956aeba9fccb445 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 19:58:41 -0400 Subject: [PATCH 077/286] implementing previously implementing seq functions using toComposer. Also fixes a bug with the boolean checking first --- src/fsharp/FSharp.Core/seq.fs | 50 ++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 80d05f48142..675a1adc09c 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2243,13 +2243,15 @@ namespace Microsoft.FSharp.Collections let inline min (source: seq<_>) = let composedSource = toComposer source - let mutable first = false + let mutable first = true let min = composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = - first <- false - if value < this.Accumulator then + if first then + first <- false + this.Accumulator <- value + elif value < this.Accumulator then this.Accumulator <- value true interface SeqComposer.ISeqComponent with @@ -2263,18 +2265,22 @@ namespace Microsoft.FSharp.Collections let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = let composedSource = toComposer source - let mutable first = false + let mutable first = true let mutable acc = Unchecked.defaultof<'U> let min = composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = - first <- false - let currValue = value - let curr = f currValue - if curr < acc then - acc <- curr + if first then + first <- false this.Accumulator <- value + else + first <- false + let currValue = value + let curr = f currValue + if curr < acc then + acc <- curr + this.Accumulator <- value true interface SeqComposer.ISeqComponent with member __.OnComplete() = @@ -2303,14 +2309,17 @@ namespace Microsoft.FSharp.Collections let inline max (source: seq<_>) = let composedSource = toComposer source - let mutable first = false + let mutable first = true let max = composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = - first <- false - if value > this.Accumulator then - this.Accumulator <- value + if first then + first <- false + this.Accumulator <- value + else + if value > this.Accumulator then + this.Accumulator <- value true interface SeqComposer.ISeqComponent with member __.OnComplete() = @@ -2323,18 +2332,21 @@ namespace Microsoft.FSharp.Collections let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = let composedSource = toComposer source - let mutable first = false + let mutable first = true let mutable acc = Unchecked.defaultof<'U> let min = composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = - first <- false - let currValue = value - let curr = f currValue - if curr > acc then - acc <- curr + if first then + first <- false this.Accumulator <- value + else + let currValue = value + let curr = f currValue + if curr > acc then + acc <- curr + this.Accumulator <- value true interface SeqComposer.ISeqComponent with member __.OnComplete() = From cc84eb86a85deacdd31f09fecf39361448b85376 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 21:32:50 -0400 Subject: [PATCH 078/286] fix bug with bool --- src/fsharp/FSharp.Core/seq.fs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 675a1adc09c..1a87fc29858 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2271,13 +2271,13 @@ namespace Microsoft.FSharp.Collections composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = + let currValue = value + let curr = f currValue if first then first <- false + acc <- curr this.Accumulator <- value else - first <- false - let currValue = value - let curr = f currValue if curr < acc then acc <- curr this.Accumulator <- value @@ -2315,8 +2315,8 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = if first then - first <- false - this.Accumulator <- value + first <- false + this.Accumulator <- value else if value > this.Accumulator then this.Accumulator <- value @@ -2338,12 +2338,13 @@ namespace Microsoft.FSharp.Collections composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = + let currValue = value + let curr = f currValue if first then first <- false + acc <- curr this.Accumulator <- value else - let currValue = value - let curr = f currValue if curr > acc then acc <- curr this.Accumulator <- value From f7d688aa1c0373f99959b01d1966d5d1c00bc8fb Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 16:55:58 +1100 Subject: [PATCH 079/286] Remove duplicated ISeqPipeline --- src/fsharp/FSharp.Core/seq.fs | 48 ++++++++++++++--------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 1a87fc29858..686c93e20d4 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -937,6 +937,11 @@ namespace Microsoft.FSharp.Collections result.Current <- input true + type Pipeline() = + let mutable halted = false + interface ISeqPipeline with member x.StopFurtherProcessing() = halted <- true + member __.Halted = halted + module Enumerable = [] type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) = @@ -1014,15 +1019,13 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let mutable halted = false - let pipeline = - { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + let pipeline = Pipeline() let result = f pipeline let consumer = current.Create pipeline result use enumerator = enumerable.GetEnumerator () - while (not halted) && (enumerator.MoveNext ()) do + while (not pipeline.Halted) && (enumerator.MoveNext ()) do consumer.ProcessNext enumerator.Current |> ignore (Helpers.upcastISeqComponent consumer).OnComplete () @@ -1080,9 +1083,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = - let mutable halted = false - let pipeline = - { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + let pipeline = Pipeline() let result = f pipeline let consumer : SeqConsumer<'T,'T> = upcast result @@ -1090,7 +1091,7 @@ namespace Microsoft.FSharp.Collections let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) use enumerator = enumerable.GetEnumerator () - while enumerator.MoveNext () do + while (not pipeline.Halted) && (enumerator.MoveNext ()) do consumer.ProcessNext enumerator.Current |> ignore (Helpers.upcastISeqComponent consumer).OnComplete () @@ -1145,16 +1146,13 @@ namespace Microsoft.FSharp.Collections override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = let mutable idx = 0 - let mutable halted = false - - let pipeline = - { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + let pipeline = Pipeline () let result = f pipeline let consumer = current.Create pipeline result let array = delayedArray () - while (not halted) && (idx < array.Length) do + while (not pipeline.Halted) && (idx < array.Length) do consumer.ProcessNext array.[idx] |> ignore idx <- idx + 1 @@ -1210,15 +1208,13 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let mutable halted = false - let pipeline = - { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + let pipeline = Pipeline () let result = f pipeline let consumer = current.Create pipeline result let rec iterate lst = - match halted, lst with + match pipeline.Halted, lst with | true, _ | false, [] -> (Helpers.upcastISeqComponent consumer).OnComplete () | false, hd :: tl -> @@ -1265,15 +1261,13 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let mutable halted = false - let pipeline = - { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + let pipeline = Pipeline () let result = f pipeline let consumer = current.Create pipeline result let rec iterate current = - match halted, generator current with + match pipeline.Halted, generator current with | true, _ | false, None -> (Helpers.upcastISeqComponent consumer).OnComplete () | false, Some (item, next) -> @@ -1362,9 +1356,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) override this.ForEach (createResult:ISeqPipeline->#SeqConsumer<'U,'U>) = - let mutable halted = false - let pipeline = - { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + let pipeline = Pipeline () let result = createResult pipeline let consumer = current.Create pipeline result @@ -1377,7 +1369,7 @@ namespace Microsoft.FSharp.Collections let mutable maybeSkipping = true - while (not halted) && (idx < terminatingIdx) do + while (not pipeline.Halted) && (idx < terminatingIdx) do if maybeSkipping then maybeSkipping <- isSkipping () @@ -1454,16 +1446,14 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = - let mutable halted = false - let pipeline = - { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + let pipeline = Pipeline () let result = f pipeline let consumer : SeqConsumer<'T,'T> = upcast result use enumerator = (Helpers.upcastEnumerable this).GetEnumerator () - while enumerator.MoveNext () do + while (not pipeline.Halted) && (enumerator.MoveNext ()) do consumer.ProcessNext enumerator.Current |> ignore (Helpers.upcastISeqComponent consumer).OnComplete () From 415eede184f596824901ce85840de0af57713602 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 17:56:26 +1100 Subject: [PATCH 080/286] Just a straight cast when EnumerableBase --- src/fsharp/FSharp.Core/seq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 686c93e20d4..1088bddf75b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2165,7 +2165,7 @@ namespace Microsoft.FSharp.Collections let toComposer (source:seq<'T>): SeqComposer.SeqEnumerable<'T> = checkNonNull "source" source match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(s, SeqComposer.IdentityFactory.IdentityFactory) + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast s | :? array<'T> as a -> upcast SeqComposer.Array.Enumerable((fun () -> a), SeqComposer.IdentityFactory.IdentityFactory) | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, SeqComposer.IdentityFactory.IdentityFactory) | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory.IdentityFactory) From 6b9ae634c3852a3457acdaac7cfb4f3b8785a2a4 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 18:24:25 +1100 Subject: [PATCH 081/286] Simplified Identity --- src/fsharp/FSharp.Core/seq.fs | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 1088bddf75b..731e9db3114 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -496,9 +496,6 @@ namespace Microsoft.FSharp.Collections type [] SeqComponentFactory<'T,'U> () = abstract Create<'V> : ISeqPipeline -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> - abstract IsIdentity : bool - - default __.IsIdentity = false and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = inherit SeqComponentFactory<'T,'V> () @@ -506,14 +503,7 @@ namespace Microsoft.FSharp.Collections first.Create result (second.Create result next) static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = - let castToTV (factory:obj) = - match factory with - | :? SeqComponentFactory<'T,'V> as result -> result - | _ -> failwith "library implementation error: they types must match when paired with identity" - - if first.IsIdentity then castToTV second - elif second.IsIdentity then castToTV first - else upcast ComposedFactory(first, second) + upcast ComposedFactory(first, second) and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () @@ -540,10 +530,9 @@ namespace Microsoft.FSharp.Collections and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Identity (next) - override __.IsIdentity = true - - static member IdentityFactory = IdentityFactory<'T>() + static let singleton = IdentityFactory<'T>() + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = next + static member IdentityFactory = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () @@ -680,12 +669,6 @@ namespace Microsoft.FSharp.Collections else false - and Identity<'T,'V> (next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - override __.ProcessNext (input:'T) : bool = - Helpers.avoidTailCall (next.ProcessNext input) - and Map<'T,'U,'V> (map:'T->'U, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) From 92b1886f8d010cf08c48c01abf0201e830de7765 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 19:25:47 +1100 Subject: [PATCH 082/286] Avoid creating extra ref objects Using average as an example of using a tuple-like, but mutable, value type to tie the data closer together and avoid allocation. --- src/fsharp/FSharp.Core/seq.fs | 43 ++++++++++++++++++++++++---------- src/fsharp/FSharp.Core/seq.fsi | 13 ++++++++-- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 731e9db3114..f1ede5539fb 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -466,11 +466,26 @@ namespace Microsoft.FSharp.Collections member __.OnComplete() = () member __.OnDispose() = () + [] + type MutableData<'a,'b> = + val mutable _1 : 'a + val mutable _2 : 'b + + new (a:'a, b: 'b) = { + _1 = a + _2 = b + } + [] - type AccumulatingConsumer<'T, 'U>(initialState:'U) = - inherit SeqConsumer<'T,'T>() + type AccumulatingConsumer<'T, 'U> = + inherit SeqConsumer<'T,'T> + + val mutable Accumulator : 'U - member val Accumulator = initialState with get, set + new (initialState) = { + inherit SeqConsumer<'T,'T>() + Accumulator = initialState + } [] type SeqEnumerable<'T>() = @@ -2153,6 +2168,8 @@ namespace Microsoft.FSharp.Collections | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, SeqComposer.IdentityFactory.IdentityFactory) | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory.IdentityFactory) + let inline foreach f (source:SeqComposer.SeqEnumerable<_>) = source.ForEach f + [] let inline sum (source:seq<'a>) : 'a = let composedSource = toComposer source @@ -2177,22 +2194,22 @@ namespace Microsoft.FSharp.Collections [] let inline average (source: seq< ^a>) : ^a = - let composedSource = toComposer source - - let mutable count = 0 let total = - composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'a, SeqComposer.MutableData<'a, int>> (SeqComposer.MutableData(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = - this.Accumulator <- Checked.(+) this.Accumulator value - count <- count + 1 + this.Accumulator._1 <- Checked.(+) this.Accumulator._1 value + this.Accumulator._2 <- this.Accumulator._2 + 1 true + interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if count = 0 then + member this.OnComplete() = + if (this:?>SeqComposer.AccumulatingConsumer<'a, SeqComposer.MutableData<'a, int>>).Accumulator._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - LanguagePrimitives.DivideByInt< ^a> total.Accumulator count + LanguagePrimitives.DivideByInt< ^a> total.Accumulator._1 total.Accumulator._2 [] let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index cdcd83cd3a9..27f20260f61 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -27,12 +27,21 @@ namespace Microsoft.FSharp.Collections abstract ProcessNext : input:'T -> bool interface ISeqComponent + [] + type MutableData<'a,'b> = + struct + new : a:'a * b:'b -> MutableData<'a,'b> + val mutable _1: 'a + val mutable _2: 'b + end + [] type AccumulatingConsumer<'T,'U> = + class inherit SeqConsumer<'T,'T> new : initialState:'U -> AccumulatingConsumer<'T,'U> - member Accumulator : 'U - member Accumulator : 'U with set + val mutable Accumulator: 'U + end [] type SeqEnumerable<'T> = From 16f4a19a10d31264e236f7a880ce6a4387580c51 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 20:08:10 +1100 Subject: [PATCH 083/286] Ensuring that OnDispose is called from ForEach --- src/fsharp/FSharp.Core/seq.fs | 178 ++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 84 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index f1ede5539fb..eff58cc5ac5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1008,6 +1008,10 @@ namespace Microsoft.FSharp.Collections and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = inherit EnumerableBase<'U>() + static let iterate (enumerator:IEnumerator<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + while (not pipeline.Halted) && (enumerator.MoveNext ()) do + consumer.ProcessNext enumerator.Current |> ignore + interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1018,17 +1022,15 @@ namespace Microsoft.FSharp.Collections override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = let pipeline = Pipeline() - let result = f pipeline let consumer = current.Create pipeline result - use enumerator = enumerable.GetEnumerator () - while (not pipeline.Halted) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - - (Helpers.upcastISeqComponent consumer).OnComplete () - - result + try + iterate enumerator pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () and AppendEnumerator<'T> (sources:list>) = let sources = sources |> List.rev @@ -1070,6 +1072,10 @@ namespace Microsoft.FSharp.Collections and AppendEnumerable<'T> (sources:list>) = inherit EnumerableBase<'T>() + static let iterate (enumerator:IEnumerator<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + while (not pipeline.Halted) && (enumerator.MoveNext ()) do + consumer.ProcessNext enumerator.Current |> ignore + interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = Helpers.upcastEnumerator (new AppendEnumerator<_> (sources)) @@ -1082,19 +1088,16 @@ namespace Microsoft.FSharp.Collections override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = let pipeline = Pipeline() - let result = f pipeline let consumer : SeqConsumer<'T,'T> = upcast result - let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) use enumerator = enumerable.GetEnumerator () - - while (not pipeline.Halted) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - - (Helpers.upcastISeqComponent consumer).OnComplete () - - result + try + iterate enumerator pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () let create enumerable current = Helpers.upcastEnumerable (Enumerable(enumerable, current)) @@ -1134,6 +1137,12 @@ namespace Microsoft.FSharp.Collections type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() + static let iterate (array:array<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let mutable idx = 0 + while (not pipeline.Halted) && (idx < array.Length) do + consumer.ProcessNext array.[idx] |> ignore + idx <- idx + 1 + interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1143,20 +1152,15 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let mutable idx = 0 let pipeline = Pipeline () - let result = f pipeline let consumer = current.Create pipeline result - - let array = delayedArray () - while (not pipeline.Halted) && (idx < array.Length) do - consumer.ProcessNext array.[idx] |> ignore - idx <- idx + 1 - - (Helpers.upcastISeqComponent consumer).OnComplete () - - result + try + iterate (delayedArray ()) pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = Helpers.upcastEnumerable (Enumerable(delayedArray, current)) @@ -1194,6 +1198,16 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext list + let iterate (alist:list<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let rec iterate lst = + match pipeline.Halted, lst with + | true, _ + | false, [] -> () + | false, hd :: tl -> + consumer.ProcessNext hd |> ignore + iterate tl + iterate alist + type Enumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() @@ -1207,21 +1221,14 @@ namespace Microsoft.FSharp.Collections override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = let pipeline = Pipeline () - let result = f pipeline let consumer = current.Create pipeline result - - let rec iterate lst = - match pipeline.Halted, lst with - | true, _ - | false, [] -> (Helpers.upcastISeqComponent consumer).OnComplete () - | false, hd :: tl -> - consumer.ProcessNext hd |> ignore - iterate tl - - iterate alist - - result + try + iterate alist pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () let create alist current = Helpers.upcastEnumerable (Enumerable(alist, current)) @@ -1250,6 +1257,17 @@ namespace Microsoft.FSharp.Collections type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() + static let iterate (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let rec iterate current = + match pipeline.Halted, generator current with + | true, _ + | false, None -> () + | false, Some (item, next) -> + consumer.ProcessNext item |> ignore + iterate next + + iterate state + interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1260,21 +1278,14 @@ namespace Microsoft.FSharp.Collections override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = let pipeline = Pipeline () - let result = f pipeline let consumer = current.Create pipeline result - - let rec iterate current = - match pipeline.Halted, generator current with - | true, _ - | false, None -> (Helpers.upcastISeqComponent consumer).OnComplete () - | false, Some (item, next) -> - consumer.ProcessNext item |> ignore - iterate next - - iterate state - - result + try + iterate generator state pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () module Init = // The original implementation of "init" delayed the calculation of Current, and so it was possible @@ -1345,6 +1356,18 @@ namespace Microsoft.FSharp.Collections type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() + static let iterate f (terminatingIdx:int) (isSkipping) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let mutable idx = -1 + let mutable maybeSkipping = true + while (not pipeline.Halted) && (idx < terminatingIdx) do + if maybeSkipping then + maybeSkipping <- isSkipping () + + if (not maybeSkipping) then + consumer.ProcessNext (f (idx+1)) |> ignore + + idx <- idx + 1 + interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1355,30 +1378,16 @@ namespace Microsoft.FSharp.Collections override this.ForEach (createResult:ISeqPipeline->#SeqConsumer<'U,'U>) = let pipeline = Pipeline () - let result = createResult pipeline let consumer = current.Create pipeline result - - let mutable idx = -1 let terminatingIdx = getTerminatingIdx count - - let isSkipping = - makeIsSkipping consumer - - let mutable maybeSkipping = true - - while (not pipeline.Halted) && (idx < terminatingIdx) do - if maybeSkipping then - maybeSkipping <- isSkipping () - - if (not maybeSkipping) then - consumer.ProcessNext (f (idx+1)) |> ignore - - idx <- idx + 1 - - (Helpers.upcastISeqComponent consumer).OnComplete () - - result + let isSkipping = makeIsSkipping consumer + try + iterate f terminatingIdx isSkipping pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () let upto lastOption f = match lastOption with @@ -1433,6 +1442,10 @@ namespace Microsoft.FSharp.Collections type EnumerableDecider<'T>(count:Nullable, f:int->'T) = inherit Enumerable.EnumerableBase<'T>() + static let iterate (enumerator:IEnumerator<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'T>) = + while (not pipeline.Halted) && (enumerator.MoveNext ()) do + consumer.ProcessNext enumerator.Current |> ignore + 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 @@ -1445,18 +1458,15 @@ namespace Microsoft.FSharp.Collections override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = let pipeline = Pipeline () - let result = f pipeline let consumer : SeqConsumer<'T,'T> = upcast result - use enumerator = (Helpers.upcastEnumerable this).GetEnumerator () - - while (not pipeline.Halted) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - - (Helpers.upcastISeqComponent consumer).OnComplete () - - result + try + iterate enumerator pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions From 8a4033493246375362290240ccdb62061ef210e9 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 20 Oct 2016 07:24:44 -0400 Subject: [PATCH 084/286] Seq.iteri, exists, contains, forall, trypick, pick, tryfind, find, reduce, last, trylast cleanup for Seq.iter, fold Also moves the functions in the seq.fsi file to be alphabetical --- src/fsharp/FSharp.Core/seq.fs | 235 +++++++++++++++++++-------------- src/fsharp/FSharp.Core/seq.fsi | 20 +-- 2 files changed, 146 insertions(+), 109 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index eff58cc5ac5..7b97f2493f3 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1477,6 +1477,17 @@ namespace Microsoft.FSharp.Collections let mkDelayedSeq (f: unit -> IEnumerable<'T>) = mkSeq (fun () -> f().GetEnumerator()) let inline indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) + + [] + let toComposer (source:seq<'T>): SeqComposer.SeqEnumerable<'T> = + checkNonNull "source" source + match source with + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast s + | :? array<'T> as a -> upcast SeqComposer.Array.Enumerable((fun () -> a), SeqComposer.IdentityFactory.IdentityFactory) + | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, SeqComposer.IdentityFactory.IdentityFactory) + | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory.IdentityFactory) + + let inline foreach f (source:SeqComposer.SeqEnumerable<_>) = source.ForEach f [] let delay f = mkDelayedSeq f @@ -1500,17 +1511,13 @@ namespace Microsoft.FSharp.Collections [] let iter f (source : seq<'T>) = - checkNonNull "source" source - match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> - s.ForEach (fun _ -> + source + |> toComposer + |> foreach (fun _ -> { new SeqComposer.SeqConsumer<'T,'T> () with override this.ProcessNext value = - f value; true }) |> ignore - | _ -> - use e = source.GetEnumerator() - while e.MoveNext() do - f e.Current + f value; true }) + |> ignore [] let item i (source : seq<'T>) = @@ -1531,41 +1538,66 @@ namespace Microsoft.FSharp.Collections [] let iteri f (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() + let composedSource = toComposer source + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) let mutable i = 0 - while e.MoveNext() do - f.Invoke(i, e.Current) - i <- i + 1 + + composedSource.ForEach (fun _ -> + { new SeqComposer.SeqConsumer<'T,'T> () with + override this.ProcessNext value = + f.Invoke(i, value) + i <- i + 1 + true }) + |> ignore [] let exists f (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() - let mutable state = false - while (not state && e.MoveNext()) do - state <- f e.Current - state + let exists = + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.AccumulatingConsumer<'T, bool> (false) with + override this.ProcessNext value = + if this.Accumulator then + pipeline.StopFurtherProcessing() + else + this.Accumulator <- f value + true + }) + exists.Accumulator [] let inline contains element (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() - let mutable state = false - while (not state && e.MoveNext()) do - state <- element = e.Current - state + let contains = + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.AccumulatingConsumer<'T, bool> (false) with + override this.ProcessNext value = + if this.Accumulator then + pipeline.StopFurtherProcessing() + else + this.Accumulator <- element = value + true + }) + contains.Accumulator [] let forall f (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() - let mutable state = true - while (state && e.MoveNext()) do - state <- f e.Current - state - + let forall = + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.AccumulatingConsumer<'T, bool> (true) with + override this.ProcessNext value = + if this.Accumulator then + this.Accumulator <- f value + else + pipeline.StopFurtherProcessing() + true + }) + forall.Accumulator [] let iter2 f (source1 : seq<_>) (source2 : seq<_>) = @@ -1660,33 +1692,45 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() - let mutable res = None - while (Option.isNone res && e.MoveNext()) do - res <- f e.Current - res + let pick = + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.AccumulatingConsumer<'T, Option<'U>> (None) with + override this.ProcessNext value = + if this.Accumulator.IsNone then + this.Accumulator <- f value + else + pipeline.StopFurtherProcessing() + true + }) + pick.Accumulator [] let pick f source = - checkNonNull "source" source match tryPick f source with | None -> indexNotFound() | Some x -> x [] let tryFind f (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() - let mutable res = None - while (Option.isNone res && e.MoveNext()) do - let c = e.Current - if f c then res <- Some(c) - res + let find = + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.AccumulatingConsumer<'T, Option<'T>> (None) with + override this.ProcessNext value = + if this.Accumulator.IsNone then + if f value then + this.Accumulator <- Some(value) + else + pipeline.StopFurtherProcessing() + true + }) + find.Accumulator [] let find f source = - checkNonNull "source" source match tryFind f source with | None -> indexNotFound() | Some x -> x @@ -1731,24 +1775,15 @@ namespace Microsoft.FSharp.Collections [] let fold<'T,'State> f (x:'State) (source:seq<'T>) = - checkNonNull "source" source - match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let total = - s.ForEach (fun _ -> + let composedSource = toComposer source + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) + + let total = composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'T,'State> (x) with override this.ProcessNext value = this.Accumulator <- f.Invoke (this.Accumulator, value) true }) - total.Accumulator - | _ -> - use e = source.GetEnumerator() - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let mutable state = x - while e.MoveNext() do - state <- f.Invoke(state, e.Current) - state + total.Accumulator [] let fold2<'T1,'T2,'State> f (state:'State) (source1: seq<'T1>) (source2: seq<'T2>) = @@ -1768,14 +1803,25 @@ namespace Microsoft.FSharp.Collections [] let reduce f (source : seq<'T>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + let composedSource = toComposer source let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let mutable state = e.Current - while e.MoveNext() do - state <- f.Invoke(state, e.Current) - state + let mutable first = true + + let total = composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + if first then + first <- false + this.Accumulator <- value + else + this.Accumulator <- f.Invoke (this.Accumulator, value) + true + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + total.Accumulator [] let replicate count x = @@ -2169,17 +2215,6 @@ namespace Microsoft.FSharp.Collections then mkDelayedSeq (fun () -> countByValueType keyf source) else mkDelayedSeq (fun () -> countByRefType keyf source) - [] - let toComposer (source:seq<'T>): SeqComposer.SeqEnumerable<'T> = - checkNonNull "source" source - match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast s - | :? array<'T> as a -> upcast SeqComposer.Array.Enumerable((fun () -> a), SeqComposer.IdentityFactory.IdentityFactory) - | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, SeqComposer.IdentityFactory.IdentityFactory) - | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory.IdentityFactory) - - let inline foreach f (source:SeqComposer.SeqEnumerable<_>) = source.ForEach f - [] let inline sum (source:seq<'a>) : 'a = let composedSource = toComposer source @@ -2427,28 +2462,30 @@ namespace Microsoft.FSharp.Collections [] let tail (source: seq<'T>) = source |> seqFactory (SeqComposer.TailFactory ()) - - [] - let last (source : seq<_>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if e.MoveNext() then - let mutable res = e.Current - while (e.MoveNext()) do res <- e.Current - res - else - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - + [] let tryLast (source : seq<_>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if e.MoveNext() then - let mutable res = e.Current - while (e.MoveNext()) do res <- e.Current - Some res - else + let composedSource = toComposer source + let mutable first = true + + let last = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T, 'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + if first then + first <- false + this.Accumulator <- value + true }) + if first then None + else + Some(last.Accumulator) + + [] + let last (source : seq<_>) = + match tryLast source with + | None -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + | Some x -> x [] let exactlyOne (source : seq<_>) = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 27f20260f61..1baeec4685e 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -1155,16 +1155,6 @@ namespace Microsoft.FSharp.Collections [] val inline sortByDescending : projection:('T -> 'Key) -> source:seq<'T> -> seq<'T> when 'Key : comparison - /// Builds an SeqEnumerable from the given collection. - /// - /// The input sequence. - /// - /// The result SeqEnumerable. - /// - /// Thrown when the input sequence is null. - [] - val toComposer : source:seq<'T> -> SeqComposer.SeqEnumerable<'T> - /// Returns the sum of the elements in the sequence. /// /// The elements are summed using the + operator and Zero property associated with the generated type. @@ -1239,6 +1229,16 @@ namespace Microsoft.FSharp.Collections /// Thrown when the input sequence is null. [] val toArray: source:seq<'T> -> 'T[] + + /// Builds an SeqEnumerable from the given collection. + /// + /// The input sequence. + /// + /// The result SeqEnumerable. + /// + /// Thrown when the input sequence is null. + [] + val toComposer : source:seq<'T> -> SeqComposer.SeqEnumerable<'T> /// Builds a list from the given collection. /// From 29b39af6a443ec3667e7cf87ee944aa93251e7a1 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 20 Oct 2016 14:03:04 -0400 Subject: [PATCH 085/286] passing false on process next when ending. --- src/fsharp/FSharp.Core/seq.fs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 7b97f2493f3..73dd69e2f26 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1561,9 +1561,10 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if this.Accumulator then pipeline.StopFurtherProcessing() + false else this.Accumulator <- f value - true + true }) exists.Accumulator @@ -1577,9 +1578,10 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if this.Accumulator then pipeline.StopFurtherProcessing() + false else this.Accumulator <- element = value - true + true }) contains.Accumulator @@ -1593,9 +1595,10 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if this.Accumulator then this.Accumulator <- f value + false else pipeline.StopFurtherProcessing() - true + true }) forall.Accumulator @@ -1700,9 +1703,10 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if this.Accumulator.IsNone then this.Accumulator <- f value + true else pipeline.StopFurtherProcessing() - true + false }) pick.Accumulator @@ -1723,9 +1727,10 @@ namespace Microsoft.FSharp.Collections if this.Accumulator.IsNone then if f value then this.Accumulator <- Some(value) + true else pipeline.StopFurtherProcessing() - true + false }) find.Accumulator From abd7839bfd3b9df0e9c64cd3497fdb79816ced2d Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 20 Oct 2016 16:29:50 -0400 Subject: [PATCH 086/286] fix bug where unfold did not respect the Halted state on Result --- src/fsharp/FSharp.Core/seq.fs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 73dd69e2f26..620f1f9d5ec 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1240,9 +1240,10 @@ namespace Microsoft.FSharp.Collections let mutable current = state let rec moveNext () = - match generator current with - | None -> false - | Some (item, nextState) -> + match signal.Halted, generator current with + | true, _ + | false, None -> false + | false, Some (item, nextState) -> current <- nextState if seqComponent.ProcessNext item then true From 2acea9c9122876f20c5f124f31fef990e9899922 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 13:36:33 +1100 Subject: [PATCH 087/286] Made names a little less verbose --- src/fsharp/FSharp.Core/seq.fs | 134 ++++++++++++++++----------------- src/fsharp/FSharp.Core/seq.fsi | 10 +-- 2 files changed, 72 insertions(+), 72 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 620f1f9d5ec..cac46b72596 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -467,7 +467,7 @@ namespace Microsoft.FSharp.Collections member __.OnDispose() = () [] - type MutableData<'a,'b> = + type Values<'a,'b> = val mutable _1 : 'a val mutable _2 : 'b @@ -477,14 +477,14 @@ namespace Microsoft.FSharp.Collections } [] - type AccumulatingConsumer<'T, 'U> = + type Folder<'T, 'U> = inherit SeqConsumer<'T,'T> - val mutable Accumulator : 'U + val mutable Value : 'U - new (initialState) = { + new (init) = { inherit SeqConsumer<'T,'T>() - Accumulator = initialState + Value = init } [] @@ -1558,16 +1558,16 @@ namespace Microsoft.FSharp.Collections source |> toComposer |> foreach (fun pipeline -> - { new SeqComposer.AccumulatingConsumer<'T, bool> (false) with + { new SeqComposer.Folder<'T, bool> (false) with override this.ProcessNext value = - if this.Accumulator then + if this.Value then pipeline.StopFurtherProcessing() false else - this.Accumulator <- f value + this.Value <- f value true }) - exists.Accumulator + exists.Value [] let inline contains element (source : seq<'T>) = @@ -1575,16 +1575,16 @@ namespace Microsoft.FSharp.Collections source |> toComposer |> foreach (fun pipeline -> - { new SeqComposer.AccumulatingConsumer<'T, bool> (false) with + { new SeqComposer.Folder<'T, bool> (false) with override this.ProcessNext value = - if this.Accumulator then + if this.Value then pipeline.StopFurtherProcessing() false else - this.Accumulator <- element = value + this.Value <- element = value true }) - contains.Accumulator + contains.Value [] let forall f (source : seq<'T>) = @@ -1592,16 +1592,16 @@ namespace Microsoft.FSharp.Collections source |> toComposer |> foreach (fun pipeline -> - { new SeqComposer.AccumulatingConsumer<'T, bool> (true) with + { new SeqComposer.Folder<'T, bool> (true) with override this.ProcessNext value = - if this.Accumulator then - this.Accumulator <- f value + if this.Value then + this.Value <- f value false else pipeline.StopFurtherProcessing() true }) - forall.Accumulator + forall.Value [] let iter2 f (source1 : seq<_>) (source2 : seq<_>) = @@ -1700,16 +1700,16 @@ namespace Microsoft.FSharp.Collections source |> toComposer |> foreach (fun pipeline -> - { new SeqComposer.AccumulatingConsumer<'T, Option<'U>> (None) with + { new SeqComposer.Folder<'T, Option<'U>> (None) with override this.ProcessNext value = - if this.Accumulator.IsNone then - this.Accumulator <- f value + if this.Value.IsNone then + this.Value <- f value true else pipeline.StopFurtherProcessing() false }) - pick.Accumulator + pick.Value [] let pick f source = @@ -1723,17 +1723,17 @@ namespace Microsoft.FSharp.Collections source |> toComposer |> foreach (fun pipeline -> - { new SeqComposer.AccumulatingConsumer<'T, Option<'T>> (None) with + { new SeqComposer.Folder<'T, Option<'T>> (None) with override this.ProcessNext value = - if this.Accumulator.IsNone then + if this.Value.IsNone then if f value then - this.Accumulator <- Some(value) + this.Value <- Some(value) true else pipeline.StopFurtherProcessing() false }) - find.Accumulator + find.Value [] let find f source = @@ -1785,11 +1785,11 @@ namespace Microsoft.FSharp.Collections let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) let total = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'State> (x) with + { new SeqComposer.Folder<'T,'State> (x) with override this.ProcessNext value = - this.Accumulator <- f.Invoke (this.Accumulator, value) + this.Value <- f.Invoke (this.Value, value) true }) - total.Accumulator + total.Value [] let fold2<'T1,'T2,'State> f (state:'State) (source1: seq<'T1>) (source2: seq<'T2>) = @@ -1814,20 +1814,20 @@ namespace Microsoft.FSharp.Collections let mutable first = true let total = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = if first then first <- false - this.Accumulator <- value + this.Value <- value else - this.Accumulator <- f.Invoke (this.Accumulator, value) + this.Value <- f.Invoke (this.Value, value) true interface SeqComposer.ISeqComponent with member this.OnComplete() = if first then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - total.Accumulator + total.Value [] let replicate count x = @@ -2226,22 +2226,22 @@ namespace Microsoft.FSharp.Collections let composedSource = toComposer source let total = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with + { new SeqComposer.Folder<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = - this.Accumulator <- Checked.(+) this.Accumulator value + this.Value <- Checked.(+) this.Value value true }) - total.Accumulator + total.Value [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = let composedSource = toComposer source let total = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = - this.Accumulator <- Checked.(+) this.Accumulator (f value) + this.Value <- Checked.(+) this.Value (f value) true }) - total.Accumulator + total.Value [] let inline average (source: seq< ^a>) : ^a = @@ -2249,18 +2249,18 @@ namespace Microsoft.FSharp.Collections source |> toComposer |> foreach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'a, SeqComposer.MutableData<'a, int>> (SeqComposer.MutableData(LanguagePrimitives.GenericZero, 0)) with + { new SeqComposer.Folder<'a, SeqComposer.Values<'a, int>> (SeqComposer.Values(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = - this.Accumulator._1 <- Checked.(+) this.Accumulator._1 value - this.Accumulator._2 <- this.Accumulator._2 + 1 + this.Value._1 <- Checked.(+) this.Value._1 value + this.Value._2 <- this.Value._2 + 1 true interface SeqComposer.ISeqComponent with member this.OnComplete() = - if (this:?>SeqComposer.AccumulatingConsumer<'a, SeqComposer.MutableData<'a, int>>).Accumulator._2 = 0 then + if (this:?>SeqComposer.Folder<'a, SeqComposer.Values<'a, int>>).Value._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - LanguagePrimitives.DivideByInt< ^a> total.Accumulator._1 total.Accumulator._2 + LanguagePrimitives.DivideByInt< ^a> total.Value._1 total.Value._2 [] let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = @@ -2268,9 +2268,9 @@ namespace Microsoft.FSharp.Collections let mutable count = 0 let total = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = - this.Accumulator <- Checked.(+) this.Accumulator (f value) + this.Value <- Checked.(+) this.Value (f value) count <- count + 1 true interface SeqComposer.ISeqComponent with @@ -2278,7 +2278,7 @@ namespace Microsoft.FSharp.Collections if count = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - LanguagePrimitives.DivideByInt< ^U> total.Accumulator count + LanguagePrimitives.DivideByInt< ^U> total.Value count [] let inline min (source: seq<_>) = @@ -2287,20 +2287,20 @@ namespace Microsoft.FSharp.Collections let mutable first = true let min = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = if first then first <- false - this.Accumulator <- value - elif value < this.Accumulator then - this.Accumulator <- value + this.Value <- value + elif value < this.Value then + this.Value <- value true interface SeqComposer.ISeqComponent with member __.OnComplete() = if first then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - min.Accumulator + min.Value [] let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = @@ -2310,25 +2310,25 @@ namespace Microsoft.FSharp.Collections let mutable acc = Unchecked.defaultof<'U> let min = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = let currValue = value let curr = f currValue if first then first <- false acc <- curr - this.Accumulator <- value + this.Value <- value else if curr < acc then acc <- curr - this.Accumulator <- value + this.Value <- value true interface SeqComposer.ISeqComponent with member __.OnComplete() = if first then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - min.Accumulator + min.Value (* [] let inline minValBy (f : 'T -> 'U) (source: seq<'T>) : 'U = @@ -2353,21 +2353,21 @@ namespace Microsoft.FSharp.Collections let mutable first = true let max = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = if first then first <- false - this.Accumulator <- value + this.Value <- value else - if value > this.Accumulator then - this.Accumulator <- value + if value > this.Value then + this.Value <- value true interface SeqComposer.ISeqComponent with member __.OnComplete() = if first then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - max.Accumulator + max.Value [] let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = @@ -2377,25 +2377,25 @@ namespace Microsoft.FSharp.Collections let mutable acc = Unchecked.defaultof<'U> let min = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = let currValue = value let curr = f currValue if first then first <- false acc <- curr - this.Accumulator <- value + this.Value <- value else if curr > acc then acc <- curr - this.Accumulator <- value + this.Value <- value true interface SeqComposer.ISeqComponent with member __.OnComplete() = if first then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - min.Accumulator + min.Value (* [] @@ -2476,16 +2476,16 @@ namespace Microsoft.FSharp.Collections let last = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T, 'T> (Unchecked.defaultof<'T>) with + { new SeqComposer.Folder<'T, 'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = if first then first <- false - this.Accumulator <- value + this.Value <- value true }) if first then None else - Some(last.Accumulator) + Some(last.Value) [] let last (source : seq<_>) = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 1baeec4685e..4e5b016e90d 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -28,19 +28,19 @@ namespace Microsoft.FSharp.Collections interface ISeqComponent [] - type MutableData<'a,'b> = + type Values<'a,'b> = struct - new : a:'a * b:'b -> MutableData<'a,'b> + new : a:'a * b:'b -> Values<'a,'b> val mutable _1: 'a val mutable _2: 'b end [] - type AccumulatingConsumer<'T,'U> = + type Folder<'T,'U> = class inherit SeqConsumer<'T,'T> - new : initialState:'U -> AccumulatingConsumer<'T,'U> - val mutable Accumulator: 'U + new : init:'U -> Folder<'T,'U> + val mutable Value: 'U end [] From b639963f430256d4c2e24ddcdd741e7c390a304f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 13:53:33 +1100 Subject: [PATCH 088/286] Fixed tryPick Processed 1 past the end of the data, as demo'd here: seq { for i = 1 to 5 do yield i failwith "boom" } |> Seq.pick (fun x -> if x = 5 then Some true else None) |> fun result -> assert result --- src/fsharp/FSharp.Core/seq.fs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index cac46b72596..291ed93bb15 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1696,20 +1696,18 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source : seq<'T>) = - let pick = - source - |> toComposer - |> foreach (fun pipeline -> - { new SeqComposer.Folder<'T, Option<'U>> (None) with - override this.ProcessNext value = - if this.Value.IsNone then - this.Value <- f value - true - else - pipeline.StopFurtherProcessing() - false - }) - pick.Value + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, Option<'U>> (None) with + override this.ProcessNext value = + match f value with + | None -> false + | (Some _) as some -> + this.Value <- some + pipeline.StopFurtherProcessing() + true }) + |> fun pick -> pick.Value [] let pick f source = From 687eb99e7fabc7c8e291b8929ce01a47036dabe7 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 14:02:20 +1100 Subject: [PATCH 089/286] Fixed tryFind, similar to tryPick Error seen with seq { for i = 1 to 5 do yield i failwith "boom" } |> Seq.find (fun x -> x = 5) |> fun result -> assert (result=5) --- src/fsharp/FSharp.Core/seq.fs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 291ed93bb15..7eeac38e53e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1717,21 +1717,18 @@ namespace Microsoft.FSharp.Collections [] let tryFind f (source : seq<'T>) = - let find = - source - |> toComposer - |> foreach (fun pipeline -> - { new SeqComposer.Folder<'T, Option<'T>> (None) with - override this.ProcessNext value = - if this.Value.IsNone then - if f value then - this.Value <- Some(value) - true - else - pipeline.StopFurtherProcessing() - false - }) - find.Value + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, Option<'T>> (None) with + override this.ProcessNext value = + if f value then + this.Value <- Some value + pipeline.StopFurtherProcessing() + true + else + false }) + |> fun find -> find.Value [] let find f source = From b7af8a035ed99d502bf47ec1963b524c11882a6e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:31:38 +1100 Subject: [PATCH 090/286] cleaned up math functions --- src/fsharp/FSharp.Core/seq.fs | 265 ++++++++++++++++----------------- src/fsharp/FSharp.Core/seq.fsi | 9 ++ 2 files changed, 141 insertions(+), 133 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 7eeac38e53e..f139ecde938 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -476,6 +476,18 @@ namespace Microsoft.FSharp.Collections _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 Folder<'T, 'U> = inherit SeqConsumer<'T,'T> @@ -2218,112 +2230,104 @@ namespace Microsoft.FSharp.Collections [] let inline sum (source:seq<'a>) : 'a = - let composedSource = toComposer source - let total = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'a,'a> (LanguagePrimitives.GenericZero) with - override this.ProcessNext value = - this.Value <- Checked.(+) this.Value value - true }) - total.Value + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'a,'a> (LanguagePrimitives.GenericZero) with + override this.ProcessNext value = + this.Value <- Checked.(+) this.Value value + true }) + |> fun sum -> sum.Value [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = - let composedSource = toComposer source - let total = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with - override this.ProcessNext value = - this.Value <- Checked.(+) this.Value (f value) - true }) - total.Value + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + override this.ProcessNext value = + this.Value <- Checked.(+) this.Value (f value) + true }) + |> fun sum -> sum.Value [] let inline average (source: seq< ^a>) : ^a = - let total = - source - |> toComposer - |> foreach (fun _ -> - { new SeqComposer.Folder<'a, SeqComposer.Values<'a, int>> (SeqComposer.Values(LanguagePrimitives.GenericZero, 0)) with - override this.ProcessNext value = - this.Value._1 <- Checked.(+) this.Value._1 value - this.Value._2 <- this.Value._2 + 1 - true + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'a, SeqComposer.Values<'a, int>> (SeqComposer.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + override this.ProcessNext value = + this.Value._1 <- Checked.(+) this.Value._1 value + this.Value._2 <- this.Value._2 + 1 + true - interface SeqComposer.ISeqComponent with - member this.OnComplete() = - if (this:?>SeqComposer.Folder<'a, SeqComposer.Values<'a, int>>).Value._2 = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - LanguagePrimitives.DivideByInt< ^a> total.Value._1 total.Value._2 + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if (this:?>SeqComposer.Folder<'a, SeqComposer.Values<'a, int>>).Value._2 = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) + |> fun total -> LanguagePrimitives.DivideByInt< ^a> total.Value._1 total.Value._2 [] let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = - let composedSource = toComposer source - let mutable count = 0 - let total = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with - override this.ProcessNext value = - this.Value <- Checked.(+) this.Value (f value) - count <- count + 1 - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if count = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - LanguagePrimitives.DivideByInt< ^U> total.Value count + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T,SeqComposer.Values<'U, int>> (SeqComposer.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + override this.ProcessNext value = + this.Value._1 <- Checked.(+) this.Value._1 (f value) + this.Value._2 <- this.Value._2 + 1 + true + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if (this:?>SeqComposer.Folder<'T,SeqComposer.Values<'U, int>>).Value._2 = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) + |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.Value._1 total.Value._2 [] let inline min (source: seq<_>) = - let composedSource = toComposer source - - let mutable first = true - let min = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - if first then - first <- false - this.Value <- value - elif value < this.Value then - this.Value <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - min.Value + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + elif value < this.Value._2 then + this.Value._2 <- value + true + + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun min -> min.Value._2 [] let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = - let composedSource = toComposer source + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + match this.Value._1, f value with + | true, valueU -> + this.Value._1 <- false + this.Value._2 <- valueU + this.Value._3 <- value + | false, valueU when valueU < this.Value._2 -> + this.Value._2 <- valueU + this.Value._3 <- value + | _ -> () + true - let mutable first = true - let mutable acc = Unchecked.defaultof<'U> - let min = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - let currValue = value - let curr = f currValue - if first then - first <- false - acc <- curr - this.Value <- value - else - if curr < acc then - acc <- curr - this.Value <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - min.Value + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun min -> min.Value._3 (* [] let inline minValBy (f : 'T -> 'U) (source: seq<'T>) : 'U = @@ -2343,54 +2347,49 @@ namespace Microsoft.FSharp.Collections *) [] let inline max (source: seq<_>) = - let composedSource = toComposer source - - let mutable first = true - let max = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - if first then - first <- false - this.Value <- value - else - if value > this.Value then - this.Value <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - max.Value + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + elif value > this.Value._2 then + this.Value._2 <- value + true + + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun max -> max.Value._2 [] let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = - let composedSource = toComposer source + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + match this.Value._1, f value with + | true, valueU -> + this.Value._1 <- false + this.Value._2 <- valueU + this.Value._3 <- value + | false, valueU when valueU > this.Value._2 -> + this.Value._2 <- valueU + this.Value._3 <- value + | _ -> () + true - let mutable first = true - let mutable acc = Unchecked.defaultof<'U> - let min = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - let currValue = value - let curr = f currValue - if first then - first <- false - acc <- curr - this.Value <- value - else - if curr > acc then - acc <- curr - this.Value <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - min.Value + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun min -> min.Value._3 (* [] diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 4e5b016e90d..7e94539f3ea 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -35,6 +35,15 @@ namespace Microsoft.FSharp.Collections val mutable _2: 'b end + [] + type Values<'a,'b,'c> = + struct + new : a:'a * b:'b * c:'c -> Values<'a,'b,'c> + val mutable _1: 'a + val mutable _2: 'b + val mutable _3: 'c + end + [] type Folder<'T,'U> = class From 0ce01ea9514253355ca60d7719d2d11dbbdd80b7 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:49:17 +1100 Subject: [PATCH 091/286] Just fixing some more one past the end --- src/fsharp/FSharp.Core/seq.fs | 81 +++++++++++++++++------------------ 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index f139ecde938..67d9b5ebe65 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1566,54 +1566,51 @@ namespace Microsoft.FSharp.Collections [] let exists f (source : seq<'T>) = - let exists = - source - |> toComposer - |> foreach (fun pipeline -> - { new SeqComposer.Folder<'T, bool> (false) with - override this.ProcessNext value = - if this.Value then - pipeline.StopFurtherProcessing() - false - else - this.Value <- f value - true - }) - exists.Value + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, bool> (false) with + override this.ProcessNext value = + if f value then + this.Value <- true + pipeline.StopFurtherProcessing () + false + else + true + }) + |> fun exists -> exists.Value [] let inline contains element (source : seq<'T>) = - let contains = - source - |> toComposer - |> foreach (fun pipeline -> - { new SeqComposer.Folder<'T, bool> (false) with - override this.ProcessNext value = - if this.Value then - pipeline.StopFurtherProcessing() - false - else - this.Value <- element = value - true - }) - contains.Value + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, bool> (false) with + override this.ProcessNext value = + if element = value then + this.Value <- true + pipeline.StopFurtherProcessing() + false + else + true + }) + |> fun contains -> contains.Value [] let forall f (source : seq<'T>) = - let forall = - source - |> toComposer - |> foreach (fun pipeline -> - { new SeqComposer.Folder<'T, bool> (true) with - override this.ProcessNext value = - if this.Value then - this.Value <- f value - false - else - pipeline.StopFurtherProcessing() - true - }) - forall.Value + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, bool> (true) with + override this.ProcessNext value = + if f value then + false + else + this.Value <- false + pipeline.StopFurtherProcessing() + true + }) + |> fun forall -> forall.Value [] let iter2 f (source1 : seq<_>) (source2 : seq<_>) = From 154149b10a052ebfa39b62c79f6b246ed8189822 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:53:22 +1100 Subject: [PATCH 092/286] more consistency --- src/fsharp/FSharp.Core/seq.fs | 49 ++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 67d9b5ebe65..7ebaa410260 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1785,15 +1785,16 @@ namespace Microsoft.FSharp.Collections [] let fold<'T,'State> f (x:'State) (source:seq<'T>) = - let composedSource = toComposer source let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let total = composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'State> (x) with - override this.ProcessNext value = - this.Value <- f.Invoke (this.Value, value) - true }) - total.Value + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T,'State> (x) with + override this.ProcessNext value = + this.Value <- f.Invoke (this.Value, value) + true }) + |> fun folded -> folded.Value [] let fold2<'T1,'T2,'State> f (state:'State) (source1: seq<'T1>) (source2: seq<'T2>) = @@ -1813,25 +1814,25 @@ namespace Microsoft.FSharp.Collections [] let reduce f (source : seq<'T>) = - let composedSource = toComposer source let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let mutable first = true - let total = composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - if first then - first <- false - this.Value <- value - else - this.Value <- f.Invoke (this.Value, value) - true - interface SeqComposer.ISeqComponent with - member this.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - total.Value + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + else + this.Value._2 <- f.Invoke (this.Value._2, value) + true + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if (this:?>SeqComposer.Folder<'T, SeqComposer.Values>).Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun reduced -> reduced.Value._2 [] let replicate count x = From 980d43f5519d7aaa16d541c243a510a309e1c678 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:57:34 +1100 Subject: [PATCH 093/286] more consistency --- src/fsharp/FSharp.Core/seq.fs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 7ebaa410260..ae6f6cbf241 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1827,6 +1827,7 @@ namespace Microsoft.FSharp.Collections else this.Value._2 <- f.Invoke (this.Value._2, value) true + interface SeqComposer.ISeqComponent with member this.OnComplete() = if (this:?>SeqComposer.Folder<'T, SeqComposer.Values>).Value._1 then @@ -2463,21 +2464,20 @@ namespace Microsoft.FSharp.Collections [] let tryLast (source : seq<_>) = - let composedSource = toComposer source - let mutable first = true - - let last = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T, 'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - if first then - first <- false - this.Value <- value - true }) - if first then - None - else - Some(last.Value) + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + true }) + |> fun tried -> + if tried.Value._1 then + None + else + Some tried.Value._2 [] let last (source : seq<_>) = From 0fd04467a2b9a7836d990641b14f2e075b3bd511 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 16:44:03 +1100 Subject: [PATCH 094/286] foreach now takes seq and calls toComposer --- src/fsharp/FSharp.Core/seq.fs | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ae6f6cbf241..960366555fb 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1500,7 +1500,10 @@ namespace Microsoft.FSharp.Collections | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, SeqComposer.IdentityFactory.IdentityFactory) | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory.IdentityFactory) - let inline foreach f (source:SeqComposer.SeqEnumerable<_>) = source.ForEach f + let inline foreach f (source:seq<_>) = + source + |> toComposer + |> fun composer -> composer.ForEach f [] let delay f = mkDelayedSeq f @@ -1525,7 +1528,6 @@ namespace Microsoft.FSharp.Collections [] let iter f (source : seq<'T>) = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.SeqConsumer<'T,'T> () with override this.ProcessNext value = @@ -1567,7 +1569,6 @@ namespace Microsoft.FSharp.Collections [] let exists f (source : seq<'T>) = source - |> toComposer |> foreach (fun pipeline -> { new SeqComposer.Folder<'T, bool> (false) with override this.ProcessNext value = @@ -1583,7 +1584,6 @@ namespace Microsoft.FSharp.Collections [] let inline contains element (source : seq<'T>) = source - |> toComposer |> foreach (fun pipeline -> { new SeqComposer.Folder<'T, bool> (false) with override this.ProcessNext value = @@ -1599,7 +1599,6 @@ namespace Microsoft.FSharp.Collections [] let forall f (source : seq<'T>) = source - |> toComposer |> foreach (fun pipeline -> { new SeqComposer.Folder<'T, bool> (true) with override this.ProcessNext value = @@ -1706,7 +1705,6 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source : seq<'T>) = source - |> toComposer |> foreach (fun pipeline -> { new SeqComposer.Folder<'T, Option<'U>> (None) with override this.ProcessNext value = @@ -1727,7 +1725,6 @@ namespace Microsoft.FSharp.Collections [] let tryFind f (source : seq<'T>) = source - |> toComposer |> foreach (fun pipeline -> { new SeqComposer.Folder<'T, Option<'T>> (None) with override this.ProcessNext value = @@ -1788,7 +1785,6 @@ namespace Microsoft.FSharp.Collections let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T,'State> (x) with override this.ProcessNext value = @@ -1817,7 +1813,6 @@ namespace Microsoft.FSharp.Collections let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = @@ -2230,7 +2225,6 @@ namespace Microsoft.FSharp.Collections [] let inline sum (source:seq<'a>) : 'a = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = @@ -2241,7 +2235,6 @@ namespace Microsoft.FSharp.Collections [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = @@ -2252,7 +2245,6 @@ namespace Microsoft.FSharp.Collections [] let inline average (source: seq< ^a>) : ^a = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'a, SeqComposer.Values<'a, int>> (SeqComposer.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = @@ -2269,7 +2261,6 @@ namespace Microsoft.FSharp.Collections [] let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T,SeqComposer.Values<'U, int>> (SeqComposer.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = @@ -2285,7 +2276,6 @@ namespace Microsoft.FSharp.Collections [] let inline min (source: seq<_>) = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = @@ -2306,7 +2296,6 @@ namespace Microsoft.FSharp.Collections [] let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with override this.ProcessNext value = @@ -2347,7 +2336,6 @@ namespace Microsoft.FSharp.Collections [] let inline max (source: seq<_>) = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = @@ -2368,7 +2356,6 @@ namespace Microsoft.FSharp.Collections [] let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with override this.ProcessNext value = @@ -2465,7 +2452,6 @@ namespace Microsoft.FSharp.Collections [] let tryLast (source : seq<_>) = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = From 2bac2c8dff59d874261e4f90c02d99bf9cc6815e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 19:37:46 +1100 Subject: [PATCH 095/286] Made ignoring return value a bit more explicit --- src/fsharp/FSharp.Core/seq.fs | 67 ++++++++++++++++------------------- 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 960366555fb..7a6004d0fa5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -516,6 +516,9 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) + // within a foreach, the value returned by ProcessNext is ignored + let processNextInForeach = true + let seqComponentTail = { new ISeqComponent with member __.OnComplete() = () @@ -1531,7 +1534,8 @@ namespace Microsoft.FSharp.Collections |> foreach (fun _ -> { new SeqComposer.SeqConsumer<'T,'T> () with override this.ProcessNext value = - f value; true }) + f value + SeqComposer.Helpers.processNextInForeach }) |> ignore [] @@ -1553,17 +1557,14 @@ namespace Microsoft.FSharp.Collections [] let iteri f (source : seq<'T>) = - let composedSource = toComposer source - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let mutable i = 0 - - composedSource.ForEach (fun _ -> - { new SeqComposer.SeqConsumer<'T,'T> () with - override this.ProcessNext value = - f.Invoke(i, value) - i <- i + 1 - true }) + source + |> foreach (fun _ -> + { new SeqComposer.Folder<'T, int> (0) with + override this.ProcessNext value = + f.Invoke(this.Value, value) + this.Value <- this.Value + 1 + SeqComposer.Helpers.processNextInForeach }) |> ignore [] @@ -1575,9 +1576,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Value <- true pipeline.StopFurtherProcessing () - false - else - true + SeqComposer.Helpers.processNextInForeach }) |> fun exists -> exists.Value @@ -1590,9 +1589,7 @@ namespace Microsoft.FSharp.Collections if element = value then this.Value <- true pipeline.StopFurtherProcessing() - false - else - true + SeqComposer.Helpers.processNextInForeach }) |> fun contains -> contains.Value @@ -1602,12 +1599,10 @@ namespace Microsoft.FSharp.Collections |> foreach (fun pipeline -> { new SeqComposer.Folder<'T, bool> (true) with override this.ProcessNext value = - if f value then - false - else + if not (f value) then this.Value <- false pipeline.StopFurtherProcessing() - true + SeqComposer.Helpers.processNextInForeach }) |> fun forall -> forall.Value @@ -1709,11 +1704,11 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.Folder<'T, Option<'U>> (None) with override this.ProcessNext value = match f value with - | None -> false | (Some _) as some -> this.Value <- some pipeline.StopFurtherProcessing() - true }) + | None -> () + SeqComposer.Helpers.processNextInForeach }) |> fun pick -> pick.Value [] @@ -1731,9 +1726,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Value <- Some value pipeline.StopFurtherProcessing() - true - else - false }) + SeqComposer.Helpers.processNextInForeach }) |> fun find -> find.Value [] @@ -1789,7 +1782,7 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.Folder<'T,'State> (x) with override this.ProcessNext value = this.Value <- f.Invoke (this.Value, value) - true }) + SeqComposer.Helpers.processNextInForeach }) |> fun folded -> folded.Value [] @@ -1821,7 +1814,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value else this.Value._2 <- f.Invoke (this.Value._2, value) - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2229,7 +2222,7 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.Folder<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value value - true }) + SeqComposer.Helpers.processNextInForeach }) |> fun sum -> sum.Value [] @@ -2239,7 +2232,7 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value (f value) - true }) + SeqComposer.Helpers.processNextInForeach }) |> fun sum -> sum.Value [] @@ -2250,7 +2243,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 value this.Value._2 <- this.Value._2 + 1 - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2266,7 +2259,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 (f value) this.Value._2 <- this.Value._2 + 1 - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = if (this:?>SeqComposer.Folder<'T,SeqComposer.Values<'U, int>>).Value._2 = 0 then @@ -2284,7 +2277,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value elif value < this.Value._2 then this.Value._2 <- value - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2308,7 +2301,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- valueU this.Value._3 <- value | _ -> () - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2344,7 +2337,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value elif value > this.Value._2 then this.Value._2 <- value - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2368,7 +2361,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- valueU this.Value._3 <- value | _ -> () - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2458,7 +2451,7 @@ namespace Microsoft.FSharp.Collections if this.Value._1 then this.Value._1 <- false this.Value._2 <- value - true }) + SeqComposer.Helpers.processNextInForeach }) |> fun tried -> if tried.Value._1 then None From 7c858ec35b860fdb675f047c0a5c8440bf492125 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 22 Oct 2016 12:38:03 +1100 Subject: [PATCH 096/286] processNextInForeach was a bit verbose --- src/fsharp/FSharp.Core/seq.fs | 39 ++++++++++++++++------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 7a6004d0fa5..64b679fdf30 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -516,9 +516,6 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) - // within a foreach, the value returned by ProcessNext is ignored - let processNextInForeach = true - let seqComponentTail = { new ISeqComponent with member __.OnComplete() = () @@ -1535,7 +1532,7 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.SeqConsumer<'T,'T> () with override this.ProcessNext value = f value - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> ignore [] @@ -1564,7 +1561,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = f.Invoke(this.Value, value) this.Value <- this.Value + 1 - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> ignore [] @@ -1576,7 +1573,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Value <- true pipeline.StopFurtherProcessing () - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof }) |> fun exists -> exists.Value @@ -1589,7 +1586,7 @@ namespace Microsoft.FSharp.Collections if element = value then this.Value <- true pipeline.StopFurtherProcessing() - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof }) |> fun contains -> contains.Value @@ -1602,7 +1599,7 @@ namespace Microsoft.FSharp.Collections if not (f value) then this.Value <- false pipeline.StopFurtherProcessing() - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof }) |> fun forall -> forall.Value @@ -1708,7 +1705,7 @@ namespace Microsoft.FSharp.Collections this.Value <- some pipeline.StopFurtherProcessing() | None -> () - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> fun pick -> pick.Value [] @@ -1726,7 +1723,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Value <- Some value pipeline.StopFurtherProcessing() - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> fun find -> find.Value [] @@ -1782,7 +1779,7 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.Folder<'T,'State> (x) with override this.ProcessNext value = this.Value <- f.Invoke (this.Value, value) - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> fun folded -> folded.Value [] @@ -1814,7 +1811,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value else this.Value._2 <- f.Invoke (this.Value._2, value) - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2222,7 +2219,7 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.Folder<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value value - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> fun sum -> sum.Value [] @@ -2232,7 +2229,7 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value (f value) - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> fun sum -> sum.Value [] @@ -2243,7 +2240,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 value this.Value._2 <- this.Value._2 + 1 - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2259,7 +2256,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 (f value) this.Value._2 <- this.Value._2 + 1 - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete() = if (this:?>SeqComposer.Folder<'T,SeqComposer.Values<'U, int>>).Value._2 = 0 then @@ -2277,7 +2274,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value elif value < this.Value._2 then this.Value._2 <- value - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2301,7 +2298,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- valueU this.Value._3 <- value | _ -> () - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2337,7 +2334,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value elif value > this.Value._2 then this.Value._2 <- value - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2361,7 +2358,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- valueU this.Value._3 <- value | _ -> () - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2451,7 +2448,7 @@ namespace Microsoft.FSharp.Collections if this.Value._1 then this.Value._1 <- false this.Value._2 <- value - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> fun tried -> if tried.Value._1 then None From c741e1f969bac524fc1db6d1593e6496805462a1 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 22 Oct 2016 13:42:57 +1100 Subject: [PATCH 097/286] Consolidated ForEach functionality --- src/fsharp/FSharp.Core/seq.fs | 194 ++++++++++++---------------------- 1 file changed, 70 insertions(+), 124 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 64b679fdf30..24af963ca04 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -952,6 +952,68 @@ namespace Microsoft.FSharp.Collections interface ISeqPipeline with member x.StopFurtherProcessing() = halted <- true member __.Halted = halted + module ForEach = + let enumerable (enumerable:IEnumerable<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + use enumerator = enumerable.GetEnumerator () + while (not pipeline.Halted) && (enumerator.MoveNext ()) do + consumer.ProcessNext enumerator.Current |> ignore + + let array (array:array<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let mutable idx = 0 + while (not pipeline.Halted) && (idx < array.Length) do + consumer.ProcessNext array.[idx] |> ignore + idx <- idx + 1 + + let list (alist:list<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let rec iterate lst = + match pipeline.Halted, lst with + | true, _ + | false, [] -> () + | false, hd :: tl -> + consumer.ProcessNext hd |> ignore + iterate tl + iterate alist + + let unfold (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let rec iterate current = + match pipeline.Halted, generator current with + | true, _ + | false, None -> () + | false, Some (item, next) -> + consumer.ProcessNext item |> ignore + iterate next + + iterate state + + let makeIsSkipping (consumer:SeqConsumer<'T,'U>) = + match consumer with + | :? SeqComponent<'T,'U> as c -> c.Skipping + | _ -> fun () -> false + + let init f (terminatingIdx:int) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let mutable idx = -1 + let isSkipping = makeIsSkipping consumer + let mutable maybeSkipping = true + while (not pipeline.Halted) && (idx < terminatingIdx) do + if maybeSkipping then + maybeSkipping <- isSkipping () + + if (not maybeSkipping) then + consumer.ProcessNext (f (idx+1)) |> ignore + + idx <- idx + 1 + + let execute (f:ISeqPipeline->#SeqConsumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = + let pipeline = Pipeline() + let result = f pipeline + let consumer = current.Create pipeline result + try + executeOn pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () + module Enumerable = [] type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) = @@ -1020,10 +1082,6 @@ namespace Microsoft.FSharp.Collections and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = inherit EnumerableBase<'U>() - static let iterate (enumerator:IEnumerator<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = - while (not pipeline.Halted) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1033,16 +1091,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let pipeline = Pipeline() - let result = f pipeline - let consumer = current.Create pipeline result - use enumerator = enumerable.GetEnumerator () - try - iterate enumerator pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () - result - finally - (Helpers.upcastISeqComponent consumer).OnDispose () + ForEach.execute f current (ForEach.enumerable enumerable) and AppendEnumerator<'T> (sources:list>) = let sources = sources |> List.rev @@ -1084,10 +1133,6 @@ namespace Microsoft.FSharp.Collections and AppendEnumerable<'T> (sources:list>) = inherit EnumerableBase<'T>() - static let iterate (enumerator:IEnumerator<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = - while (not pipeline.Halted) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = Helpers.upcastEnumerator (new AppendEnumerator<_> (sources)) @@ -1099,17 +1144,8 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = - let pipeline = Pipeline() - let result = f pipeline - let consumer : SeqConsumer<'T,'T> = upcast result let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) - use enumerator = enumerable.GetEnumerator () - try - iterate enumerator pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () - result - finally - (Helpers.upcastISeqComponent consumer).OnDispose () + ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable enumerable) let create enumerable current = Helpers.upcastEnumerable (Enumerable(enumerable, current)) @@ -1149,12 +1185,6 @@ namespace Microsoft.FSharp.Collections type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() - static let iterate (array:array<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = - let mutable idx = 0 - while (not pipeline.Halted) && (idx < array.Length) do - consumer.ProcessNext array.[idx] |> ignore - idx <- idx + 1 - interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1164,15 +1194,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let pipeline = Pipeline () - let result = f pipeline - let consumer = current.Create pipeline result - try - iterate (delayedArray ()) pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () - result - finally - (Helpers.upcastISeqComponent consumer).OnDispose () + ForEach.execute f current (ForEach.array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = Helpers.upcastEnumerable (Enumerable(delayedArray, current)) @@ -1210,16 +1232,6 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext list - let iterate (alist:list<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = - let rec iterate lst = - match pipeline.Halted, lst with - | true, _ - | false, [] -> () - | false, hd :: tl -> - consumer.ProcessNext hd |> ignore - iterate tl - iterate alist - type Enumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() @@ -1232,15 +1244,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let pipeline = Pipeline () - let result = f pipeline - let consumer = current.Create pipeline result - try - iterate alist pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () - result - finally - (Helpers.upcastISeqComponent consumer).OnDispose () + ForEach.execute f current (ForEach.list alist) let create alist current = Helpers.upcastEnumerable (Enumerable(alist, current)) @@ -1270,17 +1274,6 @@ namespace Microsoft.FSharp.Collections type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() - static let iterate (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = - let rec iterate current = - match pipeline.Halted, generator current with - | true, _ - | false, None -> () - | false, Some (item, next) -> - consumer.ProcessNext item |> ignore - iterate next - - iterate state - interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1290,15 +1283,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let pipeline = Pipeline () - let result = f pipeline - let consumer = current.Create pipeline result - try - iterate generator state pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () - result - finally - (Helpers.upcastISeqComponent consumer).OnDispose () + ForEach.execute f current (ForEach.unfold generator state) module Init = // The original implementation of "init" delayed the calculation of Current, and so it was possible @@ -1322,16 +1307,11 @@ namespace Microsoft.FSharp.Collections else System.Int32.MaxValue - let makeIsSkipping (consumer:SeqConsumer<'T,'U>) = - match consumer with - | :? SeqComponent<'T,'U> as c -> c.Skipping - | _ -> fun () -> false - type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqConsumer<'T,'U>, signal:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) let isSkipping = - makeIsSkipping seqComponent + ForEach.makeIsSkipping seqComponent let terminatingIdx = getTerminatingIdx count @@ -1369,18 +1349,6 @@ namespace Microsoft.FSharp.Collections type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() - static let iterate f (terminatingIdx:int) (isSkipping) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = - let mutable idx = -1 - let mutable maybeSkipping = true - while (not pipeline.Halted) && (idx < terminatingIdx) do - if maybeSkipping then - maybeSkipping <- isSkipping () - - if (not maybeSkipping) then - consumer.ProcessNext (f (idx+1)) |> ignore - - idx <- idx + 1 - interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1390,17 +1358,8 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) override this.ForEach (createResult:ISeqPipeline->#SeqConsumer<'U,'U>) = - let pipeline = Pipeline () - let result = createResult pipeline - let consumer = current.Create pipeline result let terminatingIdx = getTerminatingIdx count - let isSkipping = makeIsSkipping consumer - try - iterate f terminatingIdx isSkipping pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () - result - finally - (Helpers.upcastISeqComponent consumer).OnDispose () + ForEach.execute createResult current (ForEach.init f terminatingIdx) let upto lastOption f = match lastOption with @@ -1455,10 +1414,6 @@ namespace Microsoft.FSharp.Collections type EnumerableDecider<'T>(count:Nullable, f:int->'T) = inherit Enumerable.EnumerableBase<'T>() - static let iterate (enumerator:IEnumerator<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'T>) = - while (not pipeline.Halted) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - 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 @@ -1470,16 +1425,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = - let pipeline = Pipeline () - let result = f pipeline - let consumer : SeqConsumer<'T,'T> = upcast result - use enumerator = (Helpers.upcastEnumerable this).GetEnumerator () - try - iterate enumerator pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () - result - finally - (Helpers.upcastISeqComponent consumer).OnDispose () + ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable (Helpers.upcastEnumerable this)) #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions From d7b173f59f1acb4d3f1f12722f5eae2f52a55603 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 22 Oct 2016 18:06:21 +1100 Subject: [PATCH 098/286] Seq.concat --- src/fsharp/FSharp.Core/seq.fs | 70 ++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 24af963ca04..098a80f5a45 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -165,7 +165,7 @@ namespace Microsoft.FSharp.Core.CompilerServices member x.GetEnumerator() = f() interface IEnumerable with member x.GetEnumerator() = (f() :> IEnumerator) } - + [] type EmptyEnumerable<'T> = | EmptyEnumerable @@ -1015,6 +1015,21 @@ namespace Microsoft.FSharp.Collections (Helpers.upcastISeqComponent consumer).OnDispose () 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>, seqComponent:ISeqComponent) = interface IDisposable with @@ -1093,24 +1108,25 @@ namespace Microsoft.FSharp.Collections override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ForEach.execute f current (ForEach.enumerable enumerable) - and AppendEnumerator<'T> (sources:list>) = - let sources = sources |> List.rev - + and ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = let mutable state = SeqProcessNextStates.NotStarted - let mutable remaining = sources.Tail - let mutable active = sources.Head.GetEnumerator () + let main = sources.GetEnumerator () + + let mutable active = + if main.MoveNext () + then main.Current.GetEnumerator () + else EmptyEnumerators.Element let rec moveNext () = - if active.MoveNext () then true + if active.MoveNext () then + true + elif main.MoveNext () then + active.Dispose () + active <- main.Current.GetEnumerator () + moveNext () else - match remaining with - | [] -> false - | hd :: tl -> - active.Dispose () - active <- hd.GetEnumerator () - remaining <- tl - - moveNext () + state <- SeqProcessNextStates.Finished + false interface IEnumerator<'T> with member __.Current = @@ -1128,6 +1144,7 @@ namespace Microsoft.FSharp.Collections interface IDisposable with member __.Dispose() = + main.Dispose () active.Dispose () and AppendEnumerable<'T> (sources:list>) = @@ -1135,7 +1152,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - Helpers.upcastEnumerator (new AppendEnumerator<_> (sources)) + Helpers.upcastEnumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(this, next)) @@ -1144,8 +1161,20 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = - let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) - ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable enumerable) + ForEach.execute f IdentityFactory.IdentityFactory (ForEach.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> = + Helpers.upcastEnumerator (new ConcatEnumerator<_,_> (sources)) + + override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = + Helpers.upcastEnumerable (Enumerable<'T,'V>(this, next)) + + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = + ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) let create enumerable current = Helpers.upcastEnumerable (Enumerable(enumerable, current)) @@ -1696,11 +1725,10 @@ namespace Microsoft.FSharp.Collections use ie = source.GetEnumerator() not (ie.MoveNext()) - [] - let concat sources = + let concat (sources:seq<#seq<'T>>) : seq<'T> = checkNonNull "sources" sources - mkConcatSeq sources + upcast SeqComposer.Enumerable.ConcatEnumerable sources [] let length (source : seq<'T>) = From 2d242a52f01ba1be453e794a68bb17ae033cbb54 Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 22 Oct 2016 07:29:55 -0400 Subject: [PATCH 099/286] findIndex/tryFindIndex --- src/fsharp/FSharp.Core/seq.fs | 41 +++++++++++++++-------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 098a80f5a45..94ddd4402b5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1931,31 +1931,26 @@ namespace Microsoft.FSharp.Collections let res = Array.scanSubRight f arr 0 (arr.Length - 1) acc res :> seq<_>) - [] - let findIndex p (source:seq<_>) = - 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 tryFindIndex p (source:seq<_>) = - checkNonNull "source" source - use ie = source.GetEnumerator() - let rec loop i = - if ie.MoveNext() then - if p ie.Current then - Some i - else loop (i+1) - else - None - loop 0 + source + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, SeqComposer.Values, int>> (SeqComposer.Values<_,_>(None, 0)) with + override this.ProcessNext value = + if p value then + this.Value._1 <- Some(this.Value._2) + pipeline.StopFurtherProcessing() + else + this.Value._2 <- this.Value._2 + 1 + Unchecked.defaultof + }) + |> fun tried -> tried.Value._1 + + [] + let findIndex p (source:seq<_>) = + match tryFindIndex p source with + | None -> indexNotFound() + | Some x -> x [] let tryFindIndexBack f (source : seq<'T>) = From 891334b1ad6041b11ccbae68c021eb69745d5cdb Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 22 Oct 2016 10:38:32 -0400 Subject: [PATCH 100/286] fix bug with Concat when there are side effects --- src/fsharp/FSharp.Core/seq.fs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 94ddd4402b5..f664605abb2 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1112,10 +1112,7 @@ namespace Microsoft.FSharp.Collections let mutable state = SeqProcessNextStates.NotStarted let main = sources.GetEnumerator () - let mutable active = - if main.MoveNext () - then main.Current.GetEnumerator () - else EmptyEnumerators.Element + let mutable active = EmptyEnumerators.Element let rec moveNext () = if active.MoveNext () then From 7619d48bfc0c94d55cb84360f79462009c5d4841 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 23 Oct 2016 19:30:44 +1100 Subject: [PATCH 101/286] Fix a Take bug The following caused an exception, when it shouldn't: [1;2;3] |> Seq.take 100 |> Seq.takeWhile (fun _ -> false) |> Seq.iter (fun _ -> ()) I'm not 100% happy with how I'm allocating ids, nor really with the added ceremony of the solution, but I think the idea of how to resolve is basically the right one. --- src/fsharp/FSharp.Core/seq.fs | 275 ++++++++++++++++----------------- src/fsharp/FSharp.Core/seq.fsi | 4 +- 2 files changed, 139 insertions(+), 140 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index f664605abb2..7503c1f47a5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -452,18 +452,18 @@ namespace Microsoft.FSharp.Collections open IEnumerator type ISeqComponent = - abstract OnComplete : unit -> unit + abstract OnComplete : int -> unit abstract OnDispose : unit -> unit type ISeqPipeline = - abstract StopFurtherProcessing : unit -> unit + abstract StopFurtherProcessing : int -> unit [] type SeqConsumer<'T,'U> () = abstract ProcessNext : input:'T -> bool interface ISeqComponent with - member __.OnComplete() = () + member __.OnComplete _ = () member __.OnDispose() = () [] @@ -518,133 +518,135 @@ namespace Microsoft.FSharp.Collections let seqComponentTail = { new ISeqComponent with - member __.OnComplete() = () + member __.OnComplete _ = () member __.OnDispose() = () } type [] SeqComponentFactory<'T,'U> () = - abstract Create<'V> : ISeqPipeline -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> + abstract Create<'V> : ISeqPipeline -> SeqConsumer<'U,'V> -> haltingIdx:int -> SeqConsumer<'T,'V> and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = inherit SeqComponentFactory<'T,'V> () - override __.Create<'W> (result:ISeqPipeline) (next:SeqConsumer<'V,'W>) : SeqConsumer<'T,'W> = - first.Create result (second.Create result next) + override __.Create<'W> (result:ISeqPipeline) (next:SeqConsumer<'V,'W>) (haltingIdx:int) : SeqConsumer<'T,'W> = + first.Create result (second.Create result next (haltingIdx+1)) (haltingIdx+2) static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = upcast ComposedFactory(first, second) and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Choose (filter, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Choose (filter, next, haltingIdx) and DistinctFactory<'T when 'T: equality> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Distinct (next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Distinct (next, haltingIdx) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next, haltingIdx) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next, haltingIdx) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = match next with - | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter - | _ -> upcast Filter (filter, next) + | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter haltingIdx + | _ -> upcast Filter (filter, next, haltingIdx) and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () static let singleton = IdentityFactory<'T>() - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = next + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (_haltingIdx:int) : SeqConsumer<'T,'V> = next static member IdentityFactory = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = match next with - | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map - | _ -> upcast Map<_,_,_> (map, next) + | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map haltingIdx + | _ -> upcast Map<_,_,_> (map, next, haltingIdx) and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next, haltingIdx) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = inherit SeqComponentFactory<'Second,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next, haltingIdx) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, haltingIdx) and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next, haltingIdx) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next, haltingIdx) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T*'T,'V>) : SeqConsumer<'T,'V> = upcast Pairwise next + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T*'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Pairwise (next, haltingIdx) and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Skip (count, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Skip (count, next, haltingIdx) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next, haltingIdx) and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next, haltingIdx) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Take (count, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Take (count, result, next, haltingIdx) and TailFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next, haltingIdx) and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next, haltingIdx) - and [] SeqComponent<'T,'U> (next:ISeqComponent) = + and [] SeqComponent<'T,'U> (next:ISeqComponent, haltingIdx:int) = inherit SeqConsumer<'T,'U>() // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip // and it can only do it at the start of a sequence abstract Skipping : unit -> bool - abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> - abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> + abstract CreateMap<'S> : map:('S->'T) -> haltingIdx:int -> SeqComponent<'S,'U> + abstract CreateFilter : filter:('T->bool) -> haltingIdx:int -> SeqComponent<'T,'U> interface ISeqComponent with - member __.OnComplete () = next.OnComplete () + member __.OnComplete halted = next.OnComplete halted member __.OnDispose () = next.OnDispose () + member __.HaltingIdx = haltingIdx + default __.Skipping () = false - default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) - default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) + default this.CreateMap<'S> (map:'S->'T) (haltingIdx:int) = upcast Map<_,_,_> (map, this, haltingIdx) + default this.CreateFilter (filter:'T->bool) (haltingIdx:int) = upcast Filter (filter, this, haltingIdx) - and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) + and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) override __.ProcessNext (input:'T) : bool = match choose input with | Some value -> Helpers.avoidTailCall (next.ProcessNext value) | None -> false - and Distinct<'T,'V when 'T: equality> (next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and Distinct<'T,'V when 'T: equality> (next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) @@ -654,8 +656,8 @@ namespace Microsoft.FSharp.Collections else false - and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) @@ -665,8 +667,8 @@ namespace Microsoft.FSharp.Collections else false - and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) @@ -676,10 +678,10 @@ namespace Microsoft.FSharp.Collections else false - and Filter<'T,'V> (filter:'T->bool, next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and Filter<'T,'V> (filter:'T->bool, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) - override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) + override this.CreateMap<'S> (map:'S->'T) (haltingIdx:int) = upcast MapThenFilter<_,_,_> (map, filter, next, haltingIdx) override __.ProcessNext (input:'T) : bool = if filter input then @@ -687,8 +689,8 @@ namespace Microsoft.FSharp.Collections else false - and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) + and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) override __.ProcessNext (input:'T) : bool = if filter input then @@ -696,16 +698,16 @@ namespace Microsoft.FSharp.Collections else false - and Map<'T,'U,'V> (map:'T->'U, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) + and Map<'T,'U,'V> (map:'T->'U, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) - override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) + override this.CreateFilter (filter:'T->bool) (haltingIdx:int) = upcast FilterThenMap (filter, map, next, haltingIdx) override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'First,'V>(next) + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'First,'V>(next, haltingIdx) let input2 = enumerable2.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -714,7 +716,7 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) else - result.StopFurtherProcessing () + result.StopFurtherProcessing haltingIdx false interface ISeqComponent with @@ -724,8 +726,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'Second,'V>(next) + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'Second,'V>(next, haltingIdx) let input1 = enumerable1.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -734,7 +736,7 @@ namespace Microsoft.FSharp.Collections if input1.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) else - result.StopFurtherProcessing () + result.StopFurtherProcessing haltingIdx false interface ISeqComponent with @@ -744,8 +746,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'First,'V>(next) + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'First,'V>(next, haltingIdx) let input2 = enumerable2.GetEnumerator () let input3 = enumerable3.GetEnumerator () @@ -755,7 +757,7 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () && input3.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) else - result.StopFurtherProcessing () + result.StopFurtherProcessing haltingIdx false interface ISeqComponent with @@ -768,8 +770,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) override __.ProcessNext (input:'T) : bool = let u = map input @@ -778,8 +780,8 @@ namespace Microsoft.FSharp.Collections else false - and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) + and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let mutable idx = 0 let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi @@ -788,8 +790,8 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'First,'V>(next) + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'First,'V>(next, haltingIdx) let mutable idx = 0 let input2 = enumerable2.GetEnumerator () @@ -800,7 +802,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) else - result.StopFurtherProcessing () + result.StopFurtherProcessing haltingIdx false interface ISeqComponent with @@ -810,8 +812,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Pairwise<'T,'V> (next:SeqConsumer<'T*'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and Pairwise<'T,'V> (next:SeqConsumer<'T*'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let mutable isFirst = true let mutable lastValue = Unchecked.defaultof<'T> @@ -826,8 +828,8 @@ namespace Microsoft.FSharp.Collections lastValue <- input Helpers.avoidTailCall (next.ProcessNext currentPair) - and Skip<'T,'V> (skipCount:int, next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and Skip<'T,'V> (skipCount:int, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let mutable count = 0 @@ -846,15 +848,15 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext input) interface ISeqComponent with - override __.OnComplete () = + override __.OnComplete halted = if count < skipCount then let x = skipCount - count invalidOpFmt "tried to skip {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete () + (Helpers.upcastISeqComponent next).OnComplete halted - and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let mutable skip = true @@ -868,29 +870,29 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>) = - inherit Truncate<'T, 'V>(takeCount, result, next) + and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit Truncate<'T, 'V>(takeCount, result, next, haltingIdx) interface ISeqComponent with - override this.OnComplete () = - if this.Count < takeCount then + override this.OnComplete halted = + if halted = 0 || halted > haltingIdx && this.Count < takeCount then let x = takeCount - this.Count invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete () + (Helpers.upcastISeqComponent next).OnComplete halted - and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) override __.ProcessNext (input:'T) : bool = if predicate input then Helpers.avoidTailCall (next.ProcessNext input) else - result.StopFurtherProcessing () + result.StopFurtherProcessing haltingIdx false - and Tail<'T, 'V> (next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and Tail<'T, 'V> (next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let mutable first = true @@ -902,13 +904,13 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext input) interface ISeqComponent with - override this.OnComplete () = + override this.OnComplete halted = if first then invalidArg "source" (SR.GetString(SR.notEnoughElements)) - (Helpers.upcastISeqComponent next).OnComplete () + (Helpers.upcastISeqComponent next).OnComplete halted - and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let mutable count = 0 @@ -918,10 +920,10 @@ namespace Microsoft.FSharp.Collections if count < truncateCount then count <- count + 1 if count = truncateCount then - result.StopFurtherProcessing () + result.StopFurtherProcessing haltingIdx next.ProcessNext input else - result.StopFurtherProcessing () + result.StopFurtherProcessing haltingIdx false type SeqProcessNextStates = @@ -930,14 +932,14 @@ namespace Microsoft.FSharp.Collections | Finished = 2 type Result<'T>() = - let mutable halted = false + let mutable haltedIdx = 0 member val Current = Unchecked.defaultof<'T> with get, set member val SeqState = SeqProcessNextStates.NotStarted with get, set - member __.Halted = halted + member __.Halted = haltedIdx interface ISeqPipeline with - member __.StopFurtherProcessing () = halted <- true + member __.StopFurtherProcessing haltingIdx = haltedIdx <- haltingIdx // SetResult<> is used at the end of the chain of SeqComponents to assign the final value type SetResult<'T> (result:Result<'T>) = @@ -948,40 +950,38 @@ namespace Microsoft.FSharp.Collections true type Pipeline() = - let mutable halted = false - interface ISeqPipeline with member x.StopFurtherProcessing() = halted <- true + let mutable halted = 0 + interface ISeqPipeline with member x.StopFurtherProcessing haltingIdx = halted <- haltingIdx member __.Halted = halted module ForEach = let enumerable (enumerable:IEnumerable<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = use enumerator = enumerable.GetEnumerator () - while (not pipeline.Halted) && (enumerator.MoveNext ()) do + while (pipeline.Halted = 0) && (enumerator.MoveNext ()) do consumer.ProcessNext enumerator.Current |> ignore let array (array:array<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = let mutable idx = 0 - while (not pipeline.Halted) && (idx < array.Length) do + while (pipeline.Halted = 0) && (idx < array.Length) do consumer.ProcessNext array.[idx] |> ignore idx <- idx + 1 let list (alist:list<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = let rec iterate lst = match pipeline.Halted, lst with - | true, _ - | false, [] -> () - | false, hd :: tl -> + | 0, hd :: tl -> consumer.ProcessNext hd |> ignore iterate tl + | _ -> () iterate alist let unfold (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = let rec iterate current = match pipeline.Halted, generator current with - | true, _ - | false, None -> () - | false, Some (item, next) -> + | 0, Some (item, next) -> consumer.ProcessNext item |> ignore iterate next + | _ -> () iterate state @@ -994,7 +994,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = -1 let isSkipping = makeIsSkipping consumer let mutable maybeSkipping = true - while (not pipeline.Halted) && (idx < terminatingIdx) do + while (pipeline.Halted = 0) && (idx < terminatingIdx) do if maybeSkipping then maybeSkipping <- isSkipping () @@ -1006,10 +1006,10 @@ namespace Microsoft.FSharp.Collections let execute (f:ISeqPipeline->#SeqConsumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = let pipeline = Pipeline() let result = f pipeline - let consumer = current.Create pipeline result + let consumer = current.Create pipeline result 1 try executeOn pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () + (Helpers.upcastISeqComponent consumer).OnComplete pipeline.Halted result finally (Helpers.upcastISeqComponent consumer).OnDispose () @@ -1072,14 +1072,14 @@ namespace Microsoft.FSharp.Collections inherit EnumeratorBase<'U>(result, seqComponent) let rec moveNext () = - if (not result.Halted) && source.MoveNext () then + if (result.Halted = 0) && source.MoveNext () then if seqComponent.ProcessNext source.Current then true else moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete result.Halted false interface IEnumerator with @@ -1100,7 +1100,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (SetResult<'U> result) 1, result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) @@ -1192,7 +1192,7 @@ namespace Microsoft.FSharp.Collections initMoveNext <- ignore let rec moveNext () = - if (not result.Halted) && idx < array.Length then + if (result.Halted = 0) && idx < array.Length then idx <- idx+1 if seqComponent.ProcessNext array.[idx-1] then true @@ -1200,7 +1200,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete result.Halted false interface IEnumerator with @@ -1214,7 +1214,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (SetResult<'U> result) 1, result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) @@ -1242,7 +1242,7 @@ namespace Microsoft.FSharp.Collections let rec moveNext current = match result.Halted, current with - | false, head::tail -> + | 0, head::tail -> if seqComponent.ProcessNext head then list <- tail true @@ -1250,7 +1250,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete result.Halted false interface IEnumerator with @@ -1264,7 +1264,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (SetResult<'U> result) 1, result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) @@ -1283,14 +1283,13 @@ namespace Microsoft.FSharp.Collections let rec moveNext () = match signal.Halted, generator current with - | true, _ - | false, None -> false - | false, Some (item, nextState) -> + | 0, Some (item, nextState) -> current <- nextState if seqComponent.ProcessNext item then true else moveNext () + | _ -> false interface IEnumerator with member __.MoveNext () = @@ -1303,7 +1302,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (SetResult<'U> result) 1, result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) @@ -1346,7 +1345,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = -1 let rec moveNext () = - if (not signal.Halted) && idx < terminatingIdx then + if (signal.Halted = 0) && idx < terminatingIdx then idx <- idx + 1 if maybeSkipping then @@ -1360,11 +1359,11 @@ namespace Microsoft.FSharp.Collections true else moveNext () - elif (not signal.Halted) && idx = System.Int32.MaxValue then + elif (signal.Halted = 0) && idx = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else signal.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete signal.Halted false interface IEnumerator with @@ -1378,7 +1377,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (SetResult<'U> result) 1, result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) @@ -1544,7 +1543,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if f value then this.Value <- true - pipeline.StopFurtherProcessing () + pipeline.StopFurtherProcessing 1 Unchecked.defaultof }) |> fun exists -> exists.Value @@ -1557,7 +1556,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if element = value then this.Value <- true - pipeline.StopFurtherProcessing() + pipeline.StopFurtherProcessing 1 Unchecked.defaultof }) |> fun contains -> contains.Value @@ -1570,7 +1569,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if not (f value) then this.Value <- false - pipeline.StopFurtherProcessing() + pipeline.StopFurtherProcessing 1 Unchecked.defaultof }) |> fun forall -> forall.Value @@ -1675,7 +1674,7 @@ namespace Microsoft.FSharp.Collections match f value with | (Some _) as some -> this.Value <- some - pipeline.StopFurtherProcessing() + pipeline.StopFurtherProcessing 1 | None -> () Unchecked.defaultof }) |> fun pick -> pick.Value @@ -1694,7 +1693,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if f value then this.Value <- Some value - pipeline.StopFurtherProcessing() + pipeline.StopFurtherProcessing 1 Unchecked.defaultof }) |> fun find -> find.Value @@ -1785,7 +1784,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof interface SeqComposer.ISeqComponent with - member this.OnComplete() = + member this.OnComplete _ = if (this:?>SeqComposer.Folder<'T, SeqComposer.Values>).Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) @@ -1936,7 +1935,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if p value then this.Value._1 <- Some(this.Value._2) - pipeline.StopFurtherProcessing() + pipeline.StopFurtherProcessing 1 else this.Value._2 <- this.Value._2 + 1 Unchecked.defaultof @@ -2209,7 +2208,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof interface SeqComposer.ISeqComponent with - member this.OnComplete() = + member this.OnComplete _ = if (this:?>SeqComposer.Folder<'a, SeqComposer.Values<'a, int>>).Value._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun total -> LanguagePrimitives.DivideByInt< ^a> total.Value._1 total.Value._2 @@ -2224,7 +2223,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- this.Value._2 + 1 Unchecked.defaultof interface SeqComposer.ISeqComponent with - member this.OnComplete() = + member this.OnComplete _ = if (this:?>SeqComposer.Folder<'T,SeqComposer.Values<'U, int>>).Value._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.Value._1 total.Value._2 @@ -2243,7 +2242,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof interface SeqComposer.ISeqComponent with - member this.OnComplete() = + member this.OnComplete _ = if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) @@ -2267,7 +2266,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof interface SeqComposer.ISeqComponent with - member this.OnComplete() = + member this.OnComplete _ = if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) @@ -2303,7 +2302,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof interface SeqComposer.ISeqComponent with - member this.OnComplete() = + member this.OnComplete _ = if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) @@ -2327,7 +2326,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof interface SeqComposer.ISeqComponent with - member this.OnComplete() = + member this.OnComplete _ = if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 7e94539f3ea..92b49d572ae 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -15,11 +15,11 @@ namespace Microsoft.FSharp.Collections module Seq = module SeqComposer = type ISeqComponent = - abstract OnComplete : unit -> unit + abstract OnComplete : int -> unit abstract OnDispose : unit -> unit type ISeqPipeline = - abstract StopFurtherProcessing : unit -> unit + abstract StopFurtherProcessing : int -> unit [] type SeqConsumer<'T,'U> = From 0b91c52bc8c8d44c346d9974742279faffa16beb Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 22 Oct 2016 17:04:03 -0400 Subject: [PATCH 102/286] Seq.scan --- src/fsharp/FSharp.Core/seq.fs | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 7503c1f47a5..2d2df419342 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -592,6 +592,10 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'T*'T> () override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T*'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Pairwise (next, haltingIdx) + and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = + inherit SeqComponentFactory<'T,'State> () + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'State,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next, haltingIdx) + and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Skip (count, next, haltingIdx) @@ -828,6 +832,16 @@ namespace Microsoft.FSharp.Collections lastValue <- input Helpers.avoidTailCall (next.ProcessNext currentPair) + and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:SeqConsumer<'State,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) + + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + let mutable foldResult = initialState + + override __.ProcessNext (input:'T) : bool = + foldResult <- f.Invoke(foldResult, input) + Helpers.avoidTailCall (next.ProcessNext foldResult) + and Skip<'T,'V> (skipCount:int, next:SeqConsumer<'T,'V>, haltingIdx:int) = inherit SeqComponent<'T,'V>(next, haltingIdx) @@ -1899,15 +1913,10 @@ namespace Microsoft.FSharp.Collections source |> seqFactory (SeqComposer.PairwiseFactory ()) [] - let scan<'T,'State> f (z:'State) (source : seq<'T>) = - checkNonNull "source" source - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - seq { let zref = ref z - yield !zref - use ie = source.GetEnumerator() - while ie.MoveNext() do - zref := f.Invoke(!zref, ie.Current) - yield !zref } + let scan<'T,'State> f (z:'State) (source : seq<'T>): seq<'State> = + let first = [|z|] :> IEnumerable<'State> + let rest = source |> seqFactory (SeqComposer.ScanFactory (f, z)) + upcast SeqComposer.Enumerable.ConcatEnumerable [|first; rest;|] [] let tryFindBack f (source : seq<'T>) = From 3ae7a6fa4d4182da24b10a1c4ef057632ede6f7a Mon Sep 17 00:00:00 2001 From: liboz Date: Sun, 23 Oct 2016 10:05:30 -0400 Subject: [PATCH 103/286] Seq.tryItem, tryHead, head, exactlyOne --- src/fsharp/FSharp.Core/seq.fs | 70 ++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 2d2df419342..a9a2faa4ac6 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1529,10 +1529,18 @@ namespace Microsoft.FSharp.Collections [] let tryItem i (source : seq<'T>) = - checkNonNull "source" source if i < 0 then None else - use e = source.GetEnumerator() - IEnumerator.tryItem i e + source + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, SeqComposer.Values>> (SeqComposer.Values<_, _> (0, None)) with + override this.ProcessNext value = + if this.Value._1 = i then + this.Value._2 <- Some value + pipeline.StopFurtherProcessing 1 + else + this.Value._1 <- this.Value._1 + 1 + Unchecked.defaultof }) + |> fun item -> item.Value._2 [] let nth i (source : seq<'T>) = item i source @@ -2382,7 +2390,6 @@ namespace Microsoft.FSharp.Collections ok <- p.Invoke(e1.Current, e2.Current) ok - [] let exists2 p (source1: seq<_>) (source2: seq<_>) = checkNonNull "source1" source1 @@ -2394,20 +2401,23 @@ namespace Microsoft.FSharp.Collections while (not ok && e1.MoveNext() && e2.MoveNext()) do ok <- p.Invoke(e1.Current, e2.Current) ok + + [] + let tryHead (source : seq<_>) = + source + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, Option<'T>> (None) with + override this.ProcessNext value = + this.Value <- Some value + pipeline.StopFurtherProcessing 1 + Unchecked.defaultof }) + |> fun head -> head.Value [] let head (source : seq<_>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if (e.MoveNext()) then e.Current - else invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - - [] - let tryHead (source : seq<_>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if (e.MoveNext()) then Some e.Current - else None + match tryHead source with + | None -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + | Some x -> x [] let tail (source: seq<'T>) = @@ -2437,16 +2447,26 @@ namespace Microsoft.FSharp.Collections [] let exactlyOne (source : seq<_>) = - checkNonNull "source" source - use e = source.GetEnumerator() - if e.MoveNext() then - let v = e.Current - if e.MoveNext() then - invalidArg "source" (SR.GetString(SR.inputSequenceTooLong)) - else - v - else - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + source + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values(true, Unchecked.defaultof<'T>, false)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + else + this.Value._3 <- true + pipeline.StopFurtherProcessing 1 + Unchecked.defaultof + interface SeqComposer.ISeqComponent with + member this.OnComplete _ = + let value = (this:?>SeqComposer.Folder<'T,SeqComposer.Values>) + if value.Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + elif value.Value._3 then + invalidArg "source" (SR.GetString(SR.inputSequenceTooLong)) + }) + |> fun one -> one.Value._2 [] let rev source = From 701afd53d9739eb79d34a4c7c8fbc527c8e51f81 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 24 Oct 2016 20:17:12 +1100 Subject: [PATCH 104/286] Another take on halting index - Shrank public interface by removing ISeqPipeline from ForEach. - Renamed haltingIdx to pipelineDepth - Removed haltingIdx from where I could --- src/fsharp/FSharp.Core/seq.fs | 284 +++++++++++++++++---------------- src/fsharp/FSharp.Core/seq.fsi | 5 +- 2 files changed, 150 insertions(+), 139 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index a9a2faa4ac6..27d9cd7190e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -501,7 +501,7 @@ namespace Microsoft.FSharp.Collections [] type SeqEnumerable<'T>() = - abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:(ISeqPipeline->'a) -> 'a + abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:((unit->unit)->'a) -> 'a module Helpers = // used for performance reasons; these are not recursive calls, so should be safe @@ -522,135 +522,149 @@ namespace Microsoft.FSharp.Collections member __.OnDispose() = () } type [] SeqComponentFactory<'T,'U> () = - abstract Create<'V> : ISeqPipeline -> SeqConsumer<'U,'V> -> haltingIdx:int -> SeqConsumer<'T,'V> + let mutable pipelineDepth = Nullable () + + abstract Create<'V> : ISeqPipeline -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> + + member __.PipelineDepth = + if pipelineDepth.HasValue + then pipelineDepth.Value + else 1 + + member __.SetPipelineDepth depth = + if pipelineDepth.HasValue + then failwith "libray implementation error: factory depth can only be set once" + else pipelineDepth <- Nullable depth and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = inherit SeqComponentFactory<'T,'V> () - override __.Create<'W> (result:ISeqPipeline) (next:SeqConsumer<'V,'W>) (haltingIdx:int) : SeqConsumer<'T,'W> = - first.Create result (second.Create result next (haltingIdx+1)) (haltingIdx+2) + override __.Create<'W> (result:ISeqPipeline) (next:SeqConsumer<'V,'W>) : SeqConsumer<'T,'W> = + first.Create result (second.Create result next) static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = - upcast ComposedFactory(first, second) + let composed = ComposedFactory(first, second) + let nextDepth = first.PipelineDepth + 1 + second.SetPipelineDepth nextDepth + composed.SetPipelineDepth nextDepth + upcast composed and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Choose (filter, next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Choose (filter, next) and DistinctFactory<'T when 'T: equality> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Distinct (next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = match next with - | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter haltingIdx - | _ -> upcast Filter (filter, next, haltingIdx) + | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter + | _ -> upcast Filter (filter, next) and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () static let singleton = IdentityFactory<'T>() - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (_haltingIdx:int) : SeqConsumer<'T,'V> = next + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = next static member IdentityFactory = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = match next with - | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map haltingIdx - | _ -> upcast Map<_,_,_> (map, next, haltingIdx) + | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map + | _ -> upcast Map<_,_,_> (map, next) and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next, haltingIdx) + override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next, this.PipelineDepth) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = inherit SeqComponentFactory<'Second,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next, haltingIdx) + override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next, this.PipelineDepth) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, haltingIdx) + override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, this.PipelineDepth) and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next, haltingIdx) + override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next, this.PipelineDepth) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T*'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Pairwise (next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T*'T,'V>) : SeqConsumer<'T,'V> = upcast Pairwise (next) and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = inherit SeqComponentFactory<'T,'State> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'State,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'State,'V>) : SeqConsumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Skip (count, next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next, haltingIdx) + override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next, this.PipelineDepth) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Take (count, result, next, haltingIdx) + override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Take (count, result, next, this.PipelineDepth) and TailFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next, haltingIdx) + override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next, this.PipelineDepth) - and [] SeqComponent<'T,'U> (next:ISeqComponent, haltingIdx:int) = + and [] SeqComponent<'T,'U> (next:ISeqComponent) = inherit SeqConsumer<'T,'U>() // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip // and it can only do it at the start of a sequence abstract Skipping : unit -> bool - abstract CreateMap<'S> : map:('S->'T) -> haltingIdx:int -> SeqComponent<'S,'U> - abstract CreateFilter : filter:('T->bool) -> haltingIdx:int -> SeqComponent<'T,'U> + abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> + abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> interface ISeqComponent with - member __.OnComplete halted = next.OnComplete halted + member __.OnComplete terminatingDepth = next.OnComplete terminatingDepth member __.OnDispose () = next.OnDispose () - member __.HaltingIdx = haltingIdx - default __.Skipping () = false - default this.CreateMap<'S> (map:'S->'T) (haltingIdx:int) = upcast Map<_,_,_> (map, this, haltingIdx) - default this.CreateFilter (filter:'T->bool) (haltingIdx:int) = upcast Filter (filter, this, haltingIdx) + default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) + default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) - and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqConsumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = match choose input with | Some value -> Helpers.avoidTailCall (next.ProcessNext value) | None -> false - and Distinct<'T,'V when 'T: equality> (next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Distinct<'T,'V when 'T: equality> (next:SeqConsumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) @@ -660,8 +674,8 @@ namespace Microsoft.FSharp.Collections else false - and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqConsumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) @@ -671,8 +685,8 @@ namespace Microsoft.FSharp.Collections else false - and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqConsumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) @@ -682,10 +696,10 @@ namespace Microsoft.FSharp.Collections else false - and Filter<'T,'V> (filter:'T->bool, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Filter<'T,'V> (filter:'T->bool, next:SeqConsumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) - override this.CreateMap<'S> (map:'S->'T) (haltingIdx:int) = upcast MapThenFilter<_,_,_> (map, filter, next, haltingIdx) + override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) override __.ProcessNext (input:'T) : bool = if filter input then @@ -693,8 +707,8 @@ namespace Microsoft.FSharp.Collections else false - and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqConsumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = if filter input then @@ -702,16 +716,16 @@ namespace Microsoft.FSharp.Collections else false - and Map<'T,'U,'V> (map:'T->'U, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Map<'T,'U,'V> (map:'T->'U, next:SeqConsumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) - override this.CreateFilter (filter:'T->bool) (haltingIdx:int) = upcast FilterThenMap (filter, map, next, haltingIdx) + override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'First,'V>(next, haltingIdx) + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -720,7 +734,7 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) else - result.StopFurtherProcessing haltingIdx + result.StopFurtherProcessing pipelineDepth false interface ISeqComponent with @@ -730,8 +744,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'Second,'V>(next, haltingIdx) + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + inherit SeqComponent<'Second,'V>(next) let input1 = enumerable1.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -740,7 +754,7 @@ namespace Microsoft.FSharp.Collections if input1.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) else - result.StopFurtherProcessing haltingIdx + result.StopFurtherProcessing pipelineDepth false interface ISeqComponent with @@ -750,8 +764,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'First,'V>(next, haltingIdx) + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () let input3 = enumerable3.GetEnumerator () @@ -761,7 +775,7 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () && input3.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) else - result.StopFurtherProcessing haltingIdx + result.StopFurtherProcessing pipelineDepth false interface ISeqComponent with @@ -774,8 +788,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqConsumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = let u = map input @@ -784,8 +798,8 @@ namespace Microsoft.FSharp.Collections else false - and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqConsumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) let mutable idx = 0 let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi @@ -794,8 +808,8 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'First,'V>(next, haltingIdx) + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + inherit SeqComponent<'First,'V>(next) let mutable idx = 0 let input2 = enumerable2.GetEnumerator () @@ -806,7 +820,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) else - result.StopFurtherProcessing haltingIdx + result.StopFurtherProcessing pipelineDepth false interface ISeqComponent with @@ -816,8 +830,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Pairwise<'T,'V> (next:SeqConsumer<'T*'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Pairwise<'T,'V> (next:SeqConsumer<'T*'T,'V>) = + inherit SeqComponent<'T,'V>(next) let mutable isFirst = true let mutable lastValue = Unchecked.defaultof<'T> @@ -832,8 +846,8 @@ namespace Microsoft.FSharp.Collections lastValue <- input Helpers.avoidTailCall (next.ProcessNext currentPair) - and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:SeqConsumer<'State,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:SeqConsumer<'State,'V>) = + inherit SeqComponent<'T,'V>(next) let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let mutable foldResult = initialState @@ -842,8 +856,8 @@ namespace Microsoft.FSharp.Collections foldResult <- f.Invoke(foldResult, input) Helpers.avoidTailCall (next.ProcessNext foldResult) - and Skip<'T,'V> (skipCount:int, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Skip<'T,'V> (skipCount:int, next:SeqConsumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -862,15 +876,15 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext input) interface ISeqComponent with - override __.OnComplete halted = + override __.OnComplete terminatingDepth = if count < skipCount then let x = skipCount - count invalidOpFmt "tried to skip {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete halted + (Helpers.upcastISeqComponent next).OnComplete terminatingDepth - and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) let mutable skip = true @@ -884,29 +898,29 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit Truncate<'T, 'V>(takeCount, result, next, haltingIdx) + and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineDepth:int) = + inherit Truncate<'T, 'V>(takeCount, result, next, pipelineDepth) interface ISeqComponent with - override this.OnComplete halted = - if halted = 0 || halted > haltingIdx && this.Count < takeCount then + override this.OnComplete terminatingDepth = + if terminatingDepth < pipelineDepth && this.Count < takeCount then let x = takeCount - this.Count invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete halted + (Helpers.upcastISeqComponent next).OnComplete terminatingDepth - and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineDepth:int) = + inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = if predicate input then Helpers.avoidTailCall (next.ProcessNext input) else - result.StopFurtherProcessing haltingIdx + result.StopFurtherProcessing pipelineDepth false - and Tail<'T, 'V> (next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Tail<'T, 'V> (next:SeqConsumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) let mutable first = true @@ -918,13 +932,13 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext input) interface ISeqComponent with - override this.OnComplete halted = + override this.OnComplete terminatingDepth = if first then invalidArg "source" (SR.GetString(SR.notEnoughElements)) - (Helpers.upcastISeqComponent next).OnComplete halted + (Helpers.upcastISeqComponent next).OnComplete terminatingDepth - and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineDepth:int) = + inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -934,10 +948,10 @@ namespace Microsoft.FSharp.Collections if count < truncateCount then count <- count + 1 if count = truncateCount then - result.StopFurtherProcessing haltingIdx + result.StopFurtherProcessing pipelineDepth next.ProcessNext input else - result.StopFurtherProcessing haltingIdx + result.StopFurtherProcessing pipelineDepth false type SeqProcessNextStates = @@ -946,14 +960,14 @@ namespace Microsoft.FSharp.Collections | Finished = 2 type Result<'T>() = - let mutable haltedIdx = 0 + let mutable haltedDepth = 0 member val Current = Unchecked.defaultof<'T> with get, set member val SeqState = SeqProcessNextStates.NotStarted with get, set - member __.Halted = haltedIdx + member __.Halted = haltedDepth interface ISeqPipeline with - member __.StopFurtherProcessing haltingIdx = haltedIdx <- haltingIdx + member __.StopFurtherProcessing pipelineDepth = haltedDepth <- pipelineDepth // SetResult<> is used at the end of the chain of SeqComponents to assign the final value type SetResult<'T> (result:Result<'T>) = @@ -964,9 +978,9 @@ namespace Microsoft.FSharp.Collections true type Pipeline() = - let mutable halted = 0 - interface ISeqPipeline with member x.StopFurtherProcessing haltingIdx = halted <- haltingIdx - member __.Halted = halted + let mutable haltedDepth = 0 + interface ISeqPipeline with member x.StopFurtherProcessing pipelineDepth = haltedDepth <- pipelineDepth + member __.Halted = haltedDepth module ForEach = let enumerable (enumerable:IEnumerable<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = @@ -1017,10 +1031,10 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 - let execute (f:ISeqPipeline->#SeqConsumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = + let execute (f:(unit->unit)->#SeqConsumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = let pipeline = Pipeline() - let result = f pipeline - let consumer = current.Create pipeline result 1 + let result = f (fun () -> (pipeline:>ISeqPipeline).StopFurtherProcessing (current.PipelineDepth+1)) + let consumer = current.Create pipeline result try executeOn pipeline consumer (Helpers.upcastISeqComponent consumer).OnComplete pipeline.Halted @@ -1114,12 +1128,12 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (SetResult<'U> result) 1, result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = ForEach.execute f current (ForEach.enumerable enumerable) and ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = @@ -1171,7 +1185,7 @@ namespace Microsoft.FSharp.Collections override this.Append source = Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = + override this.ForEach (f:(unit->unit)->#SeqConsumer<'T,'T>) = ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) and ConcatEnumerable<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = @@ -1184,7 +1198,7 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(this, next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = + override this.ForEach (f:(unit->unit)->#SeqConsumer<'T,'T>) = ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) let create enumerable current = @@ -1228,12 +1242,12 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (SetResult<'U> result) 1, result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = ForEach.execute f current (ForEach.array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = @@ -1278,12 +1292,12 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (SetResult<'U> result) 1, result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = ForEach.execute f current (ForEach.list alist) let create alist current = @@ -1316,12 +1330,12 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (SetResult<'U> result) 1, result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (SetResult<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = ForEach.execute f current (ForEach.unfold generator state) module Init = @@ -1391,12 +1405,12 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (SetResult<'U> result) 1, result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (SetResult<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) - override this.ForEach (createResult:ISeqPipeline->#SeqConsumer<'U,'U>) = + override this.ForEach (createResult:(unit->unit)->#SeqConsumer<'U,'U>) = let terminatingIdx = getTerminatingIdx count ForEach.execute createResult current (ForEach.init f terminatingIdx) @@ -1463,7 +1477,7 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = + override this.ForEach (f:(unit->unit)->#SeqConsumer<'T,'T>) = ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable (Helpers.upcastEnumerable this)) #if FX_NO_ICLONEABLE @@ -1531,12 +1545,12 @@ namespace Microsoft.FSharp.Collections let tryItem i (source : seq<'T>) = if i < 0 then None else source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, SeqComposer.Values>> (SeqComposer.Values<_, _> (0, None)) with override this.ProcessNext value = if this.Value._1 = i then this.Value._2 <- Some value - pipeline.StopFurtherProcessing 1 + halt () else this.Value._1 <- this.Value._1 + 1 Unchecked.defaultof }) @@ -1560,12 +1574,12 @@ namespace Microsoft.FSharp.Collections [] let exists f (source : seq<'T>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, bool> (false) with override this.ProcessNext value = if f value then this.Value <- true - pipeline.StopFurtherProcessing 1 + halt () Unchecked.defaultof }) |> fun exists -> exists.Value @@ -1573,12 +1587,12 @@ namespace Microsoft.FSharp.Collections [] let inline contains element (source : seq<'T>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, bool> (false) with override this.ProcessNext value = if element = value then this.Value <- true - pipeline.StopFurtherProcessing 1 + halt () Unchecked.defaultof }) |> fun contains -> contains.Value @@ -1586,12 +1600,12 @@ namespace Microsoft.FSharp.Collections [] let forall f (source : seq<'T>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, bool> (true) with override this.ProcessNext value = if not (f value) then this.Value <- false - pipeline.StopFurtherProcessing 1 + halt () Unchecked.defaultof }) |> fun forall -> forall.Value @@ -1690,13 +1704,13 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source : seq<'T>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, Option<'U>> (None) with override this.ProcessNext value = match f value with | (Some _) as some -> this.Value <- some - pipeline.StopFurtherProcessing 1 + halt () | None -> () Unchecked.defaultof }) |> fun pick -> pick.Value @@ -1710,12 +1724,12 @@ namespace Microsoft.FSharp.Collections [] let tryFind f (source : seq<'T>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, Option<'T>> (None) with override this.ProcessNext value = if f value then this.Value <- Some value - pipeline.StopFurtherProcessing 1 + halt () Unchecked.defaultof }) |> fun find -> find.Value @@ -1947,12 +1961,12 @@ namespace Microsoft.FSharp.Collections [] let tryFindIndex p (source:seq<_>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, SeqComposer.Values, int>> (SeqComposer.Values<_,_>(None, 0)) with override this.ProcessNext value = if p value then this.Value._1 <- Some(this.Value._2) - pipeline.StopFurtherProcessing 1 + halt () else this.Value._2 <- this.Value._2 + 1 Unchecked.defaultof @@ -2405,11 +2419,11 @@ namespace Microsoft.FSharp.Collections [] let tryHead (source : seq<_>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, Option<'T>> (None) with override this.ProcessNext value = this.Value <- Some value - pipeline.StopFurtherProcessing 1 + halt () Unchecked.defaultof }) |> fun head -> head.Value @@ -2448,7 +2462,7 @@ namespace Microsoft.FSharp.Collections [] let exactlyOne (source : seq<_>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values(true, Unchecked.defaultof<'T>, false)) with override this.ProcessNext value = if this.Value._1 then @@ -2456,7 +2470,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value else this.Value._3 <- true - pipeline.StopFurtherProcessing 1 + halt () Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete _ = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 92b49d572ae..681da44368c 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -18,9 +18,6 @@ namespace Microsoft.FSharp.Collections abstract OnComplete : int -> unit abstract OnDispose : unit -> unit - type ISeqPipeline = - abstract StopFurtherProcessing : int -> unit - [] type SeqConsumer<'T,'U> = new : unit -> SeqConsumer<'T,'U> @@ -54,7 +51,7 @@ namespace Microsoft.FSharp.Collections [] type SeqEnumerable<'T> = - abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:(ISeqPipeline->'a) -> 'a + abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:((unit->unit)->'a) -> 'a /// Returns a new sequence that contains the cartesian product of the two input sequences. /// The first sequence. From fbd117bc29e0fa3bb533aa168c52baf288f54077 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 25 Oct 2016 19:21:05 +1100 Subject: [PATCH 105/286] Remove mutable state in SeqComponentFactory - Changed "depth" to "idx" to better communicate the function --- src/fsharp/FSharp.Core/seq.fs | 183 ++++++++++++++++----------------- src/fsharp/FSharp.Core/seq.fsi | 4 +- 2 files changed, 92 insertions(+), 95 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 27d9cd7190e..1acff220125 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -451,12 +451,18 @@ namespace Microsoft.FSharp.Collections module SeqComposer = open IEnumerator + type PipeIdx = int + type ``PipeIdx?`` = Nullable + let emptyPipeIdx = Nullable () + let inline getPipeIdx (maybePipeIdx:``PipeIdx?``) = if maybePipeIdx.HasValue then maybePipeIdx.Value else 1 + let inline makePipeIdx (pipeIdx:PipeIdx) = Nullable pipeIdx + type ISeqComponent = - abstract OnComplete : int -> unit + abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit type ISeqPipeline = - abstract StopFurtherProcessing : int -> unit + abstract StopFurtherProcessing : PipeIdx -> unit [] type SeqConsumer<'T,'U> () = @@ -521,52 +527,41 @@ namespace Microsoft.FSharp.Collections member __.OnComplete _ = () member __.OnDispose() = () } - type [] SeqComponentFactory<'T,'U> () = - let mutable pipelineDepth = Nullable () + type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = + abstract Create<'V> : ISeqPipeline -> ``PipeIdx?`` -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> - abstract Create<'V> : ISeqPipeline -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> + new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) - member __.PipelineDepth = - if pipelineDepth.HasValue - then pipelineDepth.Value - else 1 + member __.PipeIdx = getPipeIdx pipeIdx - member __.SetPipelineDepth depth = - if pipelineDepth.HasValue - then failwith "libray implementation error: factory depth can only be set once" - else pipelineDepth <- Nullable depth + and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>, secondPipeIdx:PipeIdx) = + inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) - and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = - inherit SeqComponentFactory<'T,'V> () - override __.Create<'W> (result:ISeqPipeline) (next:SeqConsumer<'V,'W>) : SeqConsumer<'T,'W> = - first.Create result (second.Create result next) + override this.Create<'W> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'V,'W>) : SeqConsumer<'T,'W> = + first.Create result pipeIdx (second.Create result (makePipeIdx secondPipeIdx) next) static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = - let composed = ComposedFactory(first, second) - let nextDepth = first.PipelineDepth + 1 - second.SetPipelineDepth nextDepth - composed.SetPipelineDepth nextDepth - upcast composed + upcast ComposedFactory(first, second, first.PipeIdx+1) and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Choose (filter, next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Choose (filter, next) and DistinctFactory<'T when 'T: equality> () = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Distinct (next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = match next with | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter | _ -> upcast Filter (filter, next) @@ -574,67 +569,67 @@ namespace Microsoft.FSharp.Collections and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () static let singleton = IdentityFactory<'T>() - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = next + override __.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = next static member IdentityFactory = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = match next with | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map | _ -> upcast Map<_,_,_> (map, next) and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next, this.PipelineDepth) + override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next, getPipeIdx pipeIdx) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = inherit SeqComponentFactory<'Second,'U> () - override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next, this.PipelineDepth) + override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next, getPipeIdx pipeIdx) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, this.PipelineDepth) + override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, getPipeIdx pipeIdx) and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next, this.PipelineDepth) + override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next, getPipeIdx pipeIdx) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T*'T,'V>) : SeqConsumer<'T,'V> = upcast Pairwise (next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T*'T,'V>) : SeqConsumer<'T,'V> = upcast Pairwise (next) and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = inherit SeqComponentFactory<'T,'State> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'State,'V>) : SeqConsumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'State,'V>) : SeqConsumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Skip (count, next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next, this.PipelineDepth) + override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next, getPipeIdx pipeIdx) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Take (count, result, next, this.PipelineDepth) + override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Take (count, result, next, getPipeIdx pipeIdx) and TailFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next, this.PipelineDepth) + override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next, getPipeIdx pipeIdx) and [] SeqComponent<'T,'U> (next:ISeqComponent) = inherit SeqConsumer<'T,'U>() @@ -647,7 +642,7 @@ namespace Microsoft.FSharp.Collections abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> interface ISeqComponent with - member __.OnComplete terminatingDepth = next.OnComplete terminatingDepth + member __.OnComplete terminatingIdx = next.OnComplete terminatingIdx member __.OnDispose () = next.OnDispose () default __.Skipping () = false @@ -724,7 +719,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -734,7 +729,7 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) else - result.StopFurtherProcessing pipelineDepth + result.StopFurtherProcessing pipeIdx false interface ISeqComponent with @@ -744,7 +739,7 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'Second,'V>(next) let input1 = enumerable1.GetEnumerator () @@ -754,7 +749,7 @@ namespace Microsoft.FSharp.Collections if input1.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) else - result.StopFurtherProcessing pipelineDepth + result.StopFurtherProcessing pipeIdx false interface ISeqComponent with @@ -764,7 +759,7 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -775,7 +770,7 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () && input3.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) else - result.StopFurtherProcessing pipelineDepth + result.StopFurtherProcessing pipeIdx false interface ISeqComponent with @@ -808,7 +803,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let mutable idx = 0 @@ -820,7 +815,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) else - result.StopFurtherProcessing pipelineDepth + result.StopFurtherProcessing pipeIdx false interface ISeqComponent with @@ -876,12 +871,12 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext input) interface ISeqComponent with - override __.OnComplete terminatingDepth = + override __.OnComplete terminatingIdx = if count < skipCount then let x = skipCount - count invalidOpFmt "tried to skip {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete terminatingDepth + (Helpers.upcastISeqComponent next).OnComplete terminatingIdx and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -898,25 +893,25 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineDepth:int) = - inherit Truncate<'T, 'V>(takeCount, result, next, pipelineDepth) + and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineIdx:int) = + inherit Truncate<'T, 'V>(takeCount, result, next, pipelineIdx) interface ISeqComponent with - override this.OnComplete terminatingDepth = - if terminatingDepth < pipelineDepth && this.Count < takeCount then + override this.OnComplete terminatingIdx = + if terminatingIdx < pipelineIdx && this.Count < takeCount then let x = takeCount - this.Count invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete terminatingDepth + (Helpers.upcastISeqComponent next).OnComplete terminatingIdx - and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineDepth:int) = + and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = if predicate input then Helpers.avoidTailCall (next.ProcessNext input) else - result.StopFurtherProcessing pipelineDepth + result.StopFurtherProcessing pipeIdx false and Tail<'T, 'V> (next:SeqConsumer<'T,'V>) = @@ -932,12 +927,12 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext input) interface ISeqComponent with - override this.OnComplete terminatingDepth = + override this.OnComplete terminatingIdx = if first then invalidArg "source" (SR.GetString(SR.notEnoughElements)) - (Helpers.upcastISeqComponent next).OnComplete terminatingDepth + (Helpers.upcastISeqComponent next).OnComplete terminatingIdx - and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineDepth:int) = + and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -948,10 +943,10 @@ namespace Microsoft.FSharp.Collections if count < truncateCount then count <- count + 1 if count = truncateCount then - result.StopFurtherProcessing pipelineDepth + result.StopFurtherProcessing pipeIdx next.ProcessNext input else - result.StopFurtherProcessing pipelineDepth + result.StopFurtherProcessing pipeIdx false type SeqProcessNextStates = @@ -960,14 +955,14 @@ namespace Microsoft.FSharp.Collections | Finished = 2 type Result<'T>() = - let mutable haltedDepth = 0 + let mutable haltedIdx = 0 member val Current = Unchecked.defaultof<'T> with get, set member val SeqState = SeqProcessNextStates.NotStarted with get, set - member __.Halted = haltedDepth + member __.HaltedIdx = haltedIdx interface ISeqPipeline with - member __.StopFurtherProcessing pipelineDepth = haltedDepth <- pipelineDepth + member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx // SetResult<> is used at the end of the chain of SeqComponents to assign the final value type SetResult<'T> (result:Result<'T>) = @@ -978,25 +973,25 @@ namespace Microsoft.FSharp.Collections true type Pipeline() = - let mutable haltedDepth = 0 - interface ISeqPipeline with member x.StopFurtherProcessing pipelineDepth = haltedDepth <- pipelineDepth - member __.Halted = haltedDepth + let mutable haltedIdx = 0 + interface ISeqPipeline with member x.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx + member __.HaltedIdx = haltedIdx module ForEach = let enumerable (enumerable:IEnumerable<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = use enumerator = enumerable.GetEnumerator () - while (pipeline.Halted = 0) && (enumerator.MoveNext ()) do + while (pipeline.HaltedIdx = 0) && (enumerator.MoveNext ()) do consumer.ProcessNext enumerator.Current |> ignore let array (array:array<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = let mutable idx = 0 - while (pipeline.Halted = 0) && (idx < array.Length) do + while (pipeline.HaltedIdx = 0) && (idx < array.Length) do consumer.ProcessNext array.[idx] |> ignore idx <- idx + 1 let list (alist:list<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = let rec iterate lst = - match pipeline.Halted, lst with + match pipeline.HaltedIdx, lst with | 0, hd :: tl -> consumer.ProcessNext hd |> ignore iterate tl @@ -1005,7 +1000,7 @@ namespace Microsoft.FSharp.Collections let unfold (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = let rec iterate current = - match pipeline.Halted, generator current with + match pipeline.HaltedIdx, generator current with | 0, Some (item, next) -> consumer.ProcessNext item |> ignore iterate next @@ -1022,7 +1017,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = -1 let isSkipping = makeIsSkipping consumer let mutable maybeSkipping = true - while (pipeline.Halted = 0) && (idx < terminatingIdx) do + while (pipeline.HaltedIdx = 0) && (idx < terminatingIdx) do if maybeSkipping then maybeSkipping <- isSkipping () @@ -1033,11 +1028,11 @@ namespace Microsoft.FSharp.Collections let execute (f:(unit->unit)->#SeqConsumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = let pipeline = Pipeline() - let result = f (fun () -> (pipeline:>ISeqPipeline).StopFurtherProcessing (current.PipelineDepth+1)) - let consumer = current.Create pipeline result + let result = f (fun () -> (pipeline:>ISeqPipeline).StopFurtherProcessing (current.PipeIdx+1)) + let consumer = current.Create pipeline emptyPipeIdx result try executeOn pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete pipeline.Halted + (Helpers.upcastISeqComponent consumer).OnComplete pipeline.HaltedIdx result finally (Helpers.upcastISeqComponent consumer).OnDispose () @@ -1100,14 +1095,14 @@ namespace Microsoft.FSharp.Collections inherit EnumeratorBase<'U>(result, seqComponent) let rec moveNext () = - if (result.Halted = 0) && source.MoveNext () then + if (result.HaltedIdx = 0) && source.MoveNext () then if seqComponent.ProcessNext source.Current then true else moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete result.Halted + (Helpers.upcastISeqComponent seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1128,7 +1123,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) @@ -1220,7 +1215,7 @@ namespace Microsoft.FSharp.Collections initMoveNext <- ignore let rec moveNext () = - if (result.Halted = 0) && idx < array.Length then + if (result.HaltedIdx = 0) && idx < array.Length then idx <- idx+1 if seqComponent.ProcessNext array.[idx-1] then true @@ -1228,7 +1223,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete result.Halted + (Helpers.upcastISeqComponent seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1242,7 +1237,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) @@ -1269,7 +1264,7 @@ namespace Microsoft.FSharp.Collections let mutable list = alist let rec moveNext current = - match result.Halted, current with + match result.HaltedIdx, current with | 0, head::tail -> if seqComponent.ProcessNext head then list <- tail @@ -1278,7 +1273,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete result.Halted + (Helpers.upcastISeqComponent seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1292,7 +1287,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) @@ -1310,7 +1305,7 @@ namespace Microsoft.FSharp.Collections let mutable current = state let rec moveNext () = - match signal.Halted, generator current with + match signal.HaltedIdx, generator current with | 0, Some (item, nextState) -> current <- nextState if seqComponent.ProcessNext item then @@ -1330,7 +1325,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) @@ -1373,7 +1368,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = -1 let rec moveNext () = - if (signal.Halted = 0) && idx < terminatingIdx then + if (signal.HaltedIdx = 0) && idx < terminatingIdx then idx <- idx + 1 if maybeSkipping then @@ -1387,11 +1382,11 @@ namespace Microsoft.FSharp.Collections true else moveNext () - elif (signal.Halted = 0) && idx = System.Int32.MaxValue then + elif (signal.HaltedIdx = 0) && idx = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else signal.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete signal.Halted + (Helpers.upcastISeqComponent seqComponent).OnComplete signal.HaltedIdx false interface IEnumerator with @@ -1405,7 +1400,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 681da44368c..d4ad0b51e0b 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -14,8 +14,10 @@ namespace Microsoft.FSharp.Collections [] module Seq = module SeqComposer = + type PipeIdx = int + type ISeqComponent = - abstract OnComplete : int -> unit + abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit [] From 44d49a433cddc9163913c50d9b6cb7aead704922 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 26 Oct 2016 19:46:49 +1100 Subject: [PATCH 106/286] Simplified use of OnComplete & OnDispose Pushed the chaining functionality into the interface and added extra methods on SeqConsumer. This means the consumer can ignore the interface and just implement their version, which means less likely to be an issue of the message not being chained correctly. It also has the advantage that in the object expressions we don't have to cast back to the base type, which was a potentital area for errors. --- src/fsharp/FSharp.Core/seq.fs | 125 +++++++++++++-------------------- src/fsharp/FSharp.Core/seq.fsi | 12 ++-- 2 files changed, 54 insertions(+), 83 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 1acff220125..f816379be64 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -468,9 +468,17 @@ namespace Microsoft.FSharp.Collections type SeqConsumer<'T,'U> () = abstract ProcessNext : input:'T -> bool + abstract OnComplete : PipeIdx -> unit + abstract OnDispose : unit -> unit + + default __.OnComplete _ = () + default __.OnDispose () = () + interface ISeqComponent with - member __.OnComplete _ = () - member __.OnDispose() = () + member this.OnComplete terminatingIdx = this.OnComplete terminatingIdx + member this.OnDispose () = + try this.OnDispose () + finally () [] type Values<'a,'b> = @@ -522,11 +530,6 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) - let seqComponentTail = - { new ISeqComponent with - member __.OnComplete _ = () - member __.OnDispose() = () } - type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = abstract Create<'V> : ISeqPipeline -> ``PipeIdx?`` -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> @@ -642,8 +645,12 @@ namespace Microsoft.FSharp.Collections abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> interface ISeqComponent with - member __.OnComplete terminatingIdx = next.OnComplete terminatingIdx - member __.OnDispose () = next.OnDispose () + member this.OnComplete terminatingIdx = + this.OnComplete terminatingIdx + next.OnComplete terminatingIdx + member this.OnDispose () = + try this.OnDispose () + finally next.OnDispose () default __.Skipping () = false @@ -732,12 +739,8 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing pipeIdx false - interface ISeqComponent with - override __.OnDispose () = - try - input2.Dispose () - finally - (Helpers.upcastISeqComponent next).OnDispose () + override __.OnDispose () = + input2.Dispose () and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'Second,'V>(next) @@ -752,12 +755,8 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing pipeIdx false - interface ISeqComponent with - override __.OnDispose () = - try - input1.Dispose () - finally - (Helpers.upcastISeqComponent next).OnDispose () + override __.OnDispose () = + input1.Dispose () and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) @@ -773,15 +772,9 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing pipeIdx false - interface ISeqComponent with - override __.OnDispose () = - try - input2.Dispose () - finally - try - input3.Dispose () - finally - (Helpers.upcastISeqComponent next).OnDispose () + override __.OnDispose () = + try input2.Dispose () + finally input3.Dispose () and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) @@ -818,12 +811,8 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing pipeIdx false - interface ISeqComponent with - override __.OnDispose () = - try - input2.Dispose () - finally - (Helpers.upcastISeqComponent next).OnDispose () + override __.OnDispose () = + input2.Dispose () and Pairwise<'T,'V> (next:SeqConsumer<'T*'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -870,13 +859,11 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - interface ISeqComponent with - override __.OnComplete terminatingIdx = - if count < skipCount then - let x = skipCount - count - invalidOpFmt "tried to skip {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete terminatingIdx + override __.OnComplete _ = + if count < skipCount then + let x = skipCount - count + invalidOpFmt "tried to skip {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -896,13 +883,11 @@ namespace Microsoft.FSharp.Collections and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineIdx:int) = inherit Truncate<'T, 'V>(takeCount, result, next, pipelineIdx) - interface ISeqComponent with - override this.OnComplete terminatingIdx = - if terminatingIdx < pipelineIdx && this.Count < takeCount then - let x = takeCount - this.Count - invalidOpFmt "tried to take {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete terminatingIdx + override this.OnComplete terminatingIdx = + if terminatingIdx < pipelineIdx && this.Count < takeCount then + let x = takeCount - this.Count + invalidOpFmt "tried to take {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) @@ -926,11 +911,9 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - interface ISeqComponent with - override this.OnComplete terminatingIdx = - if first then - invalidArg "source" (SR.GetString(SR.notEnoughElements)) - (Helpers.upcastISeqComponent next).OnComplete terminatingIdx + override this.OnComplete _ = + if first then + invalidArg "source" (SR.GetString(SR.notEnoughElements)) and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) @@ -1814,9 +1797,8 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- f.Invoke (this.Value._2, value) Unchecked.defaultof - interface SeqComposer.ISeqComponent with member this.OnComplete _ = - if (this:?>SeqComposer.Folder<'T, SeqComposer.Values>).Value._1 then + if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun reduced -> reduced.Value._2 @@ -2233,9 +2215,8 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- this.Value._2 + 1 Unchecked.defaultof - interface SeqComposer.ISeqComponent with member this.OnComplete _ = - if (this:?>SeqComposer.Folder<'a, SeqComposer.Values<'a, int>>).Value._2 = 0 then + if this.Value._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun total -> LanguagePrimitives.DivideByInt< ^a> total.Value._1 total.Value._2 @@ -2248,9 +2229,9 @@ namespace Microsoft.FSharp.Collections this.Value._1 <- Checked.(+) this.Value._1 (f value) this.Value._2 <- this.Value._2 + 1 Unchecked.defaultof - interface SeqComposer.ISeqComponent with + member this.OnComplete _ = - if (this:?>SeqComposer.Folder<'T,SeqComposer.Values<'U, int>>).Value._2 = 0 then + if this.Value._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.Value._1 total.Value._2 @@ -2267,9 +2248,8 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value Unchecked.defaultof - interface SeqComposer.ISeqComponent with member this.OnComplete _ = - if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun min -> min.Value._2 @@ -2291,9 +2271,8 @@ namespace Microsoft.FSharp.Collections | _ -> () Unchecked.defaultof - interface SeqComposer.ISeqComponent with member this.OnComplete _ = - if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun min -> min.Value._3 @@ -2327,9 +2306,8 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value Unchecked.defaultof - interface SeqComposer.ISeqComponent with member this.OnComplete _ = - if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun max -> max.Value._2 @@ -2351,9 +2329,8 @@ namespace Microsoft.FSharp.Collections | _ -> () Unchecked.defaultof - interface SeqComposer.ISeqComponent with member this.OnComplete _ = - if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun min -> min.Value._3 @@ -2467,14 +2444,12 @@ namespace Microsoft.FSharp.Collections this.Value._3 <- true halt () Unchecked.defaultof - interface SeqComposer.ISeqComponent with + member this.OnComplete _ = - let value = (this:?>SeqComposer.Folder<'T,SeqComposer.Values>) - if value.Value._1 then + if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - elif value.Value._3 then - invalidArg "source" (SR.GetString(SR.inputSequenceTooLong)) - }) + elif this.Value._3 then + invalidArg "source" (SR.GetString(SR.inputSequenceTooLong)) }) |> fun one -> one.Value._2 [] diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index d4ad0b51e0b..e6c311d43e1 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -22,34 +22,30 @@ namespace Microsoft.FSharp.Collections [] type SeqConsumer<'T,'U> = - new : unit -> SeqConsumer<'T,'U> - abstract ProcessNext : input:'T -> bool interface ISeqComponent + new : unit -> SeqConsumer<'T,'U> + abstract member ProcessNext : input:'T -> bool + abstract member OnComplete : PipeIdx -> unit + abstract member OnDispose : unit -> unit [] type Values<'a,'b> = - struct new : a:'a * b:'b -> Values<'a,'b> val mutable _1: 'a val mutable _2: 'b - end [] type Values<'a,'b,'c> = - struct new : a:'a * b:'b * c:'c -> Values<'a,'b,'c> val mutable _1: 'a val mutable _2: 'b val mutable _3: 'c - end [] type Folder<'T,'U> = - class inherit SeqConsumer<'T,'T> new : init:'U -> Folder<'T,'U> val mutable Value: 'U - end [] type SeqEnumerable<'T> = From 8755d36494f80f057f375c425e2dd1b63c2cd0d1 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 26 Oct 2016 20:24:17 +1100 Subject: [PATCH 107/286] Starting to finalise namespacing and comments Still playing around, happy for some input here... --- src/fsharp/FSharp.Core/seq.fs | 383 +++++++++++++++++---------------- src/fsharp/FSharp.Core/seq.fsi | 99 +++++---- 2 files changed, 255 insertions(+), 227 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index f816379be64..6617485d729 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -448,74 +448,79 @@ namespace Microsoft.FSharp.Collections [] [] module Seq = - module SeqComposer = + module Composer = open IEnumerator - type PipeIdx = int - type ``PipeIdx?`` = Nullable - let emptyPipeIdx = Nullable () - let inline getPipeIdx (maybePipeIdx:``PipeIdx?``) = if maybePipeIdx.HasValue then maybePipeIdx.Value else 1 - let inline makePipeIdx (pipeIdx:PipeIdx) = Nullable pipeIdx + module Internal = + type PipeIdx = int + type ``PipeIdx?`` = Nullable + let emptyPipeIdx = Nullable () + let inline getPipeIdx (maybePipeIdx:``PipeIdx?``) = if maybePipeIdx.HasValue then maybePipeIdx.Value else 1 + let inline makePipeIdx (pipeIdx:PipeIdx) = Nullable pipeIdx - type ISeqComponent = - abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit + type ICompletionChaining = + abstract OnComplete : PipeIdx -> unit + abstract OnDispose : unit -> unit - type ISeqPipeline = - abstract StopFurtherProcessing : PipeIdx -> unit + type IPipeline = + abstract StopFurtherProcessing : PipeIdx -> unit - [] - type SeqConsumer<'T,'U> () = - abstract ProcessNext : input:'T -> bool + [] + type Consumer<'T,'U> () = + abstract ProcessNext : input:'T -> bool + + abstract OnComplete : PipeIdx -> unit + abstract OnDispose : unit -> unit - abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit + default __.OnComplete _ = () + default __.OnDispose () = () - default __.OnComplete _ = () - default __.OnDispose () = () + interface ICompletionChaining with + member this.OnComplete terminatingIdx = + this.OnComplete terminatingIdx - interface ISeqComponent with - member this.OnComplete terminatingIdx = this.OnComplete terminatingIdx - member this.OnDispose () = - try this.OnDispose () - finally () + member this.OnDispose () = + try this.OnDispose () + finally () - [] - type Values<'a,'b> = - val mutable _1 : 'a - val mutable _2 : 'b + [] + type Values<'a,'b> = + val mutable _1 : 'a + val mutable _2 : 'b - new (a:'a, b: 'b) = { - _1 = a - _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 + [] + 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 - } + new (a:'a, b:'b, c:'c) = { + _1 = a + _2 = b + _3 = c + } - [] - type Folder<'T, 'U> = - inherit SeqConsumer<'T,'T> + [] + type Folder<'T, 'U> = + inherit Consumer<'T,'T> - val mutable Value : 'U + val mutable Value : 'U - new (init) = { - inherit SeqConsumer<'T,'T>() - Value = init - } + new (init) = { + inherit Consumer<'T,'T>() + Value = init + } + + [] + type SeqEnumerable<'T>() = + abstract member ForEach<'a when 'a :> Consumer<'T,'T>> : f:((unit->unit)->'a) -> 'a - [] - type SeqEnumerable<'T>() = - abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:((unit->unit)->'a) -> 'a + open Internal module Helpers = // used for performance reasons; these are not recursive calls, so should be safe @@ -528,10 +533,10 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) + let inline upcastISeqComponent (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = - abstract Create<'V> : ISeqPipeline -> ``PipeIdx?`` -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> + abstract Create<'V> : IPipeline -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) @@ -540,7 +545,7 @@ namespace Microsoft.FSharp.Collections and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>, secondPipeIdx:PipeIdx) = inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) - override this.Create<'W> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'V,'W>) : SeqConsumer<'T,'W> = + override this.Create<'W> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = first.Create result pipeIdx (second.Create result (makePipeIdx secondPipeIdx) next) static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = @@ -548,23 +553,23 @@ namespace Microsoft.FSharp.Collections and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Choose (filter, next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) and DistinctFactory<'T when 'T: equality> () = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Distinct (next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = match next with | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter | _ -> upcast Filter (filter, next) @@ -572,79 +577,79 @@ namespace Microsoft.FSharp.Collections and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () static let singleton = IdentityFactory<'T>() - override __.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = next + override __.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next static member IdentityFactory = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = match next with | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map | _ -> upcast Map<_,_,_> (map, next) and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next, getPipeIdx pipeIdx) + override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, result, next, getPipeIdx pipeIdx) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = inherit SeqComponentFactory<'Second,'U> () - override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next, getPipeIdx pipeIdx) + override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, result, next, getPipeIdx pipeIdx) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, getPipeIdx pipeIdx) + override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, getPipeIdx pipeIdx) and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next, getPipeIdx pipeIdx) + override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, result, next, getPipeIdx pipeIdx) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T*'T,'V>) : SeqConsumer<'T,'V> = upcast Pairwise (next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = inherit SeqComponentFactory<'T,'State> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'State,'V>) : SeqConsumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Skip (count, next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next, getPipeIdx pipeIdx) + override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, result, next, getPipeIdx pipeIdx) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Take (count, result, next, getPipeIdx pipeIdx) + override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, result, next, getPipeIdx pipeIdx) and TailFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next, getPipeIdx pipeIdx) + override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, result, next, getPipeIdx pipeIdx) - and [] SeqComponent<'T,'U> (next:ISeqComponent) = - inherit SeqConsumer<'T,'U>() + and [] SeqComponent<'T,'U> (next:ICompletionChaining) = + inherit Consumer<'T,'U>() - // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip + // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip // and it can only do it at the start of a sequence abstract Skipping : unit -> bool abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> - interface ISeqComponent with + interface ICompletionChaining with member this.OnComplete terminatingIdx = this.OnComplete terminatingIdx next.OnComplete terminatingIdx @@ -657,7 +662,7 @@ namespace Microsoft.FSharp.Collections default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) - and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqConsumer<'U,'V>) = + and Choose<'T,'U,'V> (choose:'T->option<'U>, next:Consumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -665,7 +670,7 @@ namespace Microsoft.FSharp.Collections | Some value -> Helpers.avoidTailCall (next.ProcessNext value) | None -> false - and Distinct<'T,'V when 'T: equality> (next:SeqConsumer<'T,'V>) = + and Distinct<'T,'V when 'T: equality> (next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) @@ -676,7 +681,7 @@ namespace Microsoft.FSharp.Collections else false - and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqConsumer<'T,'V>) = + and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) @@ -687,7 +692,7 @@ namespace Microsoft.FSharp.Collections else false - and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqConsumer<'T,'V>) = + and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) @@ -698,7 +703,7 @@ namespace Microsoft.FSharp.Collections else false - and Filter<'T,'V> (filter:'T->bool, next:SeqConsumer<'T,'V>) = + and Filter<'T,'V> (filter:'T->bool, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) @@ -709,7 +714,7 @@ namespace Microsoft.FSharp.Collections else false - and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqConsumer<'U,'V>) = + and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:Consumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -718,7 +723,7 @@ namespace Microsoft.FSharp.Collections else false - and Map<'T,'U,'V> (map:'T->'U, next:SeqConsumer<'U,'V>) = + and Map<'T,'U,'V> (map:'T->'U, next:Consumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) @@ -726,7 +731,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -742,7 +747,7 @@ namespace Microsoft.FSharp.Collections override __.OnDispose () = input2.Dispose () - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'Second,'V>(next) let input1 = enumerable1.GetEnumerator () @@ -758,7 +763,7 @@ namespace Microsoft.FSharp.Collections override __.OnDispose () = input1.Dispose () - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -776,7 +781,7 @@ namespace Microsoft.FSharp.Collections try input2.Dispose () finally input3.Dispose () - and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqConsumer<'U,'V>) = + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:Consumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -786,7 +791,7 @@ namespace Microsoft.FSharp.Collections else false - and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqConsumer<'U,'V>) = + and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:Consumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) let mutable idx = 0 @@ -796,7 +801,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let mutable idx = 0 @@ -814,7 +819,7 @@ namespace Microsoft.FSharp.Collections override __.OnDispose () = input2.Dispose () - and Pairwise<'T,'V> (next:SeqConsumer<'T*'T,'V>) = + and Pairwise<'T,'V> (next:Consumer<'T*'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable isFirst = true @@ -830,7 +835,7 @@ namespace Microsoft.FSharp.Collections lastValue <- input Helpers.avoidTailCall (next.ProcessNext currentPair) - and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:SeqConsumer<'State,'V>) = + and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:Consumer<'State,'V>) = inherit SeqComponent<'T,'V>(next) let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -840,7 +845,7 @@ namespace Microsoft.FSharp.Collections foldResult <- f.Invoke(foldResult, input) Helpers.avoidTailCall (next.ProcessNext foldResult) - and Skip<'T,'V> (skipCount:int, next:SeqConsumer<'T,'V>) = + and Skip<'T,'V> (skipCount:int, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -865,7 +870,7 @@ namespace Microsoft.FSharp.Collections invalidOpFmt "tried to skip {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>) = + and SkipWhile<'T,'V> (predicate:'T->bool, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable skip = true @@ -880,7 +885,7 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineIdx:int) = + and Take<'T,'V> (takeCount:int, result:IPipeline, next:Consumer<'T,'V>, pipelineIdx:int) = inherit Truncate<'T, 'V>(takeCount, result, next, pipelineIdx) override this.OnComplete terminatingIdx = @@ -889,7 +894,7 @@ namespace Microsoft.FSharp.Collections invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipeIdx:int) = + and TakeWhile<'T,'V> (predicate:'T->bool, result:IPipeline, next:Consumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -899,7 +904,7 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing pipeIdx false - and Tail<'T, 'V> (next:SeqConsumer<'T,'V>) = + and Tail<'T, 'V> (next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable first = true @@ -915,7 +920,7 @@ namespace Microsoft.FSharp.Collections if first then invalidArg "source" (SR.GetString(SR.notEnoughElements)) - and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipeIdx:int) = + and Truncate<'T,'V> (truncateCount:int, result:IPipeline, next:Consumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -944,12 +949,12 @@ namespace Microsoft.FSharp.Collections member val SeqState = SeqProcessNextStates.NotStarted with get, set member __.HaltedIdx = haltedIdx - interface ISeqPipeline with + interface IPipeline with member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx // SetResult<> is used at the end of the chain of SeqComponents to assign the final value type SetResult<'T> (result:Result<'T>) = - inherit SeqConsumer<'T,'T>() + inherit Consumer<'T,'T>() override __.ProcessNext (input:'T) : bool = result.Current <- input @@ -957,22 +962,22 @@ namespace Microsoft.FSharp.Collections type Pipeline() = let mutable haltedIdx = 0 - interface ISeqPipeline with member x.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx + interface IPipeline with member x.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx member __.HaltedIdx = haltedIdx module ForEach = - let enumerable (enumerable:IEnumerable<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let enumerable (enumerable:IEnumerable<'T>) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = use enumerator = enumerable.GetEnumerator () while (pipeline.HaltedIdx = 0) && (enumerator.MoveNext ()) do consumer.ProcessNext enumerator.Current |> ignore - let array (array:array<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let array (array:array<'T>) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = let mutable idx = 0 while (pipeline.HaltedIdx = 0) && (idx < array.Length) do consumer.ProcessNext array.[idx] |> ignore idx <- idx + 1 - let list (alist:list<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let list (alist:list<'T>) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = let rec iterate lst = match pipeline.HaltedIdx, lst with | 0, hd :: tl -> @@ -981,7 +986,7 @@ namespace Microsoft.FSharp.Collections | _ -> () iterate alist - let unfold (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let unfold (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = let rec iterate current = match pipeline.HaltedIdx, generator current with | 0, Some (item, next) -> @@ -991,12 +996,12 @@ namespace Microsoft.FSharp.Collections iterate state - let makeIsSkipping (consumer:SeqConsumer<'T,'U>) = + let makeIsSkipping (consumer:Consumer<'T,'U>) = match consumer with | :? SeqComponent<'T,'U> as c -> c.Skipping | _ -> fun () -> false - let init f (terminatingIdx:int) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let init f (terminatingIdx:int) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = let mutable idx = -1 let isSkipping = makeIsSkipping consumer let mutable maybeSkipping = true @@ -1009,9 +1014,9 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 - let execute (f:(unit->unit)->#SeqConsumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = + let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = let pipeline = Pipeline() - let result = f (fun () -> (pipeline:>ISeqPipeline).StopFurtherProcessing (current.PipeIdx+1)) + let result = f (fun () -> (pipeline:>IPipeline).StopFurtherProcessing (current.PipeIdx+1)) let consumer = current.Create pipeline emptyPipeIdx result try executeOn pipeline consumer @@ -1037,7 +1042,7 @@ namespace Microsoft.FSharp.Collections static member Element = element [] - type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) = + type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ICompletionChaining) = interface IDisposable with member __.Dispose() : unit = seqComponent.OnDispose () @@ -1074,7 +1079,7 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" - and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqConsumer<'T,'U>, result:Result<'U>) = + and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, seqComponent) let rec moveNext () = @@ -1111,7 +1116,7 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.enumerable enumerable) and ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = @@ -1163,7 +1168,7 @@ namespace Microsoft.FSharp.Collections override this.Append source = Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) - override this.ForEach (f:(unit->unit)->#SeqConsumer<'T,'T>) = + override this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) and ConcatEnumerable<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = @@ -1176,14 +1181,14 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(this, next)) - override this.ForEach (f:(unit->unit)->#SeqConsumer<'T,'T>) = + override this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) let create enumerable current = Helpers.upcastEnumerable (Enumerable(enumerable, current)) module Array = - type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:SeqConsumer<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable idx = 0 @@ -1225,7 +1230,7 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = @@ -1241,7 +1246,7 @@ namespace Microsoft.FSharp.Collections create array IdentityFactory.IdentityFactory module List = - type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqConsumer<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U>(alist:list<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable list = alist @@ -1275,14 +1280,14 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.list alist) let create alist current = Helpers.upcastEnumerable (Enumerable(alist, current)) module Unfold = - type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:SeqConsumer<'T,'U>, signal:Result<'U>) = + type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, signal:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) let mutable current = state @@ -1313,7 +1318,7 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.unfold generator state) module Init = @@ -1338,7 +1343,7 @@ namespace Microsoft.FSharp.Collections else System.Int32.MaxValue - type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqConsumer<'T,'U>, signal:Result<'U>) = + type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:Consumer<'T,'U>, signal:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) let isSkipping = @@ -1388,7 +1393,7 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) - override this.ForEach (createResult:(unit->unit)->#SeqConsumer<'U,'U>) = + override this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = let terminatingIdx = getTerminatingIdx count ForEach.execute createResult current (ForEach.init f terminatingIdx) @@ -1455,7 +1460,7 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) - override this.ForEach (f:(unit->unit)->#SeqConsumer<'T,'T>) = + override this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable (Helpers.upcastEnumerable this)) #if FX_NO_ICLONEABLE @@ -1469,13 +1474,13 @@ namespace Microsoft.FSharp.Collections let inline indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) [] - let toComposer (source:seq<'T>): SeqComposer.SeqEnumerable<'T> = + let toComposer (source:seq<'T>): Composer.Internal.SeqEnumerable<'T> = checkNonNull "source" source match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast s - | :? array<'T> as a -> upcast SeqComposer.Array.Enumerable((fun () -> a), SeqComposer.IdentityFactory.IdentityFactory) - | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, SeqComposer.IdentityFactory.IdentityFactory) - | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory.IdentityFactory) + | :? Composer.Enumerable.EnumerableBase<'T> as s -> upcast s + | :? array<'T> as a -> upcast Composer.Array.Enumerable((fun () -> a), Composer.IdentityFactory.IdentityFactory) + | :? list<'T> as a -> upcast Composer.List.Enumerable(a, Composer.IdentityFactory.IdentityFactory) + | _ -> upcast Composer.Enumerable.Enumerable<'T,'T>(source, Composer.IdentityFactory.IdentityFactory) let inline foreach f (source:seq<_>) = source @@ -1487,26 +1492,26 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : seq<'T> = - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Unfold.Enumerable<'T,'T,'State>(generator, state, SeqComposer.IdentityFactory.IdentityFactory)) + Composer.Helpers.upcastEnumerable (new Composer.Unfold.Enumerable<'T,'T,'State>(generator, state, Composer.IdentityFactory.IdentityFactory)) [] let empty<'T> = (EmptyEnumerable :> seq<'T>) [] let initInfinite<'T> (f:int->'T) : IEnumerable<'T> = - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable (), f)) + Composer.Helpers.upcastEnumerable (new Composer.Init.EnumerableDecider<'T>(Nullable (), f)) [] let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> = if count < 0 then invalidArgInputMustBeNonNegative "count" count elif count = 0 then empty else - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable count, f)) + Composer.Helpers.upcastEnumerable (new Composer.Init.EnumerableDecider<'T>(Nullable count, f)) [] let iter f (source : seq<'T>) = source |> foreach (fun _ -> - { new SeqComposer.SeqConsumer<'T,'T> () with + { new Composer.Internal.Consumer<'T,'T> () with override this.ProcessNext value = f value Unchecked.defaultof }) @@ -1524,7 +1529,7 @@ namespace Microsoft.FSharp.Collections if i < 0 then None else source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, SeqComposer.Values>> (SeqComposer.Values<_, _> (0, None)) with + { new Composer.Internal.Folder<'T, Composer.Internal.Values>> (Composer.Internal.Values<_, _> (0, None)) with override this.ProcessNext value = if this.Value._1 = i then this.Value._2 <- Some value @@ -1542,7 +1547,7 @@ namespace Microsoft.FSharp.Collections let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) source |> foreach (fun _ -> - { new SeqComposer.Folder<'T, int> (0) with + { new Composer.Internal.Folder<'T, int> (0) with override this.ProcessNext value = f.Invoke(this.Value, value) this.Value <- this.Value + 1 @@ -1553,7 +1558,7 @@ namespace Microsoft.FSharp.Collections let exists f (source : seq<'T>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, bool> (false) with + { new Composer.Internal.Folder<'T, bool> (false) with override this.ProcessNext value = if f value then this.Value <- true @@ -1566,7 +1571,7 @@ namespace Microsoft.FSharp.Collections let inline contains element (source : seq<'T>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, bool> (false) with + { new Composer.Internal.Folder<'T, bool> (false) with override this.ProcessNext value = if element = value then this.Value <- true @@ -1579,7 +1584,7 @@ namespace Microsoft.FSharp.Collections let forall f (source : seq<'T>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, bool> (true) with + { new Composer.Internal.Folder<'T, bool> (true) with override this.ProcessNext value = if not (f value) then this.Value <- false @@ -1620,51 +1625,51 @@ namespace Microsoft.FSharp.Collections let private seqFactory createSeqComponent (source:seq<'T>) = checkNonNull "source" source match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose createSeqComponent - | :? array<'T> as a -> SeqComposer.Array.create a createSeqComponent - | :? list<'T> as a -> SeqComposer.List.create a createSeqComponent - | _ -> SeqComposer.Enumerable.create source createSeqComponent + | :? Composer.Enumerable.EnumerableBase<'T> as s -> s.Compose createSeqComponent + | :? array<'T> as a -> Composer.Array.create a createSeqComponent + | :? list<'T> as a -> Composer.List.create a createSeqComponent + | _ -> Composer.Enumerable.create source createSeqComponent [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = - source |> seqFactory (SeqComposer.FilterFactory f) + source |> seqFactory (Composer.FilterFactory f) [] let where f source = filter f source [] let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> = - source |> seqFactory (SeqComposer.MapFactory f) + source |> seqFactory (Composer.MapFactory f) [] let mapi f source = - source |> seqFactory (SeqComposer.MapiFactory f) + source |> seqFactory (Composer.MapiFactory f) [] let mapi2 f source1 source2 = checkNonNull "source2" source2 - source1 |> seqFactory (SeqComposer.Mapi2Factory (f, source2)) + source1 |> seqFactory (Composer.Mapi2Factory (f, source2)) [] let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = checkNonNull "source1" source1 match source1 with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2)) - | _ -> source2 |> seqFactory (SeqComposer.Map2SecondFactory (f, source1)) + | :? Composer.Enumerable.EnumerableBase<'T> as s -> s.Compose (Composer.Map2FirstFactory (f, source2)) + | _ -> source2 |> seqFactory (Composer.Map2SecondFactory (f, source1)) [] let map3 f source1 source2 source3 = checkNonNull "source2" source2 checkNonNull "source3" source3 - source1 |> seqFactory (SeqComposer.Map3Factory (f, source2, source3)) + source1 |> seqFactory (Composer.Map3Factory (f, source2, source3)) [] let choose f source = - source |> seqFactory (SeqComposer.ChooseFactory f) + source |> seqFactory (Composer.ChooseFactory f) [] let indexed source = - source |> seqFactory (SeqComposer.MapiFactory (fun i x -> i,x) ) + source |> seqFactory (Composer.MapiFactory (fun i x -> i,x) ) [] let zip source1 source2 = @@ -1683,7 +1688,7 @@ namespace Microsoft.FSharp.Collections let tryPick f (source : seq<'T>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, Option<'U>> (None) with + { new Composer.Internal.Folder<'T, Option<'U>> (None) with override this.ProcessNext value = match f value with | (Some _) as some -> @@ -1703,7 +1708,7 @@ namespace Microsoft.FSharp.Collections let tryFind f (source : seq<'T>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, Option<'T>> (None) with + { new Composer.Internal.Folder<'T, Option<'T>> (None) with override this.ProcessNext value = if f value then this.Value <- Some value @@ -1722,7 +1727,7 @@ namespace Microsoft.FSharp.Collections if count < 0 then invalidArgInputMustBeNonNegative "count" count (* Note: don't create or dispose any IEnumerable if n = 0 *) if count = 0 then empty else - source |> seqFactory (SeqComposer.TakeFactory count) + source |> seqFactory (Composer.TakeFactory count) [] let isEmpty (source : seq<'T>) = @@ -1738,7 +1743,7 @@ namespace Microsoft.FSharp.Collections [] let concat (sources:seq<#seq<'T>>) : seq<'T> = checkNonNull "sources" sources - upcast SeqComposer.Enumerable.ConcatEnumerable sources + upcast Composer.Enumerable.ConcatEnumerable sources [] let length (source : seq<'T>) = @@ -1760,7 +1765,7 @@ namespace Microsoft.FSharp.Collections source |> foreach (fun _ -> - { new SeqComposer.Folder<'T,'State> (x) with + { new Composer.Internal.Folder<'T,'State> (x) with override this.ProcessNext value = this.Value <- f.Invoke (this.Value, value) Unchecked.defaultof }) @@ -1788,7 +1793,7 @@ namespace Microsoft.FSharp.Collections source |> foreach (fun _ -> - { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with + { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -1812,8 +1817,8 @@ namespace Microsoft.FSharp.Collections checkNonNull "source1" source1 checkNonNull "source2" source2 match source1 with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Append source2 - | _ -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Enumerable.AppendEnumerable<_>([source2; source1])) + | :? Composer.Enumerable.EnumerableBase<'T> as s -> s.Append source2 + | _ -> Composer.Helpers.upcastEnumerable (new Composer.Enumerable.AppendEnumerable<_>([source2; source1])) [] @@ -1851,7 +1856,7 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source : 'T array) = checkNonNull "source" source - SeqComposer.Array.createId source + Composer.Array.createId source [] let toArray (source : seq<'T>) = @@ -1905,17 +1910,17 @@ namespace Microsoft.FSharp.Collections [] let truncate n (source: seq<'T>) = if n <= 0 then empty else - source |> seqFactory (SeqComposer.TruncateFactory n) + source |> seqFactory (Composer.TruncateFactory n) [] let pairwise<'T> (source:seq<'T>) : seq<'T*'T> = - source |> seqFactory (SeqComposer.PairwiseFactory ()) + source |> seqFactory (Composer.PairwiseFactory ()) [] let scan<'T,'State> f (z:'State) (source : seq<'T>): seq<'State> = let first = [|z|] :> IEnumerable<'State> - let rest = source |> seqFactory (SeqComposer.ScanFactory (f, z)) - upcast SeqComposer.Enumerable.ConcatEnumerable [|first; rest;|] + let rest = source |> seqFactory (Composer.ScanFactory (f, z)) + upcast Composer.Enumerable.ConcatEnumerable [|first; rest;|] [] let tryFindBack f (source : seq<'T>) = @@ -1939,7 +1944,7 @@ namespace Microsoft.FSharp.Collections let tryFindIndex p (source:seq<_>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, SeqComposer.Values, int>> (SeqComposer.Values<_,_>(None, 0)) with + { new Composer.Internal.Folder<'T, Composer.Internal.Values, int>> (Composer.Internal.Values<_,_>(None, 0)) with override this.ProcessNext value = if p value then this.Value._1 <- Some(this.Value._2) @@ -2107,11 +2112,11 @@ namespace Microsoft.FSharp.Collections [] let distinct source = - source |> seqFactory (SeqComposer.DistinctFactory ()) + source |> seqFactory (Composer.DistinctFactory ()) [] let distinctBy keyf source = - source |> seqFactory (SeqComposer.DistinctByFactory keyf) + source |> seqFactory (Composer.DistinctByFactory keyf) [] let sortBy keyf source = @@ -2120,7 +2125,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceBy keyf array array - SeqComposer.Array.createDelayedId delayedSort + Composer.Array.createDelayedId delayedSort [] let sort source = @@ -2129,7 +2134,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlace array array - SeqComposer.Array.createDelayedId delayedSort + Composer.Array.createDelayedId delayedSort [] let sortWith f source = @@ -2138,7 +2143,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceWith f array array - SeqComposer.Array.createDelayedId delayedSort + Composer.Array.createDelayedId delayedSort [] let inline sortByDescending keyf source = @@ -2189,7 +2194,7 @@ namespace Microsoft.FSharp.Collections let inline sum (source:seq<'a>) : 'a = source |> foreach (fun _ -> - { new SeqComposer.Folder<'a,'a> (LanguagePrimitives.GenericZero) with + { new Composer.Internal.Folder<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value value Unchecked.defaultof }) @@ -2199,7 +2204,7 @@ namespace Microsoft.FSharp.Collections let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = source |> foreach (fun _ -> - { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + { new Composer.Internal.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value (f value) Unchecked.defaultof }) @@ -2209,7 +2214,7 @@ namespace Microsoft.FSharp.Collections let inline average (source: seq< ^a>) : ^a = source |> foreach (fun _ -> - { new SeqComposer.Folder<'a, SeqComposer.Values<'a, int>> (SeqComposer.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + { new Composer.Internal.Folder<'a, Composer.Internal.Values<'a, int>> (Composer.Internal.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 value this.Value._2 <- this.Value._2 + 1 @@ -2224,7 +2229,7 @@ namespace Microsoft.FSharp.Collections let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = source |> foreach (fun _ -> - { new SeqComposer.Folder<'T,SeqComposer.Values<'U, int>> (SeqComposer.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + { new Composer.Internal.Folder<'T,Composer.Internal.Values<'U, int>> (Composer.Internal.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 (f value) this.Value._2 <- this.Value._2 + 1 @@ -2239,7 +2244,7 @@ namespace Microsoft.FSharp.Collections let inline min (source: seq<_>) = source |> foreach (fun _ -> - { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with + { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2258,7 +2263,7 @@ namespace Microsoft.FSharp.Collections let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = source |> foreach (fun _ -> - { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with override this.ProcessNext value = match this.Value._1, f value with | true, valueU -> @@ -2297,7 +2302,7 @@ namespace Microsoft.FSharp.Collections let inline max (source: seq<_>) = source |> foreach (fun _ -> - { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with + { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2316,7 +2321,7 @@ namespace Microsoft.FSharp.Collections let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = source |> foreach (fun _ -> - { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with override this.ProcessNext value = match this.Value._1, f value with | true, valueU -> @@ -2354,15 +2359,15 @@ namespace Microsoft.FSharp.Collections *) [] let takeWhile p (source: seq<_>) = - source |> seqFactory (SeqComposer.TakeWhileFactory p) + source |> seqFactory (Composer.TakeWhileFactory p) [] let skip count (source: seq<_>) = - source |> seqFactory (SeqComposer.SkipFactory count) + source |> seqFactory (Composer.SkipFactory count) [] let skipWhile p (source: seq<_>) = - source |> seqFactory (SeqComposer.SkipWhileFactory p) + source |> seqFactory (Composer.SkipWhileFactory p) [] let forall2 p (source1: seq<_>) (source2: seq<_>) = @@ -2392,7 +2397,7 @@ namespace Microsoft.FSharp.Collections let tryHead (source : seq<_>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, Option<'T>> (None) with + { new Composer.Internal.Folder<'T, Option<'T>> (None) with override this.ProcessNext value = this.Value <- Some value halt () @@ -2407,13 +2412,13 @@ namespace Microsoft.FSharp.Collections [] let tail (source: seq<'T>) = - source |> seqFactory (SeqComposer.TailFactory ()) + source |> seqFactory (Composer.TailFactory ()) [] let tryLast (source : seq<_>) = source |> foreach (fun _ -> - { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values(true, Unchecked.defaultof<'T>)) with + { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2435,7 +2440,7 @@ namespace Microsoft.FSharp.Collections let exactlyOne (source : seq<_>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values(true, Unchecked.defaultof<'T>, false)) with + { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values(true, Unchecked.defaultof<'T>, false)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2459,7 +2464,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.Reverse array array - SeqComposer.Array.createDelayedId delayedReverse + Composer.Array.createDelayedId delayedReverse [] let permute f (source:seq<_>) = @@ -2468,7 +2473,7 @@ namespace Microsoft.FSharp.Collections source |> toArray |> Array.permute f - SeqComposer.Array.createDelayedId delayedPermute + Composer.Array.createDelayedId delayedPermute [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = @@ -2486,7 +2491,7 @@ namespace Microsoft.FSharp.Collections [] let except (itemsToExclude: seq<'T>) (source: seq<'T>) = checkNonNull "itemsToExclude" itemsToExclude - source |> seqFactory (SeqComposer.ExceptFactory itemsToExclude) + source |> seqFactory (Composer.ExceptFactory itemsToExclude) [] let chunkBySize chunkSize (source : seq<_>) = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index e6c311d43e1..27f44c0382a 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -13,43 +13,66 @@ namespace Microsoft.FSharp.Collections [] [] module Seq = - module SeqComposer = - type PipeIdx = int - - type ISeqComponent = - abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit - - [] - type SeqConsumer<'T,'U> = - interface ISeqComponent - new : unit -> SeqConsumer<'T,'U> - abstract member ProcessNext : input:'T -> bool - abstract member OnComplete : PipeIdx -> unit - abstract member OnDispose : unit -> unit - - [] - type Values<'a,'b> = - new : a:'a * b:'b -> Values<'a,'b> - val mutable _1: 'a - val mutable _2: 'b - - [] - 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 - - [] - type Folder<'T,'U> = - inherit SeqConsumer<'T,'T> - new : init:'U -> Folder<'T,'U> - val mutable Value: 'U - - [] - type SeqEnumerable<'T> = - abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:((unit->unit)->'a) -> 'a + module Composer = + module Internal = + /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the + /// source of the chain. + type PipeIdx = int + + /// ICompletionChaining is used to correctly handle cleaning up of the pipeline. A + /// base implementation is provided in Consumer, and should not be overwritten. Consumer + /// provides it's own OnComplete and OnDispose function which should be used to handle + /// a particular consumers cleanup. + type ICompletionChaining = + /// OnComplete is used to determine if the object has been processed correctly, + /// and possibly throw exceptions to denote incorrect application (i.e. such as a Take + /// operation which didn't have a source at least as large as was required). It is + /// not called in the case of an exception being thrown whilst the stream is still + /// being processed. + abstract OnComplete : PipeIdx -> unit + /// OnDispose is used to cleanup the stream. It is always called at the last operation + /// after the enumeration has completed. + abstract OnDispose : unit -> unit + + /// Consumer is the base class of all elements within the pipeline + [] + type Consumer<'T,'U> = + interface ICompletionChaining + new : unit -> Consumer<'T,'U> + abstract member ProcessNext : input:'T -> bool + abstract member OnComplete : PipeIdx -> unit + abstract member OnDispose : unit -> unit + + /// 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 + + /// 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 ForEach function. + [] + type Folder<'T,'U> = + inherit Consumer<'T,'T> + new : init:'U -> Folder<'T,'U> + val mutable Value: 'U + + /// SeqEnumerable functions provide the enhance seq experience + [] + type SeqEnumerable<'T> = + abstract member ForEach<'a when 'a :> Consumer<'T,'T>> : f:((unit->unit)->'a) -> 'a /// Returns a new sequence that contains the cartesian product of the two input sequences. /// The first sequence. @@ -1242,7 +1265,7 @@ namespace Microsoft.FSharp.Collections /// /// Thrown when the input sequence is null. [] - val toComposer : source:seq<'T> -> SeqComposer.SeqEnumerable<'T> + val toComposer : source:seq<'T> -> Composer.Internal.SeqEnumerable<'T> /// Builds a list from the given collection. /// From 85a601dd68b4467cad5e61d6de857570dbc2c831 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 26 Oct 2016 22:09:06 -0400 Subject: [PATCH 108/286] seq.comparewith --- src/fsharp/FSharp.Core/seq.fs | 42 ++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 6617485d729..f2f3134bc9d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1826,22 +1826,38 @@ namespace Microsoft.FSharp.Collections [] let compareWith (f:'T -> 'T -> int) (source1 : seq<'T>) (source2: seq<'T>) = - checkNonNull "source1" source1 checkNonNull "source2" source2 - use e1 = source1.GetEnumerator() + use e2 = source2.GetEnumerator() let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let rec go () = - let e1ok = e1.MoveNext() - let e2ok = e2.MoveNext() - let c = if e1ok = e2ok then 0 else if e1ok then 1 else -1 - if c <> 0 then c else - if not e1ok || not e2ok then 0 - else - let c = f.Invoke(e1.Current, e2.Current) - if c <> 0 then c else - go () - go() + let mutable e2ok = Unchecked.defaultof + + source1 + |> foreach (fun halt -> + { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values<_,_>(false, 0)) with + override this.ProcessNext value = + e2ok <- e2.MoveNext() + if not e2ok then + this.Value._1 <- true + this.Value._2 <- 1 + halt () + else + let c = f.Invoke(value, e2.Current) + if c <> 0 then + this.Value._1 <- true + this.Value._2 <- c + halt () + Unchecked.defaultof + member this.OnComplete _ = + if not this.Value._1 then + e2ok <- e2.MoveNext() + if e2ok then + this.Value._2 <- -1 + else + this.Value._2 <- 0 + + }) + |> fun compare -> compare.Value._2 [] let ofList (source : 'T list) = From 4567bd886dabb25b3d5cf8c37d2f33cff6acf816 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 27 Oct 2016 17:49:21 +1100 Subject: [PATCH 109/286] More compact Seq.compareWith Bit faster on 64 bit, as don't need to access the ref of e2ok --- src/fsharp/FSharp.Core/seq.fs | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index f2f3134bc9d..d6b2256ebb5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1830,34 +1830,24 @@ namespace Microsoft.FSharp.Collections use e2 = source2.GetEnumerator() let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let mutable e2ok = Unchecked.defaultof source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values<_,_>(false, 0)) with + { new Composer.Internal.Folder<'T,bool> (0) with override this.ProcessNext value = - e2ok <- e2.MoveNext() - if not e2ok then - this.Value._1 <- true - this.Value._2 <- 1 + if not (e2.MoveNext()) then + this.Value <- 1 halt () else - let c = f.Invoke(value, e2.Current) + let c = f.Invoke (value, e2.Current) if c <> 0 then - this.Value._1 <- true - this.Value._2 <- c + this.Value <- c halt () Unchecked.defaultof member this.OnComplete _ = - if not this.Value._1 then - e2ok <- e2.MoveNext() - if e2ok then - this.Value._2 <- -1 - else - this.Value._2 <- 0 - - }) - |> fun compare -> compare.Value._2 + if this.Value = 0 && e2.MoveNext() then + this.Value <- -1 }) + |> fun compare -> compare.Value [] let ofList (source : 'T list) = From cf40d87a240fcc1e018fa3fad25214c842458d60 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 27 Oct 2016 18:59:23 +1100 Subject: [PATCH 110/286] oops, type-o ! --- src/fsharp/FSharp.Core/seq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index d6b2256ebb5..c0cf1e67719 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1833,7 +1833,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<'T,bool> (0) with + { new Composer.Internal.Folder<'T,int> (0) with override this.ProcessNext value = if not (e2.MoveNext()) then this.Value <- 1 From ff4b2f24bf45a5809890b5e6e2dd905c0c949b13 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 13:17:25 +1100 Subject: [PATCH 111/286] Minimalist exposure of factory infrastructire - made SeqEnumerable<> into an interface (ISeq<>) - made SeqComponentFactory<> into an interface (ISeqFactory<>) --- src/fsharp/FSharp.Core/seq.fs | 230 +++++++++++++++++++-------------- src/fsharp/FSharp.Core/seq.fsi | 18 ++- 2 files changed, 147 insertions(+), 101 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index c0cf1e67719..d85be99f679 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -516,9 +516,14 @@ namespace Microsoft.FSharp.Collections Value = init } - [] - type SeqEnumerable<'T>() = - abstract member ForEach<'a when 'a :> Consumer<'T,'T>> : f:((unit->unit)->'a) -> 'a + type ISeqFactory<'T,'U> = + abstract PipeIdx : PipeIdx + abstract Create<'V> : IPipeline -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> + + type ISeq<'T> = + inherit IEnumerable<'T> + abstract member Compose<'U> : (ISeqFactory<'T,'U>) -> ISeq<'U> + abstract member ForEach<'consumer when 'consumer :> Consumer<'T,'T>> : f:((unit->unit)->'consumer) -> 'consumer open Internal @@ -530,114 +535,136 @@ 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 upcastSeq (t:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) let inline upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastISeqComponent (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = - abstract Create<'V> : IPipeline -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> - new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) - member __.PipeIdx = getPipeIdx pipeIdx + interface ISeqFactory<'T,'U> with + member __.PipeIdx = getPipeIdx pipeIdx + member __.Create _ _ _ = failwith "library implementation error: Create on base factory should not be called" - and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>, secondPipeIdx:PipeIdx) = + and ComposedFactory<'T,'U,'V> private (first:ISeqFactory<'T,'U>, second:ISeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) - override this.Create<'W> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = - first.Create result pipeIdx (second.Create result (makePipeIdx secondPipeIdx) next) + interface ISeqFactory<'T,'V> with + member this.Create<'W> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = + first.Create result pipeIdx (second.Create result (makePipeIdx secondPipeIdx) next) - static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = + static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = upcast ComposedFactory(first, second, first.PipeIdx+1) and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) + interface ISeqFactory<'T,'U> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) and DistinctFactory<'T when 'T: equality> () = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = - match next with - | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter - | _ -> upcast Filter (filter, next) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = + match next with + | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter + | _ -> upcast Filter (filter, next) and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () static let singleton = IdentityFactory<'T>() - override __.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next + interface ISeqFactory<'T,'T> with + member __.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next static member IdentityFactory = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = - match next with - | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map - | _ -> upcast Map<_,_,_> (map, next) + interface ISeqFactory<'T,'U> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = + match next with + | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map + | _ -> upcast Map<_,_,_> (map, next) and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, result, next, getPipeIdx pipeIdx) + interface ISeqFactory<'First,'U> with + member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, result, next, getPipeIdx pipeIdx) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = inherit SeqComponentFactory<'Second,'U> () - override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, result, next, getPipeIdx pipeIdx) + interface ISeqFactory<'Second,'U> with + member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, result, next, getPipeIdx pipeIdx) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, getPipeIdx pipeIdx) + interface ISeqFactory<'First,'U> with + member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, getPipeIdx pipeIdx) and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) + interface ISeqFactory<'T,'U> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, result, next, getPipeIdx pipeIdx) + interface ISeqFactory<'First,'U> with + member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, result, next, getPipeIdx pipeIdx) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) + interface ISeqFactory<'T,'T*'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = inherit SeqComponentFactory<'T,'State> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) + interface ISeqFactory<'T,'State> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, result, next, getPipeIdx pipeIdx) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, result, next, getPipeIdx pipeIdx) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, result, next, getPipeIdx pipeIdx) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, result, next, getPipeIdx pipeIdx) and TailFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, result, next, getPipeIdx pipeIdx) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, result, next, getPipeIdx pipeIdx) and [] SeqComponent<'T,'U> (next:ICompletionChaining) = inherit Consumer<'T,'U>() @@ -1014,7 +1041,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 - let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = + let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:ISeqFactory<'T,'U>) executeOn = let pipeline = Pipeline() let result = f (fun () -> (pipeline:>IPipeline).StopFurtherProcessing (current.PipeIdx+1)) let consumer = current.Create pipeline emptyPipeIdx result @@ -1062,9 +1089,9 @@ namespace Microsoft.FSharp.Collections | _ -> failwith "library implementation error: all states should have been handled" and [] EnumerableBase<'T> () = - inherit SeqEnumerable<'T>() + let derivedClassShouldImplement () = + failwith "library implementation error: derived class should implement (should be abstract)" - abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> default this.Append source = Helpers.upcastEnumerable (AppendEnumerable [this; source]) @@ -1076,8 +1103,11 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumeratorNonGeneric genericEnumerator interface IEnumerable<'T> with - member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" + member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () + interface ISeq<'T> with + member __.Compose _ = derivedClassShouldImplement () + member __.ForEach _ = derivedClassShouldImplement () and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, seqComponent) @@ -1105,7 +1135,7 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent seqComponent).OnDispose () - and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = + and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:ISeqFactory<'T,'U>) = inherit EnumerableBase<'U>() interface IEnumerable<'U> with @@ -1113,11 +1143,12 @@ namespace Microsoft.FSharp.Collections let result = Result<'U> () Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) - override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) + interface ISeq<'U> with + member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + Helpers.upcastSeq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.enumerable enumerable) + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.enumerable enumerable) and ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = let mutable state = SeqProcessNextStates.NotStarted @@ -1162,14 +1193,15 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () : IEnumerator<'T> = Helpers.upcastEnumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) - override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = - Helpers.upcastEnumerable (Enumerable<'T,'V>(this, next)) - override this.Append source = Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) - override this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) + interface ISeq<'T> with + member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + Helpers.upcastSeq (Enumerable<'T,'V>(this, next)) + + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) and ConcatEnumerable<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = inherit EnumerableBase<'T>() @@ -1178,14 +1210,15 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () : IEnumerator<'T> = Helpers.upcastEnumerator (new ConcatEnumerator<_,_> (sources)) - override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = - Helpers.upcastEnumerable (Enumerable<'T,'V>(this, next)) + interface ISeq<'T> with + member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + Helpers.upcastSeq (Enumerable<'T,'V>(this, next)) - override this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) let create enumerable current = - Helpers.upcastEnumerable (Enumerable(enumerable, current)) + Helpers.upcastSeq (Enumerable(enumerable, current)) module Array = type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = @@ -1219,7 +1252,7 @@ namespace Microsoft.FSharp.Collections initMoveNext () moveNext () - type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqComponentFactory<'T,'U>) = + type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:ISeqFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with @@ -1227,16 +1260,17 @@ namespace Microsoft.FSharp.Collections let result = Result<'U> () Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) + interface ISeq<'U> with + member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + Helpers.upcastSeq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.array (delayedArray ())) + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.array (delayedArray ())) - let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = - Helpers.upcastEnumerable (Enumerable(delayedArray, current)) + let createDelayed (delayedArray:unit->array<'T>) (current:ISeqFactory<'T,'U>) = + Helpers.upcastSeq (Enumerable(delayedArray, current)) - let create (array:array<'T>) (current:SeqComponentFactory<'T,'U>) = + let create (array:array<'T>) (current:ISeqFactory<'T,'U>) = createDelayed (fun () -> array) current let createDelayedId (delayedArray:unit -> array<'T>) = @@ -1269,7 +1303,7 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext list - type Enumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) = + type Enumerable<'T,'U>(alist:list<'T>, current:ISeqFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with @@ -1277,14 +1311,15 @@ namespace Microsoft.FSharp.Collections let result = Result<'U> () Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) + interface ISeq<'U> with + member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + Helpers.upcastSeq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.list alist) + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.list alist) let create alist current = - Helpers.upcastEnumerable (Enumerable(alist, current)) + Helpers.upcastSeq (Enumerable(alist, current)) module Unfold = type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, signal:Result<'U>) = @@ -1307,7 +1342,7 @@ namespace Microsoft.FSharp.Collections signal.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:SeqComponentFactory<'T,'U>) = + type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:ISeqFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with @@ -1315,11 +1350,12 @@ namespace Microsoft.FSharp.Collections let result = Result<'U> () Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) + interface ISeq<'U> with + member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + Helpers.upcastSeq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.unfold generator state) + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.unfold generator state) module Init = // The original implementation of "init" delayed the calculation of Current, and so it was possible @@ -1382,7 +1418,7 @@ namespace Microsoft.FSharp.Collections signal.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) = + type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:ISeqFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with @@ -1390,12 +1426,13 @@ namespace Microsoft.FSharp.Collections let result = Result<'U> () Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) + interface ISeq<'U> with + member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + Helpers.upcastSeq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) - override this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = - let terminatingIdx = getTerminatingIdx count - ForEach.execute createResult current (ForEach.init f terminatingIdx) + member this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = + let terminatingIdx = getTerminatingIdx count + ForEach.execute createResult current (ForEach.init f terminatingIdx) let upto lastOption f = match lastOption with @@ -1457,11 +1494,12 @@ namespace Microsoft.FSharp.Collections // in the way presented, but it's possible. upto (if count.HasValue then Some (count.Value-1) else None) f - override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = - Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) + interface ISeq<'T> with + member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + Helpers.upcastSeq (Enumerable<'T,'V>(count, f, next)) - override this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable (Helpers.upcastEnumerable this)) + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable (Helpers.upcastEnumerable this)) #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions @@ -1474,7 +1512,7 @@ namespace Microsoft.FSharp.Collections let inline indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) [] - let toComposer (source:seq<'T>): Composer.Internal.SeqEnumerable<'T> = + let toComposer (source:seq<'T>): Composer.Internal.ISeq<'T> = checkNonNull "source" source match source with | :? Composer.Enumerable.EnumerableBase<'T> as s -> upcast s @@ -1625,10 +1663,10 @@ namespace Microsoft.FSharp.Collections let private seqFactory createSeqComponent (source:seq<'T>) = checkNonNull "source" source match source with - | :? Composer.Enumerable.EnumerableBase<'T> as s -> s.Compose createSeqComponent - | :? array<'T> as a -> Composer.Array.create a createSeqComponent - | :? list<'T> as a -> Composer.List.create a createSeqComponent - | _ -> Composer.Enumerable.create source createSeqComponent + | :? Composer.Internal.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose createSeqComponent) + | :? array<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.Array.create a createSeqComponent) + | :? list<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.List.create a createSeqComponent) + | _ -> Composer.Helpers.upcastEnumerable (Composer.Enumerable.create source createSeqComponent) [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = @@ -1654,7 +1692,7 @@ namespace Microsoft.FSharp.Collections let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = checkNonNull "source1" source1 match source1 with - | :? Composer.Enumerable.EnumerableBase<'T> as s -> s.Compose (Composer.Map2FirstFactory (f, source2)) + | :? Composer.Internal.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose (Composer.Map2FirstFactory (f, source2))) | _ -> source2 |> seqFactory (Composer.Map2SecondFactory (f, source1)) [] @@ -1862,7 +1900,7 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source : 'T array) = checkNonNull "source" source - Composer.Array.createId source + Composer.Helpers.upcastEnumerable (Composer.Array.createId source) [] let toArray (source : seq<'T>) = @@ -2131,7 +2169,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceBy keyf array array - Composer.Array.createDelayedId delayedSort + Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedSort) [] let sort source = @@ -2140,7 +2178,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlace array array - Composer.Array.createDelayedId delayedSort + Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedSort) [] let sortWith f source = @@ -2149,7 +2187,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceWith f array array - Composer.Array.createDelayedId delayedSort + Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedSort) [] let inline sortByDescending keyf source = @@ -2470,7 +2508,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.Reverse array array - Composer.Array.createDelayedId delayedReverse + Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedReverse) [] let permute f (source:seq<_>) = @@ -2479,7 +2517,7 @@ namespace Microsoft.FSharp.Collections source |> toArray |> Array.permute f - Composer.Array.createDelayedId delayedPermute + Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedPermute) [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 27f44c0382a..3dbff6d01f1 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -18,6 +18,7 @@ namespace Microsoft.FSharp.Collections /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the /// source of the chain. type PipeIdx = int + type ``PipeIdx?`` = Nullable /// ICompletionChaining is used to correctly handle cleaning up of the pipeline. A /// base implementation is provided in Consumer, and should not be overwritten. Consumer @@ -34,6 +35,9 @@ namespace Microsoft.FSharp.Collections /// after the enumeration has completed. abstract OnDispose : unit -> unit + type IPipeline = + abstract StopFurtherProcessing : PipeIdx -> unit + /// Consumer is the base class of all elements within the pipeline [] type Consumer<'T,'U> = @@ -69,10 +73,14 @@ namespace Microsoft.FSharp.Collections new : init:'U -> Folder<'T,'U> val mutable Value: 'U - /// SeqEnumerable functions provide the enhance seq experience - [] - type SeqEnumerable<'T> = - abstract member ForEach<'a when 'a :> Consumer<'T,'T>> : f:((unit->unit)->'a) -> 'a + type ISeqFactory<'T,'U> = + abstract member Create : IPipeline -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> + abstract member PipeIdx : PipeIdx + + type ISeq<'T> = + inherit System.Collections.Generic.IEnumerable<'T> + abstract member Compose : ISeqFactory<'T,'U> -> ISeq<'U> + abstract member ForEach : f:((unit -> unit) -> 'a) -> 'a when 'a :> Consumer<'T,'T> /// Returns a new sequence that contains the cartesian product of the two input sequences. /// The first sequence. @@ -1265,7 +1273,7 @@ namespace Microsoft.FSharp.Collections /// /// Thrown when the input sequence is null. [] - val toComposer : source:seq<'T> -> Composer.Internal.SeqEnumerable<'T> + val toComposer : source:seq<'T> -> Composer.Internal.ISeq<'T> /// Builds a list from the given collection. /// From 9ecbf7a0dd7158eecc25df651a26a4f19a065f43 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 13:36:13 +1100 Subject: [PATCH 112/286] Renaming recommentations base on @rmunn feedback --- src/fsharp/FSharp.Core/seq.fs | 144 ++++++++++++++++----------------- src/fsharp/FSharp.Core/seq.fsi | 4 +- 2 files changed, 74 insertions(+), 74 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index d85be99f679..ebf6158d5c3 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -462,7 +462,7 @@ namespace Microsoft.FSharp.Collections abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit - type IPipeline = + type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit [] @@ -518,7 +518,7 @@ namespace Microsoft.FSharp.Collections type ISeqFactory<'T,'U> = abstract PipeIdx : PipeIdx - abstract Create<'V> : IPipeline -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> + abstract Create<'V> : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> type ISeq<'T> = inherit IEnumerable<'T> @@ -539,7 +539,7 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline upcastISeqComponent (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) + let inline upcastICompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) @@ -552,8 +552,8 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) interface ISeqFactory<'T,'V> with - member this.Create<'W> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = - first.Create result pipeIdx (second.Create result (makePipeIdx secondPipeIdx) next) + member this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = + first.Create outOfBand pipeIdx (second.Create outOfBand (makePipeIdx secondPipeIdx) next) static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = upcast ComposedFactory(first, second, first.PipeIdx+1) @@ -561,27 +561,27 @@ namespace Microsoft.FSharp.Collections and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () interface ISeqFactory<'T,'U> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) and DistinctFactory<'T when 'T: equality> () = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = match next with | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter | _ -> upcast Filter (filter, next) @@ -590,13 +590,13 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'T> () static let singleton = IdentityFactory<'T>() interface ISeqFactory<'T,'T> with - member __.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next + member __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next static member IdentityFactory = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () interface ISeqFactory<'T,'U> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = match next with | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map | _ -> upcast Map<_,_,_> (map, next) @@ -604,67 +604,67 @@ namespace Microsoft.FSharp.Collections and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () interface ISeqFactory<'First,'U> with - member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, result, next, getPipeIdx pipeIdx) + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, outOfBand, next, getPipeIdx pipeIdx) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = inherit SeqComponentFactory<'Second,'U> () interface ISeqFactory<'Second,'U> with - member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, result, next, getPipeIdx pipeIdx) + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, outOfBand, next, getPipeIdx pipeIdx) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () interface ISeqFactory<'First,'U> with - member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, getPipeIdx pipeIdx) + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, outOfBand, next, getPipeIdx pipeIdx) and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () interface ISeqFactory<'T,'U> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () interface ISeqFactory<'First,'U> with - member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, result, next, getPipeIdx pipeIdx) + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, outOfBand, next, getPipeIdx pipeIdx) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () interface ISeqFactory<'T,'T*'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = inherit SeqComponentFactory<'T,'State> () interface ISeqFactory<'T,'State> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, result, next, getPipeIdx pipeIdx) + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, outOfBand, next, getPipeIdx pipeIdx) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, result, next, getPipeIdx pipeIdx) + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, getPipeIdx pipeIdx) and TailFactory<'T> () = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, result, next, getPipeIdx pipeIdx) + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, getPipeIdx pipeIdx) and [] SeqComponent<'T,'U> (next:ICompletionChaining) = inherit Consumer<'T,'U>() @@ -758,7 +758,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -768,13 +768,13 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) else - result.StopFurtherProcessing pipeIdx + outOfBand.StopFurtherProcessing pipeIdx false override __.OnDispose () = input2.Dispose () - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'Second,'V>(next) let input1 = enumerable1.GetEnumerator () @@ -784,13 +784,13 @@ namespace Microsoft.FSharp.Collections if input1.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) else - result.StopFurtherProcessing pipeIdx + outOfBand.StopFurtherProcessing pipeIdx false override __.OnDispose () = input1.Dispose () - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -801,7 +801,7 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () && input3.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) else - result.StopFurtherProcessing pipeIdx + outOfBand.StopFurtherProcessing pipeIdx false override __.OnDispose () = @@ -828,7 +828,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let mutable idx = 0 @@ -840,7 +840,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) else - result.StopFurtherProcessing pipeIdx + outOfBand.StopFurtherProcessing pipeIdx false override __.OnDispose () = @@ -912,8 +912,8 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - and Take<'T,'V> (takeCount:int, result:IPipeline, next:Consumer<'T,'V>, pipelineIdx:int) = - inherit Truncate<'T, 'V>(takeCount, result, next, pipelineIdx) + and Take<'T,'V> (takeCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipelineIdx:int) = + inherit Truncate<'T, 'V>(takeCount, outOfBand, next, pipelineIdx) override this.OnComplete terminatingIdx = if terminatingIdx < pipelineIdx && this.Count < takeCount then @@ -921,14 +921,14 @@ namespace Microsoft.FSharp.Collections invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - and TakeWhile<'T,'V> (predicate:'T->bool, result:IPipeline, next:Consumer<'T,'V>, pipeIdx:int) = + and TakeWhile<'T,'V> (predicate:'T->bool, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = if predicate input then Helpers.avoidTailCall (next.ProcessNext input) else - result.StopFurtherProcessing pipeIdx + outOfBand.StopFurtherProcessing pipeIdx false and Tail<'T, 'V> (next:Consumer<'T,'V>) = @@ -947,7 +947,7 @@ namespace Microsoft.FSharp.Collections if first then invalidArg "source" (SR.GetString(SR.notEnoughElements)) - and Truncate<'T,'V> (truncateCount:int, result:IPipeline, next:Consumer<'T,'V>, pipeIdx:int) = + and Truncate<'T,'V> (truncateCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -958,10 +958,10 @@ namespace Microsoft.FSharp.Collections if count < truncateCount then count <- count + 1 if count = truncateCount then - result.StopFurtherProcessing pipeIdx + outOfBand.StopFurtherProcessing pipeIdx next.ProcessNext input else - result.StopFurtherProcessing pipeIdx + outOfBand.StopFurtherProcessing pipeIdx false type SeqProcessNextStates = @@ -976,7 +976,7 @@ namespace Microsoft.FSharp.Collections member val SeqState = SeqProcessNextStates.NotStarted with get, set member __.HaltedIdx = haltedIdx - interface IPipeline with + interface IOutOfBand with member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx // SetResult<> is used at the end of the chain of SeqComponents to assign the final value @@ -987,35 +987,35 @@ namespace Microsoft.FSharp.Collections result.Current <- input true - type Pipeline() = + type OutOfBand() = let mutable haltedIdx = 0 - interface IPipeline with member x.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx + interface IOutOfBand with member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx member __.HaltedIdx = haltedIdx module ForEach = - let enumerable (enumerable:IEnumerable<'T>) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = + let enumerable (enumerable:IEnumerable<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = use enumerator = enumerable.GetEnumerator () - while (pipeline.HaltedIdx = 0) && (enumerator.MoveNext ()) do + while (outOfBand.HaltedIdx = 0) && (enumerator.MoveNext ()) do consumer.ProcessNext enumerator.Current |> ignore - let array (array:array<'T>) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = + let array (array:array<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = let mutable idx = 0 - while (pipeline.HaltedIdx = 0) && (idx < array.Length) do + while (outOfBand.HaltedIdx = 0) && (idx < array.Length) do consumer.ProcessNext array.[idx] |> ignore idx <- idx + 1 - let list (alist:list<'T>) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = + let list (alist:list<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = let rec iterate lst = - match pipeline.HaltedIdx, lst with + match outOfBand.HaltedIdx, lst with | 0, hd :: tl -> consumer.ProcessNext hd |> ignore iterate tl | _ -> () iterate alist - let unfold (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = + let unfold (generator:'S->option<'T*'S>) state (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = let rec iterate current = - match pipeline.HaltedIdx, generator current with + match outOfBand.HaltedIdx, generator current with | 0, Some (item, next) -> consumer.ProcessNext item |> ignore iterate next @@ -1028,11 +1028,11 @@ namespace Microsoft.FSharp.Collections | :? SeqComponent<'T,'U> as c -> c.Skipping | _ -> fun () -> false - let init f (terminatingIdx:int) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = + let init f (terminatingIdx:int) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = let mutable idx = -1 let isSkipping = makeIsSkipping consumer let mutable maybeSkipping = true - while (pipeline.HaltedIdx = 0) && (idx < terminatingIdx) do + while (outOfBand.HaltedIdx = 0) && (idx < terminatingIdx) do if maybeSkipping then maybeSkipping <- isSkipping () @@ -1042,15 +1042,15 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:ISeqFactory<'T,'U>) executeOn = - let pipeline = Pipeline() - let result = f (fun () -> (pipeline:>IPipeline).StopFurtherProcessing (current.PipeIdx+1)) + let pipeline = OutOfBand() + let result = f (fun () -> (pipeline:>IOutOfBand).StopFurtherProcessing (current.PipeIdx+1)) let consumer = current.Create pipeline emptyPipeIdx result try executeOn pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete pipeline.HaltedIdx + (Helpers.upcastICompletionChaining consumer).OnComplete pipeline.HaltedIdx result finally - (Helpers.upcastISeqComponent consumer).OnDispose () + (Helpers.upcastICompletionChaining consumer).OnDispose () module Enumerable = type Empty<'T>() = @@ -1120,7 +1120,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete result.HaltedIdx + (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1133,7 +1133,7 @@ namespace Microsoft.FSharp.Collections try source.Dispose () finally - (Helpers.upcastISeqComponent seqComponent).OnDispose () + (Helpers.upcastICompletionChaining seqComponent).OnDispose () and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:ISeqFactory<'T,'U>) = inherit EnumerableBase<'U>() @@ -1244,7 +1244,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete result.HaltedIdx + (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1295,7 +1295,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete result.HaltedIdx + (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1322,13 +1322,13 @@ namespace Microsoft.FSharp.Collections Helpers.upcastSeq (Enumerable(alist, current)) module Unfold = - type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, signal:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) + type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable current = state let rec moveNext () = - match signal.HaltedIdx, generator current with + match result.HaltedIdx, generator current with | 0, Some (item, nextState) -> current <- nextState if seqComponent.ProcessNext item then @@ -1339,7 +1339,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerator with member __.MoveNext () = - signal.SeqState <- SeqProcessNextStates.InProcess + result.SeqState <- SeqProcessNextStates.InProcess moveNext () type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:ISeqFactory<'T,'U>) = @@ -1379,8 +1379,8 @@ namespace Microsoft.FSharp.Collections else System.Int32.MaxValue - type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:Consumer<'T,'U>, signal:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) + type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let isSkipping = ForEach.makeIsSkipping seqComponent @@ -1392,7 +1392,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = -1 let rec moveNext () = - if (signal.HaltedIdx = 0) && idx < terminatingIdx then + if (result.HaltedIdx = 0) && idx < terminatingIdx then idx <- idx + 1 if maybeSkipping then @@ -1406,16 +1406,16 @@ namespace Microsoft.FSharp.Collections true else moveNext () - elif (signal.HaltedIdx = 0) && idx = System.Int32.MaxValue then + elif (result.HaltedIdx = 0) && idx = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else - signal.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete signal.HaltedIdx + result.SeqState <- SeqProcessNextStates.Finished + (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with member __.MoveNext () = - signal.SeqState <- SeqProcessNextStates.InProcess + result.SeqState <- SeqProcessNextStates.InProcess moveNext () type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:ISeqFactory<'T,'U>) = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 3dbff6d01f1..94dbb8bcc1a 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -35,7 +35,7 @@ namespace Microsoft.FSharp.Collections /// after the enumeration has completed. abstract OnDispose : unit -> unit - type IPipeline = + type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit /// Consumer is the base class of all elements within the pipeline @@ -74,7 +74,7 @@ namespace Microsoft.FSharp.Collections val mutable Value: 'U type ISeqFactory<'T,'U> = - abstract member Create : IPipeline -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> + abstract member Create : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> abstract member PipeIdx : PipeIdx type ISeq<'T> = From 596c6a689031e459b963d2d446c9988997248569 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 13:40:36 +1100 Subject: [PATCH 113/286] Commented strange Unchecked.default usage --- src/fsharp/FSharp.Core/seq.fs | 47 +++++++++++++++++------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ebf6158d5c3..c42681d1d21 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1552,7 +1552,7 @@ namespace Microsoft.FSharp.Collections { new Composer.Internal.Consumer<'T,'T> () with override this.ProcessNext value = f value - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore [] @@ -1574,7 +1574,7 @@ namespace Microsoft.FSharp.Collections halt () else this.Value._1 <- this.Value._1 + 1 - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun item -> item.Value._2 [] @@ -1589,7 +1589,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = f.Invoke(this.Value, value) this.Value <- this.Value + 1 - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore [] @@ -1601,7 +1601,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Value <- true halt () - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun exists -> exists.Value @@ -1614,7 +1614,7 @@ namespace Microsoft.FSharp.Collections if element = value then this.Value <- true halt () - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun contains -> contains.Value @@ -1627,7 +1627,7 @@ namespace Microsoft.FSharp.Collections if not (f value) then this.Value <- false halt () - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun forall -> forall.Value @@ -1733,7 +1733,7 @@ namespace Microsoft.FSharp.Collections this.Value <- some halt () | None -> () - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun pick -> pick.Value [] @@ -1751,7 +1751,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Value <- Some value halt () - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun find -> find.Value [] @@ -1806,7 +1806,7 @@ namespace Microsoft.FSharp.Collections { new Composer.Internal.Folder<'T,'State> (x) with override this.ProcessNext value = this.Value <- f.Invoke (this.Value, value) - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun folded -> folded.Value [] @@ -1838,7 +1838,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value else this.Value._2 <- f.Invoke (this.Value._2, value) - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._1 then @@ -1881,7 +1881,7 @@ namespace Microsoft.FSharp.Collections if c <> 0 then this.Value <- c halt () - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value = 0 && e2.MoveNext() then this.Value <- -1 }) @@ -1995,8 +1995,7 @@ namespace Microsoft.FSharp.Collections halt () else this.Value._2 <- this.Value._2 + 1 - Unchecked.defaultof - }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun tried -> tried.Value._1 [] @@ -2241,7 +2240,7 @@ namespace Microsoft.FSharp.Collections { new Composer.Internal.Folder<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value value - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun sum -> sum.Value [] @@ -2251,7 +2250,7 @@ namespace Microsoft.FSharp.Collections { new Composer.Internal.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value (f value) - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun sum -> sum.Value [] @@ -2262,7 +2261,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 value this.Value._2 <- this.Value._2 + 1 - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._2 = 0 then @@ -2277,7 +2276,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 (f value) this.Value._2 <- this.Value._2 + 1 - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._2 = 0 then @@ -2295,7 +2294,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value elif value < this.Value._2 then this.Value._2 <- value - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._1 then @@ -2318,7 +2317,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- valueU this.Value._3 <- value | _ -> () - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._1 then @@ -2353,7 +2352,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value elif value > this.Value._2 then this.Value._2 <- value - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._1 then @@ -2376,7 +2375,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- valueU this.Value._3 <- value | _ -> () - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._1 then @@ -2445,7 +2444,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Value <- Some value halt () - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun head -> head.Value [] @@ -2467,7 +2466,7 @@ namespace Microsoft.FSharp.Collections if this.Value._1 then this.Value._1 <- false this.Value._2 <- value - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun tried -> if tried.Value._1 then None @@ -2492,7 +2491,7 @@ namespace Microsoft.FSharp.Collections else this.Value._3 <- true halt () - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._1 then From 4ee51fdb5638d26d52e878f80ea1a81687b6659f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 19:58:10 +1100 Subject: [PATCH 114/286] Partial move to Composer module In the Composer module we use ISeq rather than seq. An end goal could be be publicly expose this module for enhanced performancy. --- src/fsharp/FSharp.Core/seq.fs | 332 +++++++++++++++++++++++----------- 1 file changed, 222 insertions(+), 110 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index c42681d1d21..c2041123962 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -536,6 +536,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 upcastSeq (t:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) + let inline upcastFactory (t:#ISeqFactory<'T,'U>) : ISeqFactory<'T,'U> = (# "" t : ISeqFactory<'T,'U> #) let inline upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) @@ -556,7 +557,7 @@ namespace Microsoft.FSharp.Collections first.Create outOfBand pipeIdx (second.Create outOfBand (makePipeIdx secondPipeIdx) next) static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = - upcast ComposedFactory(first, second, first.PipeIdx+1) + ComposedFactory(first, second, first.PipeIdx+1) |> Helpers.upcastFactory and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () @@ -591,7 +592,7 @@ namespace Microsoft.FSharp.Collections static let singleton = IdentityFactory<'T>() interface ISeqFactory<'T,'T> with member __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next - static member IdentityFactory = singleton + static member Instance = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () @@ -1201,7 +1202,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastSeq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) and ConcatEnumerable<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = inherit EnumerableBase<'T>() @@ -1215,11 +1216,33 @@ namespace Microsoft.FSharp.Collections Helpers.upcastSeq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) let create enumerable current = Helpers.upcastSeq (Enumerable(enumerable, current)) + 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 = + Helpers.upcastEnumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) + + interface ISeq<'T> with + member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + Helpers.upcastSeq (Enumerable.Enumerable<'T,'V>(this, next)) + + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) + + + module Array = type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) @@ -1274,10 +1297,10 @@ namespace Microsoft.FSharp.Collections createDelayed (fun () -> array) current let createDelayedId (delayedArray:unit -> array<'T>) = - createDelayed delayedArray IdentityFactory.IdentityFactory + createDelayed delayedArray IdentityFactory.Instance let createId (array:array<'T>) = - create array IdentityFactory.IdentityFactory + create array IdentityFactory.Instance module List = type Enumerator<'T,'U>(alist:list<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = @@ -1499,7 +1522,167 @@ namespace Microsoft.FSharp.Collections Helpers.upcastSeq (Enumerable<'T,'V>(count, f, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable (Helpers.upcastEnumerable this)) + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (Helpers.upcastEnumerable this)) + + open RuntimeHelpers + + [] + let toComposer (source:seq<'T>) : ISeq<'T> = + checkNonNull "source" source + match source with + | :? ISeq<'T> as s -> s + | :? array<'T> as a -> Helpers.upcastSeq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) + | :? list<'T> as a -> Helpers.upcastSeq (List.Enumerable(a, IdentityFactory.Instance)) + | _ -> Helpers.upcastSeq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) + + let inline foreach f (source:ISeq<_>) = + source.ForEach f + + let inline compose factory (source:ISeq<'T>) = + source.Compose factory + + [] + let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance + + [] + let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = + Helpers.upcastSeq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) + + [] + let initInfinite<'T> (f:int->'T) : ISeq<'T> = + Helpers.upcastSeq (new Init.EnumerableDecider<'T>(Nullable (), f)) + + [] + let init<'T> (count:int) (f:int->'T) : ISeq<'T> = + if count < 0 then invalidArgInputMustBeNonNegative "count" count + elif count = 0 then empty else + Helpers.upcastSeq (new Init.EnumerableDecider<'T>(Nullable count, f)) + + [] + let iter f (source:ISeq<'T>) = + source + |> foreach (fun _ -> + { new Consumer<'T,'T> () with + override this.ProcessNext value = + f value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> ignore + + [] + let tryItem i (source:ISeq<'T>) = + if i < 0 then None else + source + |> foreach (fun halt -> + { new Folder<'T, Values>> (Values<_,_> (0, None)) with + override this.ProcessNext value = + if this.Value._1 = i then + this.Value._2 <- Some value + halt () + else + this.Value._1 <- this.Value._1 + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun item -> item.Value._2 + + [] + let iteri f (source:ISeq<'T>) = + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f + + source + |> foreach (fun _ -> + { new Folder<'T, int> (0) with + override this.ProcessNext value = + f.Invoke(this.Value, value) + this.Value <- this.Value + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> ignore + + [] + let exists f (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, bool> (false) with + override this.ProcessNext value = + if f value then + this.Value <- true + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun exists -> exists.Value + + [] + let inline contains element (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, bool> (false) with + override this.ProcessNext value = + if element = value then + this.Value <- true + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun contains -> contains.Value + + [] + let forall f (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, bool> (true) with + override this.ProcessNext value = + if not (f value) then + this.Value <- false + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun forall -> forall.Value + + [] + let filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = + source + |> compose (FilterFactory f) + + [] + let map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = + source + |> compose (MapFactory f) + + [] + let mapi f source = + source + |> compose (MapiFactory f) + + [] + let choose f source = + source + |> compose (ChooseFactory f) + + [] + let indexed source = + source + |> compose (MapiFactory (fun i x -> i,x)) + + [] + let tryPick f (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, Option<'U>> (None) with + override this.ProcessNext value = + match f value with + | (Some _) as some -> + this.Value <- some + halt () + | None -> () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun pick -> pick.Value + + [] + let tryFind f (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, Option<'T>> (None) with + override this.ProcessNext value = + if f value then + this.Value <- Some value + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun find -> find.Value + #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions @@ -1513,47 +1696,35 @@ namespace Microsoft.FSharp.Collections [] let toComposer (source:seq<'T>): Composer.Internal.ISeq<'T> = - checkNonNull "source" source - match source with - | :? Composer.Enumerable.EnumerableBase<'T> as s -> upcast s - | :? array<'T> as a -> upcast Composer.Array.Enumerable((fun () -> a), Composer.IdentityFactory.IdentityFactory) - | :? list<'T> as a -> upcast Composer.List.Enumerable(a, Composer.IdentityFactory.IdentityFactory) - | _ -> upcast Composer.Enumerable.Enumerable<'T,'T>(source, Composer.IdentityFactory.IdentityFactory) + Composer.toComposer source let inline foreach f (source:seq<_>) = - source - |> toComposer - |> fun composer -> composer.ForEach f + Composer.foreach f (toComposer source) [] let delay f = mkDelayedSeq f [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : seq<'T> = - Composer.Helpers.upcastEnumerable (new Composer.Unfold.Enumerable<'T,'T,'State>(generator, state, Composer.IdentityFactory.IdentityFactory)) + Composer.unfold generator state + |> Composer.Helpers.upcastEnumerable [] let empty<'T> = (EmptyEnumerable :> seq<'T>) [] let initInfinite<'T> (f:int->'T) : IEnumerable<'T> = - Composer.Helpers.upcastEnumerable (new Composer.Init.EnumerableDecider<'T>(Nullable (), f)) + Composer.initInfinite f + |> Composer.Helpers.upcastEnumerable [] let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> = - if count < 0 then invalidArgInputMustBeNonNegative "count" count - elif count = 0 then empty else - Composer.Helpers.upcastEnumerable (new Composer.Init.EnumerableDecider<'T>(Nullable count, f)) + Composer.init count f + |> Composer.Helpers.upcastEnumerable [] let iter f (source : seq<'T>) = - source - |> foreach (fun _ -> - { new Composer.Internal.Consumer<'T,'T> () with - override this.ProcessNext value = - f value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> ignore + Composer.iter f (toComposer source) [] let item i (source : seq<'T>) = @@ -1563,73 +1734,27 @@ namespace Microsoft.FSharp.Collections IEnumerator.nth i e [] - let tryItem i (source : seq<'T>) = - if i < 0 then None else - source - |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Composer.Internal.Values>> (Composer.Internal.Values<_, _> (0, None)) with - override this.ProcessNext value = - if this.Value._1 = i then - this.Value._2 <- Some value - halt () - else - this.Value._1 <- this.Value._1 + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun item -> item.Value._2 + let tryItem i (source:seq<'T>) = + Composer.tryItem i (toComposer source) [] let nth i (source : seq<'T>) = item i source [] - let iteri f (source : seq<'T>) = - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - source - |> foreach (fun _ -> - { new Composer.Internal.Folder<'T, int> (0) with - override this.ProcessNext value = - f.Invoke(this.Value, value) - this.Value <- this.Value + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> ignore + let iteri f (source:seq<'T>) = + Composer.iteri f (toComposer source) [] - let exists f (source : seq<'T>) = - source - |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, bool> (false) with - override this.ProcessNext value = - if f value then - this.Value <- true - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - }) - |> fun exists -> exists.Value + let exists f (source:seq<'T>) = + Composer.exists f (toComposer source) [] - let inline contains element (source : seq<'T>) = - source - |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, bool> (false) with - override this.ProcessNext value = - if element = value then - this.Value <- true - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - }) - |> fun contains -> contains.Value + let inline contains element (source:seq<'T>) = + Composer.contains element (toComposer source) [] - let forall f (source : seq<'T>) = - source - |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, bool> (true) with - override this.ProcessNext value = - if not (f value) then - this.Value <- false - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - }) - |> fun forall -> forall.Value + let forall f (source:seq<'T>) = + Composer.forall f (toComposer source) [] let iter2 f (source1 : seq<_>) (source2 : seq<_>) = @@ -1670,18 +1795,21 @@ namespace Microsoft.FSharp.Collections [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = - source |> seqFactory (Composer.FilterFactory f) + Composer.filter f (toComposer source) + |> Composer.Helpers.upcastEnumerable [] let where f source = filter f source [] let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> = - source |> seqFactory (Composer.MapFactory f) + Composer.map f (toComposer source) + |> Composer.Helpers.upcastEnumerable [] let mapi f source = - source |> seqFactory (Composer.MapiFactory f) + Composer.mapi f (toComposer source) + |> Composer.Helpers.upcastEnumerable [] let mapi2 f source1 source2 = @@ -1702,12 +1830,14 @@ namespace Microsoft.FSharp.Collections source1 |> seqFactory (Composer.Map3Factory (f, source2, source3)) [] - let choose f source = - source |> seqFactory (Composer.ChooseFactory f) + let choose f source = + Composer.choose f (toComposer source) + |> Composer.Helpers.upcastEnumerable [] let indexed source = - source |> seqFactory (Composer.MapiFactory (fun i x -> i,x) ) + Composer.indexed (toComposer source) + |> Composer.Helpers.upcastEnumerable [] let zip source1 source2 = @@ -1724,17 +1854,7 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source : seq<'T>) = - source - |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Option<'U>> (None) with - override this.ProcessNext value = - match f value with - | (Some _) as some -> - this.Value <- some - halt () - | None -> () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun pick -> pick.Value + Composer.tryPick f (toComposer source) [] let pick f source = @@ -1744,15 +1864,7 @@ namespace Microsoft.FSharp.Collections [] let tryFind f (source : seq<'T>) = - source - |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Option<'T>> (None) with - override this.ProcessNext value = - if f value then - this.Value <- Some value - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun find -> find.Value + Composer.tryFind f (toComposer source) [] let find f source = From ddd71109ab45bb101058b32638748d035e53ffee Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 29 Oct 2016 22:26:16 -0400 Subject: [PATCH 115/286] Seq.item/iter2/iteri2/fold2/forall2/exists2 --- src/fsharp/FSharp.Core/seq.fs | 131 +++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 48 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index c2041123962..386a956a87c 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -56,20 +56,6 @@ namespace Microsoft.FSharp.Collections let Empty<'T> () = (new EmptyEnumerator<'T>() :> IEnumerator<'T>) - let rec tryItem index (e : IEnumerator<'T>) = - if not (e.MoveNext()) then None - elif index = 0 then Some(e.Current) - else tryItem (index-1) e - - let rec nth index (e : IEnumerator<'T>) = - if not (e.MoveNext()) then - let shortBy = index + 1 - invalidArgFmt "index" - "{0}\nseq was short by {1} {2}" - [|SR.GetString SR.notEnoughElements; shortBy; (if shortBy = 1 then "element" else "elements")|] - if index = 0 then e.Current - else nth (index-1) e - let readAndClear r = lock r (fun () -> match !r with None -> None | Some _ as res -> r := None; res) @@ -1728,10 +1714,26 @@ namespace Microsoft.FSharp.Collections [] let item i (source : seq<'T>) = - checkNonNull "source" source - if i < 0 then invalidArgInputMustBeNonNegative "index" i - use e = source.GetEnumerator() - IEnumerator.nth i e + if i < 0 then invalidArgInputMustBeNonNegative "index" i else + source + |> foreach (fun halt -> + { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values<_,_,_> (0, false, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 = i then + this.Value._2 <- true + this.Value._3 <- value + halt () + else + this.Value._1 <- this.Value._1 + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + override this.OnComplete _ = + if not this.Value._2 then + let index = i - this.Value._1 + 1 + invalidArgFmt "index" + "{0}\nseq was short by {1} {2}" + [|SR.GetString SR.notEnoughElements; index; (if index=1 then "element" else "elements")|] + }) + |> fun item -> item.Value._3 [] let tryItem i (source:seq<'T>) = @@ -1758,25 +1760,40 @@ namespace Microsoft.FSharp.Collections [] let iter2 f (source1 : seq<_>) (source2 : seq<_>) = - checkNonNull "source1" source1 checkNonNull "source2" source2 - use e1 = source1.GetEnumerator() + use e2 = source2.GetEnumerator() let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - while (e1.MoveNext() && e2.MoveNext()) do - f.Invoke(e1.Current, e2.Current) + + source1 + |> foreach (fun halt -> + { new Composer.Internal.Folder<_,_> () with + override this.ProcessNext value = + if (e2.MoveNext()) then + f.Invoke(value, e2.Current) + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> ignore [] let iteri2 f (source1 : seq<_>) (source2 : seq<_>) = - checkNonNull "source1" source1 checkNonNull "source2" source2 - use e1 = source1.GetEnumerator() + use e2 = source2.GetEnumerator() let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) - let mutable i = 0 - while (e1.MoveNext() && e2.MoveNext()) do - f.Invoke(i, e1.Current, e2.Current) - i <- i + 1 + + source1 + |> foreach (fun halt -> + { new Composer.Internal.Folder<_,int> (0) with + override this.ProcessNext value = + if (e2.MoveNext()) then + f.Invoke(this.Value, value, e2.Current) + this.Value <- this.Value + 1 + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> ignore // Build an IEnumerble by wrapping/transforming iterators as they get generated. let revamp f (ie : seq<_>) = mkSeq (fun () -> f (ie.GetEnumerator())) @@ -1923,19 +1940,21 @@ namespace Microsoft.FSharp.Collections [] let fold2<'T1,'T2,'State> f (state:'State) (source1: seq<'T1>) (source2: seq<'T2>) = - checkNonNull "source1" source1 checkNonNull "source2" source2 - use e1 = source1.GetEnumerator() use e2 = source2.GetEnumerator() - let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) - let mutable state = state - while e1.MoveNext() && e2.MoveNext() do - state <- f.Invoke(state, e1.Current, e2.Current) - - state + source1 + |> foreach (fun halt -> + { new Composer.Internal.Folder<_,'State> (state) with + override this.ProcessNext value = + if (e2.MoveNext()) then + this.Value <- f.Invoke(this.Value, value, e2.Current) + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun fold -> fold.Value [] let reduce f (source : seq<'T>) = @@ -2526,27 +2545,43 @@ namespace Microsoft.FSharp.Collections [] let forall2 p (source1: seq<_>) (source2: seq<_>) = - checkNonNull "source1" source1 checkNonNull "source2" source2 - use e1 = source1.GetEnumerator() + use e2 = source2.GetEnumerator() let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(p) - let mutable ok = true - while (ok && e1.MoveNext() && e2.MoveNext()) do - ok <- p.Invoke(e1.Current, e2.Current) - ok + + source1 + |> foreach (fun halt -> + { new Composer.Internal.Folder<_,bool> (true) with + override this.ProcessNext value = + if (e2.MoveNext()) then + if not (p.Invoke(value, e2.Current)) then + this.Value <- false + halt() + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun all -> all.Value [] let exists2 p (source1: seq<_>) (source2: seq<_>) = - checkNonNull "source1" source1 checkNonNull "source2" source2 - use e1 = source1.GetEnumerator() + use e2 = source2.GetEnumerator() let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(p) - let mutable ok = false - while (not ok && e1.MoveNext() && e2.MoveNext()) do - ok <- p.Invoke(e1.Current, e2.Current) - ok + + source1 + |> foreach (fun halt -> + { new Composer.Internal.Folder<_,bool> (false) with + override this.ProcessNext value = + if (e2.MoveNext()) then + if p.Invoke(value, e2.Current) then + this.Value <- true + halt() + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun exists -> exists.Value [] let tryHead (source : seq<_>) = From 98f7a4a65d71023dc257ff30564e4021dcb5b1c2 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 30 Oct 2016 14:56:56 +1100 Subject: [PATCH 116/286] Removed Helpers. qualifier Names are unique and descriptive enough --- src/fsharp/FSharp.Core/seq.fs | 126 +++++++++++++++++----------------- 1 file changed, 64 insertions(+), 62 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 386a956a87c..4bb65806098 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -528,6 +528,8 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastICompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) + open Helpers + type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) @@ -543,7 +545,7 @@ namespace Microsoft.FSharp.Collections first.Create outOfBand pipeIdx (second.Create outOfBand (makePipeIdx secondPipeIdx) next) static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = - ComposedFactory(first, second, first.PipeIdx+1) |> Helpers.upcastFactory + ComposedFactory(first, second, first.PipeIdx+1) |> upcastFactory and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () @@ -681,7 +683,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = match choose input with - | Some value -> Helpers.avoidTailCall (next.ProcessNext value) + | Some value -> avoidTailCall (next.ProcessNext value) | None -> false and Distinct<'T,'V when 'T: equality> (next:Consumer<'T,'V>) = @@ -691,7 +693,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if hashSet.Add input then - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else false @@ -702,7 +704,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if hashSet.Add(keyFunction input) then - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else false @@ -713,7 +715,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if cached.Value.Add input then - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else false @@ -724,7 +726,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if filter input then - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else false @@ -733,7 +735,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if filter input then - Helpers.avoidTailCall (next.ProcessNext (map input)) + avoidTailCall (next.ProcessNext (map input)) else false @@ -743,7 +745,7 @@ namespace Microsoft.FSharp.Collections override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) override __.ProcessNext (input:'T) : bool = - Helpers.avoidTailCall (next.ProcessNext (map input)) + avoidTailCall (next.ProcessNext (map input)) and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) @@ -753,7 +755,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'First) : bool = if input2.MoveNext () then - Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) + avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -769,7 +771,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'Second) : bool = if input1.MoveNext () then - Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) + avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -786,7 +788,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'First) : bool = if input2.MoveNext () && input3.MoveNext () then - Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) + avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -801,7 +803,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = let u = map input if filter u then - Helpers.avoidTailCall (next.ProcessNext u) + avoidTailCall (next.ProcessNext u) else false @@ -813,7 +815,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = idx <- idx + 1 - Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) + avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) @@ -825,7 +827,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'First) : bool = if input2.MoveNext () then idx <- idx + 1 - Helpers.avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) + avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -847,7 +849,7 @@ namespace Microsoft.FSharp.Collections else let currentPair = lastValue, input lastValue <- input - Helpers.avoidTailCall (next.ProcessNext currentPair) + avoidTailCall (next.ProcessNext currentPair) and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:Consumer<'State,'V>) = inherit SeqComponent<'T,'V>(next) @@ -857,7 +859,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = foldResult <- f.Invoke(foldResult, input) - Helpers.avoidTailCall (next.ProcessNext foldResult) + avoidTailCall (next.ProcessNext foldResult) and Skip<'T,'V> (skipCount:int, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -876,7 +878,7 @@ namespace Microsoft.FSharp.Collections count <- count + 1 false else - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) override __.OnComplete _ = if count < skipCount then @@ -895,9 +897,9 @@ namespace Microsoft.FSharp.Collections if skip then false else - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) and Take<'T,'V> (takeCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipelineIdx:int) = inherit Truncate<'T, 'V>(takeCount, outOfBand, next, pipelineIdx) @@ -913,7 +915,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if predicate input then - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else outOfBand.StopFurtherProcessing pipeIdx false @@ -928,7 +930,7 @@ namespace Microsoft.FSharp.Collections first <- false false else - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) override this.OnComplete _ = if first then @@ -946,7 +948,7 @@ namespace Microsoft.FSharp.Collections count <- count + 1 if count = truncateCount then outOfBand.StopFurtherProcessing pipeIdx - next.ProcessNext input + avoidTailCall (next.ProcessNext input) else outOfBand.StopFurtherProcessing pipeIdx false @@ -1034,10 +1036,10 @@ namespace Microsoft.FSharp.Collections let consumer = current.Create pipeline emptyPipeIdx result try executeOn pipeline consumer - (Helpers.upcastICompletionChaining consumer).OnComplete pipeline.HaltedIdx + (upcastICompletionChaining consumer).OnComplete pipeline.HaltedIdx result finally - (Helpers.upcastICompletionChaining consumer).OnDispose () + (upcastICompletionChaining consumer).OnDispose () module Enumerable = type Empty<'T>() = @@ -1062,7 +1064,7 @@ namespace Microsoft.FSharp.Collections seqComponent.OnDispose () interface IEnumerator with - member this.Current : obj = box ((Helpers.upcastEnumerator this)).Current + member this.Current : obj = box ((upcastEnumerator this)).Current member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)" member __.Reset () : unit = noReset () @@ -1081,13 +1083,13 @@ namespace Microsoft.FSharp.Collections abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> - default this.Append source = Helpers.upcastEnumerable (AppendEnumerable [this; source]) + default this.Append source = upcastEnumerable (AppendEnumerable [this; source]) interface IEnumerable with member this.GetEnumerator () : IEnumerator = - let genericEnumerable = Helpers.upcastEnumerable this + let genericEnumerable = upcastEnumerable this let genericEnumerator = genericEnumerable.GetEnumerator () - Helpers.upcastEnumeratorNonGeneric genericEnumerator + upcastEnumeratorNonGeneric genericEnumerator interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () @@ -1107,7 +1109,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1120,7 +1122,7 @@ namespace Microsoft.FSharp.Collections try source.Dispose () finally - (Helpers.upcastICompletionChaining seqComponent).OnDispose () + (upcastICompletionChaining seqComponent).OnDispose () and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:ISeqFactory<'T,'U>) = inherit EnumerableBase<'U>() @@ -1128,11 +1130,11 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) + upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - Helpers.upcastSeq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) + upcastSeq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.enumerable enumerable) @@ -1162,7 +1164,7 @@ namespace Microsoft.FSharp.Collections | _ -> active.Current interface IEnumerator with - member this.Current = box ((Helpers.upcastEnumerator this)).Current + member this.Current = box ((upcastEnumerator this)).Current member __.MoveNext () = state <- SeqProcessNextStates.InProcess moveNext () @@ -1178,14 +1180,14 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - Helpers.upcastEnumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) + upcastEnumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) override this.Append source = - Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) + upcastEnumerable (AppendEnumerable (source :: sources)) interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - Helpers.upcastSeq (Enumerable<'T,'V>(this, next)) + upcastSeq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) @@ -1195,17 +1197,17 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - Helpers.upcastEnumerator (new ConcatEnumerator<_,_> (sources)) + upcastEnumerator (new ConcatEnumerator<_,_> (sources)) interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - Helpers.upcastSeq (Enumerable<'T,'V>(this, next)) + upcastSeq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) let create enumerable current = - Helpers.upcastSeq (Enumerable(enumerable, current)) + upcastSeq (Enumerable(enumerable, current)) module EmptyEnumerable = type Enumerable<'T> () = @@ -1218,11 +1220,11 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () : IEnumerator<'T> = IEnumerator.Empty<'T>() override this.Append source = - Helpers.upcastEnumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) + upcastEnumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - Helpers.upcastSeq (Enumerable.Enumerable<'T,'V>(this, next)) + upcastSeq (Enumerable.Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) @@ -1253,7 +1255,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1267,17 +1269,17 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - Helpers.upcastSeq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) + upcastSeq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:ISeqFactory<'T,'U>) = - Helpers.upcastSeq (Enumerable(delayedArray, current)) + upcastSeq (Enumerable(delayedArray, current)) let create (array:array<'T>) (current:ISeqFactory<'T,'U>) = createDelayed (fun () -> array) current @@ -1304,7 +1306,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1318,17 +1320,17 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - Helpers.upcastSeq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) + upcastSeq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.list alist) let create alist current = - Helpers.upcastSeq (Enumerable(alist, current)) + upcastSeq (Enumerable(alist, current)) module Unfold = type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, result:Result<'U>) = @@ -1357,11 +1359,11 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - Helpers.upcastSeq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) + upcastSeq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.unfold generator state) @@ -1419,7 +1421,7 @@ namespace Microsoft.FSharp.Collections raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1433,11 +1435,11 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - Helpers.upcastSeq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) + upcastSeq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) member this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = let terminatingIdx = getTerminatingIdx count @@ -1505,10 +1507,10 @@ namespace Microsoft.FSharp.Collections interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - Helpers.upcastSeq (Enumerable<'T,'V>(count, f, next)) + upcastSeq (Enumerable<'T,'V>(count, f, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (Helpers.upcastEnumerable this)) + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (upcastEnumerable this)) open RuntimeHelpers @@ -1517,9 +1519,9 @@ namespace Microsoft.FSharp.Collections checkNonNull "source" source match source with | :? ISeq<'T> as s -> s - | :? array<'T> as a -> Helpers.upcastSeq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) - | :? list<'T> as a -> Helpers.upcastSeq (List.Enumerable(a, IdentityFactory.Instance)) - | _ -> Helpers.upcastSeq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) + | :? array<'T> as a -> upcastSeq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) + | :? list<'T> as a -> upcastSeq (List.Enumerable(a, IdentityFactory.Instance)) + | _ -> upcastSeq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) let inline foreach f (source:ISeq<_>) = source.ForEach f @@ -1532,17 +1534,17 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = - Helpers.upcastSeq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) + upcastSeq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) [] let initInfinite<'T> (f:int->'T) : ISeq<'T> = - Helpers.upcastSeq (new Init.EnumerableDecider<'T>(Nullable (), f)) + upcastSeq (new Init.EnumerableDecider<'T>(Nullable (), f)) [] let init<'T> (count:int) (f:int->'T) : ISeq<'T> = if count < 0 then invalidArgInputMustBeNonNegative "count" count elif count = 0 then empty else - Helpers.upcastSeq (new Init.EnumerableDecider<'T>(Nullable count, f)) + upcastSeq (new Init.EnumerableDecider<'T>(Nullable count, f)) [] let iter f (source:ISeq<'T>) = From 2e1598356fb59c406507134dddc1ff4dc6e72e62 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 30 Oct 2016 18:58:55 +1100 Subject: [PATCH 117/286] Update NoNeedToTailcall.output.test.bsl for Seq mod --- .../analyses/tailcalls.NoNeedToTailcall.output.test.bsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl index 785a337a2f4..5f4e677efc6 100644 --- a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl +++ b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl @@ -38,7 +38,7 @@ value simpleLibraryCall6 at line 60 does not make a critical tailcall value simpleLibraryCall7 at line 61 does not make a critical tailcall value simpleLibraryCall8 at line 62 does not make a critical tailcall value simpleLibraryCall9 at line 63 does not make a critical tailcall -value simpleLibraryCall10 at line 65 may make a critical tailcall +value simpleLibraryCall10 at line 65 does not make a critical tailcall value simpleLibraryCall11 at line 66 does not make a critical tailcall value simpleLibraryCall12 at line 67 does not make a critical tailcall value simpleLibraryCall13 at line 68 does not make a critical tailcall From a94f8876ec0f8f82058ba9a937652f98c09e84b6 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 30 Oct 2016 19:08:45 +1100 Subject: [PATCH 118/286] Adding types to try to appease test Adding the types doesn't work. Only appearing in portable build, so pondering if it is a compiler bug? Will need to get onto someone about it I think. --- src/fsharp/FSharp.Core/seq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 4bb65806098..b2eb55f0468 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -535,7 +535,7 @@ namespace Microsoft.FSharp.Collections interface ISeqFactory<'T,'U> with member __.PipeIdx = getPipeIdx pipeIdx - member __.Create _ _ _ = failwith "library implementation error: Create on base factory should not be called" + member __.Create<'V> (_:IOutOfBand) (_:``PipeIdx?``) (_:Consumer<'U,'V>) : Consumer<'T,'V> = failwith "library implementation error: Create on base factory should not be called" and ComposedFactory<'T,'U,'V> private (first:ISeqFactory<'T,'U>, second:ISeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) From 16faaa82ad2cd1e70d23ca055420ad0007b41191 Mon Sep 17 00:00:00 2001 From: liboz Date: Mon, 31 Oct 2016 19:40:51 -0400 Subject: [PATCH 119/286] seq.windowed --- src/fsharp/FSharp.Core/seq.fs | 53 ++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index b2eb55f0468..6cbf1dc1ca5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -654,6 +654,11 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, getPipeIdx pipeIdx) + + and WindowedFactory<'T> (windowSize:int) = + inherit SeqComponentFactory<'T, 'T[]> () + interface ISeqFactory<'T, 'T[]> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T[],'V>) : Consumer<'T,'V> = upcast Windowed (windowSize, next) and [] SeqComponent<'T,'U> (next:ICompletionChaining) = inherit Consumer<'T,'U>() @@ -953,6 +958,34 @@ namespace Microsoft.FSharp.Collections outOfBand.StopFurtherProcessing pipeIdx false + and Windowed<'T,'V> (windowSize: int, next:Consumer<'T[],'V>) = + inherit SeqComponent<'T,'V>(next) + + let arr = Array.zeroCreateUnchecked windowSize + let r = ref (windowSize - 1) + let i = ref 0 + + let arrWindow innerDerefI j = arr.[(innerDerefI+j) % windowSize] + + override __.ProcessNext (input:'T) : bool = + let derefI = !i + arr.[derefI] <- input + i := (derefI + 1) % windowSize + let derefR = !r + if derefR = 0 then + let innerDerefI = !i + if windowSize < 32 then + let window = Array.init windowSize (arrWindow innerDerefI) + avoidTailCall (next.ProcessNext window) + else + let window = Array.zeroCreateUnchecked windowSize + Array.Copy(arr, innerDerefI, window, 0, windowSize - innerDerefI) + Array.Copy(arr, 0, window, windowSize - innerDerefI, innerDerefI) + avoidTailCall (next.ProcessNext window) + else + r := (derefR - 1) + false + type SeqProcessNextStates = | InProcess = 0 | NotStarted = 1 @@ -2150,27 +2183,9 @@ namespace Microsoft.FSharp.Collections // windowed : int -> seq<'T> -> seq<'T[]> [] let windowed windowSize (source: seq<_>) = - checkNonNull "source" source if windowSize <= 0 then invalidArgFmt "windowSize" "{0}\nwindowSize = {1}" [|SR.GetString SR.inputMustBePositive; windowSize|] - seq { - let arr = Array.zeroCreateUnchecked windowSize - let r = ref (windowSize - 1) - let i = ref 0 - use e = source.GetEnumerator() - while e.MoveNext() do - arr.[!i] <- e.Current - i := (!i + 1) % windowSize - if !r = 0 then - if windowSize < 32 then - yield Array.init windowSize (fun j -> arr.[(!i+j) % windowSize]) - else - let result = Array.zeroCreateUnchecked windowSize - Array.Copy(arr, !i, result, 0, windowSize - !i) - Array.Copy(arr, 0, result, windowSize - !i, !i) - yield result - else r := (!r - 1) - } + source |> seqFactory (Composer.WindowedFactory (windowSize)) [] let cache (source : seq<'T>) = From f6bd2f8b1c8964377dae39f5dfebb758882e2450 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 1 Nov 2016 18:25:18 +1100 Subject: [PATCH 120/286] Tightening up Seq.windowed - removed ref vars, as can just us let mutable - renamed variables to more meaningful names - removed modulus because I can --- src/fsharp/FSharp.Core/seq.fs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 6cbf1dc1ca5..6ba2d789ece 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -961,30 +961,30 @@ namespace Microsoft.FSharp.Collections and Windowed<'T,'V> (windowSize: int, next:Consumer<'T[],'V>) = inherit SeqComponent<'T,'V>(next) - let arr = Array.zeroCreateUnchecked windowSize - let r = ref (windowSize - 1) - let i = ref 0 + let circularBuffer = Array.zeroCreateUnchecked windowSize + let mutable idx = 0 - let arrWindow innerDerefI j = arr.[(innerDerefI+j) % windowSize] + let mutable priming = windowSize - 1 override __.ProcessNext (input:'T) : bool = - let derefI = !i - arr.[derefI] <- input - i := (derefI + 1) % windowSize - let derefR = !r - if derefR = 0 then - let innerDerefI = !i + circularBuffer.[idx] <- input + + idx <- idx + 1 + if idx = windowSize then + idx <- 0 + + if priming > 0 then + priming <- priming - 1 + false + else if windowSize < 32 then - let window = Array.init windowSize (arrWindow innerDerefI) + let window = Array.init windowSize (fun i -> circularBuffer.[(idx+i) % windowSize]) avoidTailCall (next.ProcessNext window) else let window = Array.zeroCreateUnchecked windowSize - Array.Copy(arr, innerDerefI, window, 0, windowSize - innerDerefI) - Array.Copy(arr, 0, window, windowSize - innerDerefI, innerDerefI) + Array.Copy(circularBuffer, idx, window, 0, windowSize - idx) + Array.Copy(circularBuffer, 0, window, windowSize - idx, idx) avoidTailCall (next.ProcessNext window) - else - r := (derefR - 1) - false type SeqProcessNextStates = | InProcess = 0 From a4c030224e3c3f8a49566c8a5937eb5c578638ea Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 3 Nov 2016 22:50:07 -0400 Subject: [PATCH 121/286] Reduce the diff on seq.fs so that it is easier to review on GitHub --- src/fsharp/FSharp.Core/FSharp.Core.fsproj | 12 + src/fsharp/FSharp.Core/seq.fs | 1823 +-------------------- src/fsharp/FSharp.Core/seq.fsi | 167 +- src/fsharp/FSharp.Core/seqcomposer.fs | 1286 +++++++++++++++ src/fsharp/FSharp.Core/seqcomposer.fsi | 757 +++++++++ src/fsharp/FSharp.Core/seqcore.fs | 405 +++++ src/fsharp/FSharp.Core/seqcore.fsi | 150 ++ 7 files changed, 2685 insertions(+), 1915 deletions(-) create mode 100644 src/fsharp/FSharp.Core/seqcomposer.fs create mode 100644 src/fsharp/FSharp.Core/seqcomposer.fsi create mode 100644 src/fsharp/FSharp.Core/seqcore.fs create mode 100644 src/fsharp/FSharp.Core/seqcore.fsi diff --git a/src/fsharp/FSharp.Core/FSharp.Core.fsproj b/src/fsharp/FSharp.Core/FSharp.Core.fsproj index 8ad25ce16c7..b03f6d410c1 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/seqcore.fsi + + + Collections/seqcore.fs + + + Collections/seqcomposer.fsi + + + Collections/seqcomposer.fs Collections/seq.fsi diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 6ba2d789ece..8d9686b9431 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1,410 +1,5 @@ // 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 - #nowarn "52" // The value has been copied to ensure the original is not mutated by this operation - - open System - open System.Diagnostics - open System.Collections - open System.Collections.Generic - open Microsoft.FSharp.Core - open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators - open Microsoft.FSharp.Core.Operators - open Microsoft.FSharp.Control - open Microsoft.FSharp.Collections - - module IEnumerator = - - let noReset() = raise (new System.NotSupportedException(SR.GetString(SR.resetNotSupported))) - let notStarted() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationNotStarted))) - let alreadyFinished() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationAlreadyFinished))) - let check started = if not started then notStarted() - let dispose (r : System.IDisposable) = r.Dispose() - - let cast (e : IEnumerator) : IEnumerator<'T> = - { new IEnumerator<'T> with - member x.Current = unbox<'T> e.Current - interface IEnumerator with - member x.Current = unbox<'T> e.Current :> obj - member x.MoveNext() = e.MoveNext() - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = - match e with - | :? System.IDisposable as e -> e.Dispose() - | _ -> () } - - /// A concrete implementation of an enumerator that returns no values - [] - type EmptyEnumerator<'T>() = - let mutable started = false - interface IEnumerator<'T> with - member x.Current = - check started - (alreadyFinished() : 'T) - - interface System.Collections.IEnumerator with - member x.Current = - check started - (alreadyFinished() : obj) - member x.MoveNext() = - if not started then started <- true - false - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = () - - let Empty<'T> () = (new EmptyEnumerator<'T>() :> IEnumerator<'T>) - - let readAndClear r = - lock r (fun () -> match !r with None -> None | Some _ as res -> r := None; res) - - let generateWhileSome openf compute closef : IEnumerator<'U> = - let started = ref false - let curr = ref None - let state = ref (Some(openf())) - let getCurr() = - check !started - match !curr with None -> alreadyFinished() | Some x -> x - let start() = if not !started then (started := true) - - let dispose() = readAndClear state |> Option.iter closef - let finish() = (try dispose() finally curr := None) - { new IEnumerator<'U> with - member x.Current = getCurr() - interface IEnumerator with - member x.Current = box (getCurr()) - member x.MoveNext() = - start() - match !state with - | None -> false (* we started, then reached the end, then got another MoveNext *) - | Some s -> - match (try compute s with e -> finish(); reraise()) with - | None -> finish(); false - | Some _ as x -> curr := x; true - - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = dispose() } - - [] - type Singleton<'T>(v:'T) = - let mutable started = false - interface IEnumerator<'T> with - member x.Current = v - interface IEnumerator with - member x.Current = box v - member x.MoveNext() = if started then false else (started <- true; true) - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = () - - let Singleton x = (new Singleton<'T>(x) :> IEnumerator<'T>) - - let EnumerateThenFinally f (e : IEnumerator<'T>) = - { new IEnumerator<'T> with - member x.Current = e.Current - interface IEnumerator with - member x.Current = (e :> IEnumerator).Current - member x.MoveNext() = e.MoveNext() - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = - try - e.Dispose() - finally - f() - } - - -namespace Microsoft.FSharp.Core.CompilerServices - - open System - open System.Diagnostics - open Microsoft.FSharp.Core - open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators - open Microsoft.FSharp.Core.Operators - open Microsoft.FSharp.Control - open Microsoft.FSharp.Collections - open Microsoft.FSharp.Primitives.Basics - open System.Collections - open System.Collections.Generic - - 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 inline checkNonNull argName arg = - match box arg with - | null -> nullArg argName - | _ -> () - - let mkSeq f = - { new IEnumerable<'U> with - member x.GetEnumerator() = f() - interface IEnumerable with - member x.GetEnumerator() = (f() :> IEnumerator) } - - [] - type EmptyEnumerable<'T> = - | EmptyEnumerable - interface IEnumerable<'T> with - member x.GetEnumerator() = IEnumerator.Empty<'T>() - interface IEnumerable with - member x.GetEnumerator() = (IEnumerator.Empty<'T>() :> IEnumerator) - - let Generate openf compute closef = - mkSeq (fun () -> IEnumerator.generateWhileSome openf compute closef) - - let GenerateUsing (openf : unit -> ('U :> System.IDisposable)) compute = - Generate openf compute (fun (s:'U) -> s.Dispose()) - - let EnumerateFromFunctions opener moveNext current = - Generate - opener - (fun x -> if moveNext x then Some(current x) else None) - (fun x -> match box(x) with :? System.IDisposable as id -> id.Dispose() | _ -> ()) - - // A family of enumerators that can have additional 'finally' actions added to the enumerator through - // the use of mutation. This is used to 'push' the disposal action for a 'use' into the next enumerator. - // For example, - // seq { use x = ... - // while ... } - // results in the 'while' loop giving an adjustable enumerator. This is then adjusted by adding the disposal action - // from the 'use' into the enumerator. This means that we avoid constructing a two-deep enumerator chain in this - // common case. - type IFinallyEnumerator = - abstract AppendFinallyAction : (unit -> unit) -> unit - - /// A concrete implementation of IEnumerable that adds the given compensation to the "Dispose" chain of any - /// enumerators returned by the enumerable. - [] - type FinallyEnumerable<'T>(compensation: unit -> unit, restf: unit -> seq<'T>) = - interface IEnumerable<'T> with - member x.GetEnumerator() = - try - let ie = restf().GetEnumerator() - match ie with - | :? IFinallyEnumerator as a -> - a.AppendFinallyAction(compensation) - ie - | _ -> - IEnumerator.EnumerateThenFinally compensation ie - with e -> - compensation() - reraise() - interface IEnumerable with - member x.GetEnumerator() = ((x :> IEnumerable<'T>).GetEnumerator() :> IEnumerator) - - /// An optimized object for concatenating a sequence of enumerables - [] - type ConcatEnumerator<'T,'U when 'U :> seq<'T>>(sources: seq<'U>) = - let mutable outerEnum = sources.GetEnumerator() - let mutable currInnerEnum = IEnumerator.Empty() - - let mutable started = false - let mutable finished = false - let mutable compensations = [] - - [] // false = unchecked - val mutable private currElement : 'T - - member x.Finish() = - finished <- true - try - match currInnerEnum with - | null -> () - | _ -> - try - currInnerEnum.Dispose() - finally - currInnerEnum <- null - finally - try - match outerEnum with - | null -> () - | _ -> - try - outerEnum.Dispose() - finally - outerEnum <- null - finally - let rec iter comps = - match comps with - | [] -> () - | h::t -> - try h() finally iter t - try - compensations |> List.rev |> iter - finally - compensations <- [] - - member x.GetCurrent() = - IEnumerator.check started - if finished then IEnumerator.alreadyFinished() else x.currElement - - interface IFinallyEnumerator with - member x.AppendFinallyAction(f) = - compensations <- f :: compensations - - interface IEnumerator<'T> with - member x.Current = x.GetCurrent() - - interface IEnumerator with - member x.Current = box (x.GetCurrent()) - - member x.MoveNext() = - if not started then (started <- true) - if finished then false - else - let rec takeInner () = - // check the inner list - if currInnerEnum.MoveNext() then - x.currElement <- currInnerEnum.Current - true - else - // check the outer list - let rec takeOuter() = - if outerEnum.MoveNext() then - let ie = outerEnum.Current - // Optimization to detect the statically-allocated empty IEnumerables - match box ie with - | :? EmptyEnumerable<'T> -> - // This one is empty, just skip, don't call GetEnumerator, try again - takeOuter() - | _ -> - // OK, this one may not be empty. - // Don't forget to dispose of the enumerator for the inner list now we're done with it - currInnerEnum.Dispose() - currInnerEnum <- ie.GetEnumerator() - takeInner () - else - // We're done - x.Finish() - false - takeOuter() - takeInner () - - member x.Reset() = IEnumerator.noReset() - - interface System.IDisposable with - member x.Dispose() = - if not finished then - x.Finish() - - let EnumerateUsing (resource : 'T :> System.IDisposable) (rest: 'T -> #seq<'U>) = - (FinallyEnumerable((fun () -> match box resource with null -> () | _ -> resource.Dispose()), - (fun () -> rest resource :> seq<_>)) :> seq<_>) - - let mkConcatSeq (sources: seq<'U :> seq<'T>>) = - mkSeq (fun () -> new ConcatEnumerator<_,_>(sources) :> IEnumerator<'T>) - - let EnumerateWhile (g : unit -> bool) (b: seq<'T>) : seq<'T> = - let started = ref false - let curr = ref None - let getCurr() = - IEnumerator.check !started - match !curr with None -> IEnumerator.alreadyFinished() | Some x -> x - let start() = if not !started then (started := true) - - let finish() = (curr := None) - mkConcatSeq - (mkSeq (fun () -> - { new IEnumerator<_> with - member x.Current = getCurr() - interface IEnumerator with - member x.Current = box (getCurr()) - member x.MoveNext() = - start() - let keepGoing = (try g() with e -> finish (); reraise ()) in - if keepGoing then - curr := Some(b); true - else - finish(); false - member x.Reset() = IEnumerator.noReset() - interface System.IDisposable with - member x.Dispose() = () })) - - let EnumerateThenFinally (rest : seq<'T>) (compensation : unit -> unit) = - (FinallyEnumerable(compensation, (fun () -> rest)) :> seq<_>) - - let CreateEvent (add : 'Delegate -> unit) (remove : 'Delegate -> unit) (create : (obj -> 'Args -> unit) -> 'Delegate ) :IEvent<'Delegate,'Args> = - // Note, we implement each interface explicitly: this works around a bug in the CLR - // implementation on CompactFramework 3.7, used on Windows Phone 7 - { new obj() with - member x.ToString() = "" - interface IEvent<'Delegate,'Args> - interface IDelegateEvent<'Delegate> with - member x.AddHandler(h) = add h - member x.RemoveHandler(h) = remove h - interface System.IObservable<'Args> with - member x.Subscribe(r:IObserver<'Args>) = - let h = create (fun _ args -> r.OnNext(args)) - add h - { new System.IDisposable with - member x.Dispose() = remove h } } - - - [] - type GeneratedSequenceBase<'T>() = - let mutable redirectTo : GeneratedSequenceBase<'T> = Unchecked.defaultof<_> - let mutable redirect : bool = false - - abstract GetFreshEnumerator : unit -> IEnumerator<'T> - abstract GenerateNext : next:byref> -> int // 0 = Stop, 1 = Yield, 2 = Goto - abstract Close: unit -> unit - abstract CheckClose: bool - abstract LastGenerated : 'T - - //[] - member x.MoveNextImpl() = - let active = - if redirect then redirectTo - else x - let mutable target = null - match active.GenerateNext(&target) with - | 1 -> - true - | 2 -> - match target.GetEnumerator() with - | :? GeneratedSequenceBase<'T> as g when not active.CheckClose -> - redirectTo <- g - | e -> - redirectTo <- - { new GeneratedSequenceBase<'T>() with - member x.GetFreshEnumerator() = e - member x.GenerateNext(_) = if e.MoveNext() then 1 else 0 - member x.Close() = try e.Dispose() finally active.Close() - member x.CheckClose = true - member x.LastGenerated = e.Current } - redirect <- true - x.MoveNextImpl() - | _ (* 0 *) -> - false - - interface IEnumerable<'T> with - member x.GetEnumerator() = x.GetFreshEnumerator() - interface IEnumerable with - member x.GetEnumerator() = (x.GetFreshEnumerator() :> IEnumerator) - interface IEnumerator<'T> with - member x.Current = if redirect then redirectTo.LastGenerated else x.LastGenerated - member x.Dispose() = if redirect then redirectTo.Close() else x.Close() - interface IEnumerator with - member x.Current = box (if redirect then redirectTo.LastGenerated else x.LastGenerated) - - //[] - member x.MoveNext() = x.MoveNextImpl() - - member x.Reset() = raise <| new System.NotSupportedException() - - namespace Microsoft.FSharp.Collections open System @@ -419,6 +14,7 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Control open Microsoft.FSharp.Collections open Microsoft.FSharp.Primitives.Basics + open Microsoft.FSharp.Collections.IEnumerator [] type CachedSeq<'T>(cleanup,res:seq<'T>) = @@ -434,1300 +30,27 @@ namespace Microsoft.FSharp.Collections [] [] module Seq = - module Composer = - open IEnumerator - - module Internal = - type PipeIdx = int - type ``PipeIdx?`` = Nullable - let emptyPipeIdx = Nullable () - let inline getPipeIdx (maybePipeIdx:``PipeIdx?``) = if maybePipeIdx.HasValue then maybePipeIdx.Value else 1 - let inline makePipeIdx (pipeIdx:PipeIdx) = Nullable pipeIdx - - type ICompletionChaining = - abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit - - type IOutOfBand = - abstract StopFurtherProcessing : PipeIdx -> unit - - [] - type Consumer<'T,'U> () = - abstract ProcessNext : input:'T -> bool - - abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit - - default __.OnComplete _ = () - default __.OnDispose () = () - - interface ICompletionChaining with - member this.OnComplete terminatingIdx = - this.OnComplete terminatingIdx - - member this.OnDispose () = - try this.OnDispose () - finally () - - [] - 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 Folder<'T, 'U> = - inherit Consumer<'T,'T> - - val mutable Value : 'U - - new (init) = { - inherit Consumer<'T,'T>() - Value = init - } - - type ISeqFactory<'T,'U> = - abstract PipeIdx : PipeIdx - abstract Create<'V> : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> - - type ISeq<'T> = - inherit IEnumerable<'T> - abstract member Compose<'U> : (ISeqFactory<'T,'U>) -> ISeq<'U> - abstract member ForEach<'consumer when 'consumer :> Consumer<'T,'T>> : f:((unit->unit)->'consumer) -> 'consumer - - open Internal - - module Helpers = - // 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 avoidTailCall boolean = match boolean with true -> true | false -> false - - // 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 upcastSeq (t:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) - let inline upcastFactory (t:#ISeqFactory<'T,'U>) : ISeqFactory<'T,'U> = (# "" t : ISeqFactory<'T,'U> #) - let inline upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) - let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) - let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline upcastICompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) - - open Helpers - - type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = - new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) - - interface ISeqFactory<'T,'U> with - member __.PipeIdx = getPipeIdx pipeIdx - member __.Create<'V> (_:IOutOfBand) (_:``PipeIdx?``) (_:Consumer<'U,'V>) : Consumer<'T,'V> = failwith "library implementation error: Create on base factory should not be called" - - and ComposedFactory<'T,'U,'V> private (first:ISeqFactory<'T,'U>, second:ISeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = - inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) - - interface ISeqFactory<'T,'V> with - member this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = - first.Create outOfBand pipeIdx (second.Create outOfBand (makePipeIdx secondPipeIdx) next) - - static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = - ComposedFactory(first, second, first.PipeIdx+1) |> upcastFactory - - and ChooseFactory<'T,'U> (filter:'T->option<'U>) = - inherit SeqComponentFactory<'T,'U> () - interface ISeqFactory<'T,'U> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) - - and DistinctFactory<'T when 'T: equality> () = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) - - and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) - - and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) - - and FilterFactory<'T> (filter:'T->bool) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = - match next with - | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter - | _ -> upcast Filter (filter, next) - - and IdentityFactory<'T> () = - inherit SeqComponentFactory<'T,'T> () - static let singleton = IdentityFactory<'T>() - interface ISeqFactory<'T,'T> with - member __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next - static member Instance = singleton - - and MapFactory<'T,'U> (map:'T->'U) = - inherit SeqComponentFactory<'T,'U> () - interface ISeqFactory<'T,'U> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = - match next with - | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map - | _ -> upcast Map<_,_,_> (map, next) - - and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = - inherit SeqComponentFactory<'First,'U> () - interface ISeqFactory<'First,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, outOfBand, next, getPipeIdx pipeIdx) - - and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = - inherit SeqComponentFactory<'Second,'U> () - interface ISeqFactory<'Second,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, outOfBand, next, getPipeIdx pipeIdx) - - and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = - inherit SeqComponentFactory<'First,'U> () - interface ISeqFactory<'First,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, outOfBand, next, getPipeIdx pipeIdx) - - and MapiFactory<'T,'U> (mapi:int->'T->'U) = - inherit SeqComponentFactory<'T,'U> () - interface ISeqFactory<'T,'U> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) - - and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = - inherit SeqComponentFactory<'First,'U> () - interface ISeqFactory<'First,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, outOfBand, next, getPipeIdx pipeIdx) - - and PairwiseFactory<'T> () = - inherit SeqComponentFactory<'T,'T*'T> () - interface ISeqFactory<'T,'T*'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) - - and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = - inherit SeqComponentFactory<'T,'State> () - interface ISeqFactory<'T,'State> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) - - and SkipFactory<'T> (count:int) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) - - and SkipWhileFactory<'T> (predicate:'T->bool) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) - - and TakeWhileFactory<'T> (predicate:'T->bool) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, outOfBand, next, getPipeIdx pipeIdx) - - and TakeFactory<'T> (count:int) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, getPipeIdx pipeIdx) - - and TailFactory<'T> () = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) - - and TruncateFactory<'T> (count:int) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, getPipeIdx pipeIdx) - - and WindowedFactory<'T> (windowSize:int) = - inherit SeqComponentFactory<'T, 'T[]> () - interface ISeqFactory<'T, 'T[]> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T[],'V>) : Consumer<'T,'V> = upcast Windowed (windowSize, next) - - and [] SeqComponent<'T,'U> (next:ICompletionChaining) = - inherit Consumer<'T,'U>() - - // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip - // and it can only do it at the start of a sequence - abstract Skipping : unit -> bool - - abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> - abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> - - interface ICompletionChaining with - member this.OnComplete terminatingIdx = - this.OnComplete terminatingIdx - next.OnComplete terminatingIdx - member this.OnDispose () = - try this.OnDispose () - finally next.OnDispose () - - default __.Skipping () = false - - default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) - default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) - - and Choose<'T,'U,'V> (choose:'T->option<'U>, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - override __.ProcessNext (input:'T) : bool = - match choose input with - | Some value -> avoidTailCall (next.ProcessNext value) - | None -> false - - and Distinct<'T,'V when 'T: equality> (next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) - - override __.ProcessNext (input:'T) : bool = - if hashSet.Add input then - avoidTailCall (next.ProcessNext input) - else - false - - and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) - - override __.ProcessNext (input:'T) : bool = - if hashSet.Add(keyFunction input) then - avoidTailCall (next.ProcessNext input) - else - false - - and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) - - override __.ProcessNext (input:'T) : bool = - if cached.Value.Add input then - avoidTailCall (next.ProcessNext input) - else - false - - and Filter<'T,'V> (filter:'T->bool, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) - - override __.ProcessNext (input:'T) : bool = - if filter input then - avoidTailCall (next.ProcessNext input) - else - false - - and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - override __.ProcessNext (input:'T) : bool = - if filter input then - avoidTailCall (next.ProcessNext (map input)) - else - false - - and Map<'T,'U,'V> (map:'T->'U, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) - - override __.ProcessNext (input:'T) : bool = - avoidTailCall (next.ProcessNext (map input)) - - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(next) - - let input2 = enumerable2.GetEnumerator () - let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map - - override __.ProcessNext (input:'First) : bool = - if input2.MoveNext () then - avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - override __.OnDispose () = - input2.Dispose () - - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'Second,'V>(next) - - let input1 = enumerable1.GetEnumerator () - let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map - - override __.ProcessNext (input:'Second) : bool = - if input1.MoveNext () then - avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - override __.OnDispose () = - input1.Dispose () - - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(next) - - let input2 = enumerable2.GetEnumerator () - let input3 = enumerable3.GetEnumerator () - let map' = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt map - - override __.ProcessNext (input:'First) : bool = - if input2.MoveNext () && input3.MoveNext () then - avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - override __.OnDispose () = - try input2.Dispose () - finally input3.Dispose () - - and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - override __.ProcessNext (input:'T) : bool = - let u = map input - if filter u then - avoidTailCall (next.ProcessNext u) - else - false - - and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - let mutable idx = 0 - let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi - - override __.ProcessNext (input:'T) : bool = - idx <- idx + 1 - avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) - - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(next) - - let mutable idx = 0 - let input2 = enumerable2.GetEnumerator () - let mapi2' = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt map - - override __.ProcessNext (input:'First) : bool = - if input2.MoveNext () then - idx <- idx + 1 - avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - override __.OnDispose () = - input2.Dispose () - - and Pairwise<'T,'V> (next:Consumer<'T*'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let mutable isFirst = true - let mutable lastValue = Unchecked.defaultof<'T> - - override __.ProcessNext (input:'T) : bool = - if isFirst then - lastValue <- input - isFirst <- false - false - else - let currentPair = lastValue, input - lastValue <- input - avoidTailCall (next.ProcessNext currentPair) - - and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:Consumer<'State,'V>) = - inherit SeqComponent<'T,'V>(next) - - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - let mutable foldResult = initialState - - override __.ProcessNext (input:'T) : bool = - foldResult <- f.Invoke(foldResult, input) - avoidTailCall (next.ProcessNext foldResult) - - and Skip<'T,'V> (skipCount:int, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let mutable count = 0 - - override __.Skipping () = - if count < skipCount then - count <- count + 1 - true - else - false - - override __.ProcessNext (input:'T) : bool = - if count < skipCount then - count <- count + 1 - false - else - avoidTailCall (next.ProcessNext input) - - override __.OnComplete _ = - if count < skipCount then - let x = skipCount - count - invalidOpFmt "tried to skip {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - - and SkipWhile<'T,'V> (predicate:'T->bool, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let mutable skip = true - - override __.ProcessNext (input:'T) : bool = - if skip then - skip <- predicate input - if skip then - false - else - avoidTailCall (next.ProcessNext input) - else - avoidTailCall (next.ProcessNext input) - - and Take<'T,'V> (takeCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipelineIdx:int) = - inherit Truncate<'T, 'V>(takeCount, outOfBand, next, pipelineIdx) - - override this.OnComplete terminatingIdx = - if terminatingIdx < pipelineIdx && this.Count < takeCount then - let x = takeCount - this.Count - invalidOpFmt "tried to take {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - - and TakeWhile<'T,'V> (predicate:'T->bool, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = - inherit SeqComponent<'T,'V>(next) - - override __.ProcessNext (input:'T) : bool = - if predicate input then - avoidTailCall (next.ProcessNext input) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - and Tail<'T, 'V> (next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let mutable first = true - - override __.ProcessNext (input:'T) : bool = - if first then - first <- false - false - else - avoidTailCall (next.ProcessNext input) - - override this.OnComplete _ = - if first then - invalidArg "source" (SR.GetString(SR.notEnoughElements)) - - and Truncate<'T,'V> (truncateCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = - inherit SeqComponent<'T,'V>(next) - - let mutable count = 0 - - member __.Count = count - - override __.ProcessNext (input:'T) : bool = - if count < truncateCount then - count <- count + 1 - if count = truncateCount then - outOfBand.StopFurtherProcessing pipeIdx - avoidTailCall (next.ProcessNext input) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - and Windowed<'T,'V> (windowSize: int, next:Consumer<'T[],'V>) = - inherit SeqComponent<'T,'V>(next) - - let circularBuffer = Array.zeroCreateUnchecked windowSize - let mutable idx = 0 - - let mutable priming = windowSize - 1 - - override __.ProcessNext (input:'T) : bool = - circularBuffer.[idx] <- input - - idx <- idx + 1 - if idx = windowSize then - idx <- 0 - - if priming > 0 then - priming <- priming - 1 - false - else - if windowSize < 32 then - let window = Array.init windowSize (fun i -> circularBuffer.[(idx+i) % windowSize]) - avoidTailCall (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) - avoidTailCall (next.ProcessNext window) - - type SeqProcessNextStates = - | InProcess = 0 - | NotStarted = 1 - | Finished = 2 - - type Result<'T>() = - let mutable haltedIdx = 0 - - member val Current = Unchecked.defaultof<'T> with get, set - member val SeqState = SeqProcessNextStates.NotStarted with get, set - member __.HaltedIdx = haltedIdx - - interface IOutOfBand with - member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx - - // SetResult<> is used at the end of the chain of SeqComponents to assign the final value - type SetResult<'T> (result:Result<'T>) = - inherit Consumer<'T,'T>() - - override __.ProcessNext (input:'T) : bool = - result.Current <- input - true - - type OutOfBand() = - let mutable haltedIdx = 0 - interface IOutOfBand with member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx - member __.HaltedIdx = haltedIdx - - module ForEach = - let enumerable (enumerable:IEnumerable<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = - use enumerator = enumerable.GetEnumerator () - while (outOfBand.HaltedIdx = 0) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - - let array (array:array<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = - let mutable idx = 0 - while (outOfBand.HaltedIdx = 0) && (idx < array.Length) do - consumer.ProcessNext array.[idx] |> ignore - idx <- idx + 1 - - let list (alist:list<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = - let rec iterate lst = - match outOfBand.HaltedIdx, lst with - | 0, hd :: tl -> - consumer.ProcessNext hd |> ignore - iterate tl - | _ -> () - iterate alist - - let unfold (generator:'S->option<'T*'S>) state (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = - let rec iterate current = - match outOfBand.HaltedIdx, generator current with - | 0, Some (item, next) -> - consumer.ProcessNext item |> ignore - iterate next - | _ -> () - - iterate state - - let makeIsSkipping (consumer:Consumer<'T,'U>) = - match consumer with - | :? SeqComponent<'T,'U> as c -> c.Skipping - | _ -> fun () -> false - - let init f (terminatingIdx:int) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = - let mutable idx = -1 - let isSkipping = makeIsSkipping consumer - let mutable maybeSkipping = true - while (outOfBand.HaltedIdx = 0) && (idx < terminatingIdx) do - if maybeSkipping then - maybeSkipping <- isSkipping () - - if (not maybeSkipping) then - consumer.ProcessNext (f (idx+1)) |> ignore - - idx <- idx + 1 - - let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:ISeqFactory<'T,'U>) executeOn = - let pipeline = OutOfBand() - let result = f (fun () -> (pipeline:>IOutOfBand).StopFurtherProcessing (current.PipeIdx+1)) - let consumer = current.Create pipeline emptyPipeIdx result - try - executeOn pipeline consumer - (upcastICompletionChaining consumer).OnComplete pipeline.HaltedIdx - result - finally - (upcastICompletionChaining consumer).OnDispose () - - 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>, seqComponent:ICompletionChaining) = - interface IDisposable with - member __.Dispose() : unit = - seqComponent.OnDispose () - - interface IEnumerator with - member this.Current : obj = box ((upcastEnumerator 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.Current - 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<'T> : (seq<'T>) -> IEnumerable<'T> - - default this.Append source = upcastEnumerable (AppendEnumerable [this; source]) - - interface IEnumerable with - member this.GetEnumerator () : IEnumerator = - let genericEnumerable = upcastEnumerable this - let genericEnumerator = genericEnumerable.GetEnumerator () - upcastEnumeratorNonGeneric genericEnumerator - - interface IEnumerable<'T> with - member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () - - interface ISeq<'T> with - member __.Compose _ = derivedClassShouldImplement () - member __.ForEach _ = derivedClassShouldImplement () - - and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, seqComponent) - - let rec moveNext () = - if (result.HaltedIdx = 0) && source.MoveNext () then - if seqComponent.ProcessNext source.Current then - true - else - moveNext () - else - result.SeqState <- SeqProcessNextStates.Finished - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () - - interface IDisposable with - member __.Dispose() = - try - source.Dispose () - finally - (upcastICompletionChaining seqComponent).OnDispose () - - and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:ISeqFactory<'T,'U>) = - inherit EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) - - interface ISeq<'U> with - member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.enumerable enumerable) - - 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 = - match state with - | SeqProcessNextStates.NotStarted -> notStarted() - | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> active.Current - - interface IEnumerator with - member this.Current = box ((upcastEnumerator 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> = - upcastEnumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) - - override this.Append source = - upcastEnumerable (AppendEnumerable (source :: sources)) - - interface ISeq<'T> with - member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable<'T,'V>(this, next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.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> = - upcastEnumerator (new ConcatEnumerator<_,_> (sources)) - - interface ISeq<'T> with - member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable<'T,'V>(this, next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) - - let create enumerable current = - upcastSeq (Enumerable(enumerable, current)) - - 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 = - upcastEnumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) - - interface ISeq<'T> with - member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable.Enumerable<'T,'V>(this, next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) - - - - module Array = - type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) - - let mutable idx = 0 - let mutable array = Unchecked.defaultof<_> - - let mutable initMoveNext = Unchecked.defaultof<_> - do - initMoveNext <- - fun () -> - result.SeqState <- SeqProcessNextStates.InProcess - array <- delayedArray () - initMoveNext <- ignore - - let rec moveNext () = - if (result.HaltedIdx = 0) && idx < array.Length then - idx <- idx+1 - if seqComponent.ProcessNext array.[idx-1] then - true - else - moveNext () - else - result.SeqState <- SeqProcessNextStates.Finished - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - initMoveNext () - moveNext () - - type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:ISeqFactory<'T,'U>) = - inherit Enumerable.EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - - interface ISeq<'U> with - member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.array (delayedArray ())) - - let createDelayed (delayedArray:unit->array<'T>) (current:ISeqFactory<'T,'U>) = - upcastSeq (Enumerable(delayedArray, current)) - - let create (array:array<'T>) (current:ISeqFactory<'T,'U>) = - createDelayed (fun () -> array) current - - let createDelayedId (delayedArray:unit -> array<'T>) = - createDelayed delayedArray IdentityFactory.Instance - - let createId (array:array<'T>) = - create array IdentityFactory.Instance - - module List = - type Enumerator<'T,'U>(alist:list<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) - - let mutable list = alist - - let rec moveNext current = - match result.HaltedIdx, current with - | 0, head::tail -> - if seqComponent.ProcessNext head then - list <- tail - true - else - moveNext tail - | _ -> - result.SeqState <- SeqProcessNextStates.Finished - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext list - - type Enumerable<'T,'U>(alist:list<'T>, current:ISeqFactory<'T,'U>) = - inherit Enumerable.EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - - interface ISeq<'U> with - member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.list alist) - - let create alist current = - upcastSeq (Enumerable(alist, current)) - - module Unfold = - type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) - - let mutable current = state - - let rec moveNext () = - match result.HaltedIdx, generator current with - | 0, Some (item, nextState) -> - current <- nextState - if seqComponent.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, current:ISeqFactory<'T,'U>) = - inherit Enumerable.EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - - interface ISeq<'U> with - member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.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. - type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) - - 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, seqComponent:Consumer<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) - - let isSkipping = - ForEach.makeIsSkipping seqComponent - - 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 seqComponent.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 - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () - - type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:ISeqFactory<'T,'U>) = - inherit Enumerable.EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - - interface ISeq<'U> with - member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) - - member this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = - let terminatingIdx = getTerminatingIdx count - ForEach.execute createResult current (ForEach.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 self.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = () } - - type EnumerableDecider<'T>(count:Nullable, f:int->'T) = - 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.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable<'T,'V>(count, f, next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (upcastEnumerable this)) - - open RuntimeHelpers - - [] - let toComposer (source:seq<'T>) : ISeq<'T> = - checkNonNull "source" source - match source with - | :? ISeq<'T> as s -> s - | :? array<'T> as a -> upcastSeq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) - | :? list<'T> as a -> upcastSeq (List.Enumerable(a, IdentityFactory.Instance)) - | _ -> upcastSeq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) - - let inline foreach f (source:ISeq<_>) = - source.ForEach f - - let inline compose factory (source:ISeq<'T>) = - source.Compose factory - - [] - let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance - - [] - let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = - upcastSeq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) - - [] - let initInfinite<'T> (f:int->'T) : ISeq<'T> = - upcastSeq (new Init.EnumerableDecider<'T>(Nullable (), f)) - - [] - let init<'T> (count:int) (f:int->'T) : ISeq<'T> = - if count < 0 then invalidArgInputMustBeNonNegative "count" count - elif count = 0 then empty else - upcastSeq (new Init.EnumerableDecider<'T>(Nullable count, f)) - - [] - let iter f (source:ISeq<'T>) = - source - |> foreach (fun _ -> - { new Consumer<'T,'T> () with - override this.ProcessNext value = - f value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> ignore - - [] - let tryItem i (source:ISeq<'T>) = - if i < 0 then None else - source - |> foreach (fun halt -> - { new Folder<'T, Values>> (Values<_,_> (0, None)) with - override this.ProcessNext value = - if this.Value._1 = i then - this.Value._2 <- Some value - halt () - else - this.Value._1 <- this.Value._1 + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun item -> item.Value._2 - - [] - let iteri f (source:ISeq<'T>) = - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f - - source - |> foreach (fun _ -> - { new Folder<'T, int> (0) with - override this.ProcessNext value = - f.Invoke(this.Value, value) - this.Value <- this.Value + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> ignore - - [] - let exists f (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, bool> (false) with - override this.ProcessNext value = - if f value then - this.Value <- true - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun exists -> exists.Value - - [] - let inline contains element (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, bool> (false) with - override this.ProcessNext value = - if element = value then - this.Value <- true - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun contains -> contains.Value - - [] - let forall f (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, bool> (true) with - override this.ProcessNext value = - if not (f value) then - this.Value <- false - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun forall -> forall.Value - - [] - let filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source - |> compose (FilterFactory f) - - [] - let map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = - source - |> compose (MapFactory f) - - [] - let mapi f source = - source - |> compose (MapiFactory f) - - [] - let choose f source = - source - |> compose (ChooseFactory f) - - [] - let indexed source = - source - |> compose (MapiFactory (fun i x -> i,x)) - - [] - let tryPick f (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, Option<'U>> (None) with - override this.ProcessNext value = - match f value with - | (Some _) as some -> - this.Value <- some - halt () - | None -> () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun pick -> pick.Value - - [] - let tryFind f (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, Option<'T>> (None) with - override this.ProcessNext value = - if f value then - this.Value <- Some value - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun find -> find.Value - - #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions #else #endif - open Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers - let mkDelayedSeq (f: unit -> IEnumerable<'T>) = mkSeq (fun () -> f().GetEnumerator()) let inline indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) [] - let toComposer (source:seq<'T>): Composer.Internal.ISeq<'T> = - Composer.toComposer source + let toComposer (source:seq<'T>): Composer.Core.ISeq<'T> = + Composer.Seq.toComposer source let inline foreach f (source:seq<_>) = - Composer.foreach f (toComposer source) + Composer.Seq.foreach f (toComposer source) [] let delay f = mkDelayedSeq f [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : seq<'T> = - Composer.unfold generator state + Composer.Seq.unfold generator state |> Composer.Helpers.upcastEnumerable [] @@ -1735,24 +58,24 @@ namespace Microsoft.FSharp.Collections [] let initInfinite<'T> (f:int->'T) : IEnumerable<'T> = - Composer.initInfinite f + Composer.Seq.initInfinite f |> Composer.Helpers.upcastEnumerable [] let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> = - Composer.init count f + Composer.Seq.init count f |> Composer.Helpers.upcastEnumerable [] let iter f (source : seq<'T>) = - Composer.iter f (toComposer source) + Composer.Seq.iter f (toComposer source) [] let item i (source : seq<'T>) = if i < 0 then invalidArgInputMustBeNonNegative "index" i else source |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values<_,_,_> (0, false, Unchecked.defaultof<'T>)) with + { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values<_,_,_> (0, false, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 = i then this.Value._2 <- true @@ -1772,26 +95,26 @@ namespace Microsoft.FSharp.Collections [] let tryItem i (source:seq<'T>) = - Composer.tryItem i (toComposer source) + Composer.Seq.tryItem i (toComposer source) [] let nth i (source : seq<'T>) = item i source [] let iteri f (source:seq<'T>) = - Composer.iteri f (toComposer source) + Composer.Seq.iteri f (toComposer source) [] let exists f (source:seq<'T>) = - Composer.exists f (toComposer source) + Composer.Seq.exists f (toComposer source) [] let inline contains element (source:seq<'T>) = - Composer.contains element (toComposer source) + Composer.Seq.contains element (toComposer source) [] let forall f (source:seq<'T>) = - Composer.forall f (toComposer source) + Composer.Seq.forall f (toComposer source) [] let iter2 f (source1 : seq<_>) (source2 : seq<_>) = @@ -1802,7 +125,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<_,_> () with + { new Composer.Core.Folder<_,_> () with override this.ProcessNext value = if (e2.MoveNext()) then f.Invoke(value, e2.Current) @@ -1820,7 +143,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<_,int> (0) with + { new Composer.Core.Folder<_,int> (0) with override this.ProcessNext value = if (e2.MoveNext()) then f.Invoke(this.Value, value, e2.Current) @@ -1840,14 +163,14 @@ namespace Microsoft.FSharp.Collections let private seqFactory createSeqComponent (source:seq<'T>) = checkNonNull "source" source match source with - | :? Composer.Internal.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose createSeqComponent) - | :? array<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.Array.create a createSeqComponent) - | :? list<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.List.create a createSeqComponent) - | _ -> Composer.Helpers.upcastEnumerable (Composer.Enumerable.create source createSeqComponent) + | :? Composer.Core.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose createSeqComponent) + | :? array<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.Seq.Array.create a createSeqComponent) + | :? list<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.Seq.List.create a createSeqComponent) + | _ -> Composer.Helpers.upcastEnumerable (Composer.Seq.Enumerable.create source createSeqComponent) [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = - Composer.filter f (toComposer source) + Composer.Seq.filter f (toComposer source) |> Composer.Helpers.upcastEnumerable [] @@ -1855,40 +178,40 @@ namespace Microsoft.FSharp.Collections [] let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> = - Composer.map f (toComposer source) + Composer.Seq.map f (toComposer source) |> Composer.Helpers.upcastEnumerable [] let mapi f source = - Composer.mapi f (toComposer source) + Composer.Seq.mapi f (toComposer source) |> Composer.Helpers.upcastEnumerable [] let mapi2 f source1 source2 = checkNonNull "source2" source2 - source1 |> seqFactory (Composer.Mapi2Factory (f, source2)) + source1 |> seqFactory (Composer.Seq.Mapi2Factory (f, source2)) [] let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = checkNonNull "source1" source1 match source1 with - | :? Composer.Internal.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose (Composer.Map2FirstFactory (f, source2))) - | _ -> source2 |> seqFactory (Composer.Map2SecondFactory (f, source1)) + | :? Composer.Core.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose (Composer.Seq.Map2FirstFactory (f, source2))) + | _ -> source2 |> seqFactory (Composer.Seq.Map2SecondFactory (f, source1)) [] let map3 f source1 source2 source3 = checkNonNull "source2" source2 checkNonNull "source3" source3 - source1 |> seqFactory (Composer.Map3Factory (f, source2, source3)) + source1 |> seqFactory (Composer.Seq.Map3Factory (f, source2, source3)) [] let choose f source = - Composer.choose f (toComposer source) + Composer.Seq.choose f (toComposer source) |> Composer.Helpers.upcastEnumerable [] let indexed source = - Composer.indexed (toComposer source) + Composer.Seq.indexed (toComposer source) |> Composer.Helpers.upcastEnumerable [] @@ -1906,7 +229,7 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source : seq<'T>) = - Composer.tryPick f (toComposer source) + Composer.Seq.tryPick f (toComposer source) [] let pick f source = @@ -1916,7 +239,7 @@ namespace Microsoft.FSharp.Collections [] let tryFind f (source : seq<'T>) = - Composer.tryFind f (toComposer source) + Composer.Seq.tryFind f (toComposer source) [] let find f source = @@ -1929,7 +252,7 @@ namespace Microsoft.FSharp.Collections if count < 0 then invalidArgInputMustBeNonNegative "count" count (* Note: don't create or dispose any IEnumerable if n = 0 *) if count = 0 then empty else - source |> seqFactory (Composer.TakeFactory count) + source |> seqFactory (Composer.Seq.TakeFactory count) [] let isEmpty (source : seq<'T>) = @@ -1945,7 +268,7 @@ namespace Microsoft.FSharp.Collections [] let concat (sources:seq<#seq<'T>>) : seq<'T> = checkNonNull "sources" sources - upcast Composer.Enumerable.ConcatEnumerable sources + upcast Composer.Seq.Enumerable.ConcatEnumerable sources [] let length (source : seq<'T>) = @@ -1967,7 +290,7 @@ namespace Microsoft.FSharp.Collections source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T,'State> (x) with + { new Composer.Core.Folder<'T,'State> (x) with override this.ProcessNext value = this.Value <- f.Invoke (this.Value, value) Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) @@ -1982,7 +305,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<_,'State> (state) with + { new Composer.Core.Folder<_,'State> (state) with override this.ProcessNext value = if (e2.MoveNext()) then this.Value <- f.Invoke(this.Value, value, e2.Current) @@ -1997,7 +320,7 @@ namespace Microsoft.FSharp.Collections source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values<_,_>(true, Unchecked.defaultof<'T>)) with + { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2021,8 +344,8 @@ namespace Microsoft.FSharp.Collections checkNonNull "source1" source1 checkNonNull "source2" source2 match source1 with - | :? Composer.Enumerable.EnumerableBase<'T> as s -> s.Append source2 - | _ -> Composer.Helpers.upcastEnumerable (new Composer.Enumerable.AppendEnumerable<_>([source2; source1])) + | :? Composer.Seq.Enumerable.EnumerableBase<'T> as s -> s.Append source2 + | _ -> Composer.Helpers.upcastEnumerable (new Composer.Seq.Enumerable.AppendEnumerable<_>([source2; source1])) [] @@ -2037,7 +360,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<'T,int> (0) with + { new Composer.Core.Folder<'T,int> (0) with override this.ProcessNext value = if not (e2.MoveNext()) then this.Value <- 1 @@ -2066,7 +389,7 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source : 'T array) = checkNonNull "source" source - Composer.Helpers.upcastEnumerable (Composer.Array.createId source) + Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createId source) [] let toArray (source : seq<'T>) = @@ -2120,17 +443,17 @@ namespace Microsoft.FSharp.Collections [] let truncate n (source: seq<'T>) = if n <= 0 then empty else - source |> seqFactory (Composer.TruncateFactory n) + source |> seqFactory (Composer.Seq.TruncateFactory n) [] let pairwise<'T> (source:seq<'T>) : seq<'T*'T> = - source |> seqFactory (Composer.PairwiseFactory ()) + source |> seqFactory (Composer.Seq.PairwiseFactory ()) [] let scan<'T,'State> f (z:'State) (source : seq<'T>): seq<'State> = let first = [|z|] :> IEnumerable<'State> - let rest = source |> seqFactory (Composer.ScanFactory (f, z)) - upcast Composer.Enumerable.ConcatEnumerable [|first; rest;|] + let rest = source |> seqFactory (Composer.Seq.ScanFactory (f, z)) + upcast Composer.Seq.Enumerable.ConcatEnumerable [|first; rest;|] [] let tryFindBack f (source : seq<'T>) = @@ -2154,7 +477,7 @@ namespace Microsoft.FSharp.Collections let tryFindIndex p (source:seq<_>) = source |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Composer.Internal.Values, int>> (Composer.Internal.Values<_,_>(None, 0)) with + { new Composer.Core.Folder<'T, Composer.Core.Values, int>> (Composer.Core.Values<_,_>(None, 0)) with override this.ProcessNext value = if p value then this.Value._1 <- Some(this.Value._2) @@ -2185,7 +508,7 @@ namespace Microsoft.FSharp.Collections let windowed windowSize (source: seq<_>) = if windowSize <= 0 then invalidArgFmt "windowSize" "{0}\nwindowSize = {1}" [|SR.GetString SR.inputMustBePositive; windowSize|] - source |> seqFactory (Composer.WindowedFactory (windowSize)) + source |> seqFactory (Composer.Seq.WindowedFactory (windowSize)) [] let cache (source : seq<'T>) = @@ -2289,7 +612,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 StructBox<'Key>.Comparer (fun t -> StructBox (keyf t)) (fun sb -> sb.Value) + let groupByRefType (keyf:'T->'Key) (seq:seq<'T>) = seq |> groupByImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun t -> RuntimeHelpers.StructBox (keyf t)) (fun sb -> sb.Value) [] let groupBy (keyf:'T->'Key) (seq:seq<'T>) = @@ -2303,11 +626,11 @@ namespace Microsoft.FSharp.Collections [] let distinct source = - source |> seqFactory (Composer.DistinctFactory ()) + source |> seqFactory (Composer.Seq.DistinctFactory ()) [] let distinctBy keyf source = - source |> seqFactory (Composer.DistinctByFactory keyf) + source |> seqFactory (Composer.Seq.DistinctByFactory keyf) [] let sortBy keyf source = @@ -2316,7 +639,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceBy keyf array array - Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedSort) + Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedSort) [] let sort source = @@ -2325,7 +648,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlace array array - Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedSort) + Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedSort) [] let sortWith f source = @@ -2334,7 +657,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceWith f array array - Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedSort) + Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedSort) [] let inline sortByDescending keyf source = @@ -2367,7 +690,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 StructBox<'Key>.Comparer (fun t -> StructBox (keyf t)) (fun sb -> sb.Value) + 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 countBy (keyf:'T->'Key) (source:seq<'T>) = @@ -2385,7 +708,7 @@ namespace Microsoft.FSharp.Collections let inline sum (source:seq<'a>) : 'a = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'a,'a> (LanguagePrimitives.GenericZero) with + { new Composer.Core.Folder<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value value Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) @@ -2395,7 +718,7 @@ namespace Microsoft.FSharp.Collections let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + { new Composer.Core.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value (f value) Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) @@ -2405,7 +728,7 @@ namespace Microsoft.FSharp.Collections let inline average (source: seq< ^a>) : ^a = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'a, Composer.Internal.Values<'a, int>> (Composer.Internal.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + { new Composer.Core.Folder<'a, Composer.Core.Values<'a, int>> (Composer.Core.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 value this.Value._2 <- this.Value._2 + 1 @@ -2420,7 +743,7 @@ namespace Microsoft.FSharp.Collections let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T,Composer.Internal.Values<'U, int>> (Composer.Internal.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + { new Composer.Core.Folder<'T,Composer.Core.Values<'U, int>> (Composer.Core.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 (f value) this.Value._2 <- this.Value._2 + 1 @@ -2435,7 +758,7 @@ namespace Microsoft.FSharp.Collections let inline min (source: seq<_>) = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_>(true, Unchecked.defaultof<'T>)) with + { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2454,7 +777,7 @@ namespace Microsoft.FSharp.Collections let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with override this.ProcessNext value = match this.Value._1, f value with | true, valueU -> @@ -2493,7 +816,7 @@ namespace Microsoft.FSharp.Collections let inline max (source: seq<_>) = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_>(true, Unchecked.defaultof<'T>)) with + { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2512,7 +835,7 @@ namespace Microsoft.FSharp.Collections let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with override this.ProcessNext value = match this.Value._1, f value with | true, valueU -> @@ -2550,15 +873,15 @@ namespace Microsoft.FSharp.Collections *) [] let takeWhile p (source: seq<_>) = - source |> seqFactory (Composer.TakeWhileFactory p) + source |> seqFactory (Composer.Seq.TakeWhileFactory p) [] let skip count (source: seq<_>) = - source |> seqFactory (Composer.SkipFactory count) + source |> seqFactory (Composer.Seq.SkipFactory count) [] let skipWhile p (source: seq<_>) = - source |> seqFactory (Composer.SkipWhileFactory p) + source |> seqFactory (Composer.Seq.SkipWhileFactory p) [] let forall2 p (source1: seq<_>) (source2: seq<_>) = @@ -2569,7 +892,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<_,bool> (true) with + { new Composer.Core.Folder<_,bool> (true) with override this.ProcessNext value = if (e2.MoveNext()) then if not (p.Invoke(value, e2.Current)) then @@ -2589,7 +912,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<_,bool> (false) with + { new Composer.Core.Folder<_,bool> (false) with override this.ProcessNext value = if (e2.MoveNext()) then if p.Invoke(value, e2.Current) then @@ -2604,7 +927,7 @@ namespace Microsoft.FSharp.Collections let tryHead (source : seq<_>) = source |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Option<'T>> (None) with + { new Composer.Core.Folder<'T, Option<'T>> (None) with override this.ProcessNext value = this.Value <- Some value halt () @@ -2619,13 +942,13 @@ namespace Microsoft.FSharp.Collections [] let tail (source: seq<'T>) = - source |> seqFactory (Composer.TailFactory ()) + source |> seqFactory (Composer.Seq.TailFactory ()) [] let tryLast (source : seq<_>) = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values(true, Unchecked.defaultof<'T>)) with + { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2647,7 +970,7 @@ namespace Microsoft.FSharp.Collections let exactlyOne (source : seq<_>) = source |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values(true, Unchecked.defaultof<'T>, false)) with + { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values(true, Unchecked.defaultof<'T>, false)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2671,7 +994,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.Reverse array array - Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedReverse) + Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedReverse) [] let permute f (source:seq<_>) = @@ -2680,7 +1003,7 @@ namespace Microsoft.FSharp.Collections source |> toArray |> Array.permute f - Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedPermute) + Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedPermute) [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = @@ -2698,7 +1021,7 @@ namespace Microsoft.FSharp.Collections [] let except (itemsToExclude: seq<'T>) (source: seq<'T>) = checkNonNull "itemsToExclude" itemsToExclude - source |> seqFactory (Composer.ExceptFactory itemsToExclude) + source |> seqFactory (Composer.Seq.ExceptFactory itemsToExclude) [] let chunkBySize chunkSize (source : seq<_>) = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 94dbb8bcc1a..f06c676e4de 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -13,75 +13,6 @@ namespace Microsoft.FSharp.Collections [] [] module Seq = - module Composer = - module Internal = - /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the - /// source of the chain. - type PipeIdx = int - type ``PipeIdx?`` = Nullable - - /// ICompletionChaining is used to correctly handle cleaning up of the pipeline. A - /// base implementation is provided in Consumer, and should not be overwritten. Consumer - /// provides it's own OnComplete and OnDispose function which should be used to handle - /// a particular consumers cleanup. - type ICompletionChaining = - /// OnComplete is used to determine if the object has been processed correctly, - /// and possibly throw exceptions to denote incorrect application (i.e. such as a Take - /// operation which didn't have a source at least as large as was required). It is - /// not called in the case of an exception being thrown whilst the stream is still - /// being processed. - abstract OnComplete : PipeIdx -> unit - /// OnDispose is used to cleanup the stream. It is always called at the last operation - /// after the enumeration has completed. - abstract OnDispose : unit -> unit - - type IOutOfBand = - abstract StopFurtherProcessing : PipeIdx -> unit - - /// Consumer is the base class of all elements within the pipeline - [] - type Consumer<'T,'U> = - interface ICompletionChaining - new : unit -> Consumer<'T,'U> - abstract member ProcessNext : input:'T -> bool - abstract member OnComplete : PipeIdx -> unit - abstract member OnDispose : unit -> unit - - /// 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 - - /// 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 ForEach function. - [] - type Folder<'T,'U> = - inherit Consumer<'T,'T> - new : init:'U -> Folder<'T,'U> - val mutable Value: 'U - - type ISeqFactory<'T,'U> = - abstract member Create : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> - abstract member PipeIdx : PipeIdx - - type ISeq<'T> = - inherit System.Collections.Generic.IEnumerable<'T> - abstract member Compose : ISeqFactory<'T,'U> -> ISeq<'U> - abstract member ForEach : f:((unit -> unit) -> 'a) -> 'a when 'a :> Consumer<'T,'T> - /// Returns a new sequence that contains the cartesian product of the two input sequences. /// The first sequence. /// The second sequence. @@ -1273,7 +1204,7 @@ namespace Microsoft.FSharp.Collections /// /// Thrown when the input sequence is null. [] - val toComposer : source:seq<'T> -> Composer.Internal.ISeq<'T> + val toComposer : source:seq<'T> -> Composer.Core.ISeq<'T> /// Builds a list from the given collection. /// @@ -1419,98 +1350,4 @@ namespace Microsoft.FSharp.Collections /// /// Thrown when any of the input sequences is null. [] - val zip3: source1:seq<'T1> -> source2:seq<'T2> -> source3:seq<'T3> -> seq<'T1 * 'T2 * 'T3> - -namespace Microsoft.FSharp.Core.CompilerServices - - open System - open System.Collections - open System.Collections.Generic - open Microsoft.FSharp.Core - open Microsoft.FSharp.Collections - - - [] - /// 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> - - /// The F# compiler emits calls to this function to - /// implement the while operator for F# sequence expressions. - /// - /// A function that indicates whether iteration should continue. - /// The input sequence. - /// - /// The result sequence. - val EnumerateWhile : guard:(unit -> bool) -> source:seq<'T> -> seq<'T> - - /// The F# compiler emits calls to this function to - /// implement the try/finally operator for F# sequence expressions. - /// - /// The input sequence. - /// A computation to be included in an enumerator's Dispose method. - /// - /// The result sequence. - val EnumerateThenFinally : source:seq<'T> -> compensation:(unit -> unit) -> seq<'T> - - /// The F# compiler emits calls to this function to implement the compiler-intrinsic - /// conversions from untyped System.Collections.IEnumerable sequences to typed sequences. - /// - /// An initializer function. - /// A function to iterate and test if end of sequence is reached. - /// A function to retrieve the current element. - /// - /// The resulting typed sequence. - val EnumerateFromFunctions: create:(unit -> 'T) -> moveNext:('T -> bool) -> current:('T -> 'U) -> seq<'U> - - /// The F# compiler emits calls to this function to implement the use operator for F# sequence - /// expressions. - /// - /// The resource to be used and disposed. - /// The input sequence. - /// - /// The result sequence. - val EnumerateUsing : resource:'T -> source:('T -> 'Collection) -> seq<'U> when 'T :> IDisposable and 'Collection :> seq<'U> - - /// Creates an anonymous event with the given handlers. - /// - /// A function to handle adding a delegate for the event to trigger. - /// A function to handle removing a delegate that the event triggers. - /// A function to produce the delegate type the event can trigger. - /// - /// The initialized event. - val CreateEvent : addHandler : ('Delegate -> unit) -> removeHandler : ('Delegate -> unit) -> createHandler : ((obj -> 'Args -> unit) -> 'Delegate) -> Microsoft.FSharp.Control.IEvent<'Delegate,'Args> - - [] - /// The F# compiler emits implementations of this type for compiled sequence expressions. - type GeneratedSequenceBase<'T> = - /// The F# compiler emits implementations of this type for compiled sequence expressions. - /// - /// A new sequence generator for the expression. - new : unit -> GeneratedSequenceBase<'T> - /// The F# compiler emits implementations of this type for compiled sequence expressions. - /// - /// A new enumerator for the sequence. - abstract GetFreshEnumerator : unit -> IEnumerator<'T> - /// The F# compiler emits implementations of this type for compiled sequence expressions. - /// - /// A reference to the sequence. - /// - /// A 0, 1, and 2 respectively indicate Stop, Yield, and Goto conditions for the sequence generator. - abstract GenerateNext : result:byref> -> int - /// The F# compiler emits implementations of this type for compiled sequence expressions. - abstract Close: unit -> unit - /// The F# compiler emits implementations of this type for compiled sequence expressions. - abstract CheckClose: bool - /// The F# compiler emits implementations of this type for compiled sequence expressions. - abstract LastGenerated : 'T - interface IEnumerable<'T> - interface IEnumerable - interface IEnumerator<'T> - interface IEnumerator - + val zip3: source1:seq<'T1> -> source2:seq<'T2> -> source3:seq<'T3> -> seq<'T1 * 'T2 * 'T3> \ No newline at end of file diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs new file mode 100644 index 00000000000..3f36e2c1469 --- /dev/null +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -0,0 +1,1286 @@ +// 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 Composer = + open IEnumerator + + module Core = + type PipeIdx = int + type ``PipeIdx?`` = Nullable + let emptyPipeIdx = Nullable () + let inline getPipeIdx (maybePipeIdx:``PipeIdx?``) = if maybePipeIdx.HasValue then maybePipeIdx.Value else 1 + let inline makePipeIdx (pipeIdx:PipeIdx) = Nullable pipeIdx + + type ICompletionChaining = + abstract OnComplete : PipeIdx -> unit + abstract OnDispose : unit -> unit + + type IOutOfBand = + abstract StopFurtherProcessing : PipeIdx -> unit + + [] + type Consumer<'T,'U> () = + abstract ProcessNext : input:'T -> bool + + abstract OnComplete : PipeIdx -> unit + abstract OnDispose : unit -> unit + + default __.OnComplete _ = () + default __.OnDispose () = () + + interface ICompletionChaining with + member this.OnComplete terminatingIdx = + this.OnComplete terminatingIdx + + member this.OnDispose () = + try this.OnDispose () + finally () + + [] + 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 Folder<'T, 'U> = + inherit Consumer<'T,'T> + + val mutable Value : 'U + + new (init) = { + inherit Consumer<'T,'T>() + Value = init + } + + type ISeqFactory<'T,'U> = + abstract PipeIdx : PipeIdx + abstract Create<'V> : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> + + type ISeq<'T> = + inherit IEnumerable<'T> + abstract member Compose<'U> : (ISeqFactory<'T,'U>) -> ISeq<'U> + abstract member ForEach<'consumer when 'consumer :> Consumer<'T,'T>> : f:((unit->unit)->'consumer) -> 'consumer + + open Core + + module internal Helpers = + // 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 avoidTailCall boolean = match boolean with true -> true | false -> false + + // 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 upcastSeq (t:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) + let inline upcastFactory (t:#ISeqFactory<'T,'U>) : ISeqFactory<'T,'U> = (# "" t : ISeqFactory<'T,'U> #) + let inline upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) + let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) + let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) + let inline upcastICompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) + + open Helpers + + module internal Seq = + type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = + new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) + + interface ISeqFactory<'T,'U> with + member __.PipeIdx = getPipeIdx pipeIdx + member __.Create<'V> (_:IOutOfBand) (_:``PipeIdx?``) (_:Consumer<'U,'V>) : Consumer<'T,'V> = failwith "library implementation error: Create on base factory should not be called" + + and ComposedFactory<'T,'U,'V> private (first:ISeqFactory<'T,'U>, second:ISeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = + inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) + + interface ISeqFactory<'T,'V> with + member this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = + first.Create outOfBand pipeIdx (second.Create outOfBand (makePipeIdx secondPipeIdx) next) + + static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = + ComposedFactory(first, second, first.PipeIdx+1) |> upcastFactory + + and ChooseFactory<'T,'U> (filter:'T->option<'U>) = + inherit SeqComponentFactory<'T,'U> () + interface ISeqFactory<'T,'U> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) + + and DistinctFactory<'T when 'T: equality> () = + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) + + and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) + + and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) + + and FilterFactory<'T> (filter:'T->bool) = + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = + match next with + | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter + | _ -> upcast Filter (filter, next) + + and IdentityFactory<'T> () = + inherit SeqComponentFactory<'T,'T> () + static let singleton = IdentityFactory<'T>() + interface ISeqFactory<'T,'T> with + member __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next + static member Instance = singleton + + and MapFactory<'T,'U> (map:'T->'U) = + inherit SeqComponentFactory<'T,'U> () + interface ISeqFactory<'T,'U> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = + match next with + | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map + | _ -> upcast Map<_,_,_> (map, next) + + and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = + inherit SeqComponentFactory<'First,'U> () + interface ISeqFactory<'First,'U> with + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, outOfBand, next, getPipeIdx pipeIdx) + + and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = + inherit SeqComponentFactory<'Second,'U> () + interface ISeqFactory<'Second,'U> with + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, outOfBand, next, getPipeIdx pipeIdx) + + and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = + inherit SeqComponentFactory<'First,'U> () + interface ISeqFactory<'First,'U> with + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, outOfBand, next, getPipeIdx pipeIdx) + + and MapiFactory<'T,'U> (mapi:int->'T->'U) = + inherit SeqComponentFactory<'T,'U> () + interface ISeqFactory<'T,'U> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) + + and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = + inherit SeqComponentFactory<'First,'U> () + interface ISeqFactory<'First,'U> with + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, outOfBand, next, getPipeIdx pipeIdx) + + and PairwiseFactory<'T> () = + inherit SeqComponentFactory<'T,'T*'T> () + interface ISeqFactory<'T,'T*'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) + + and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = + inherit SeqComponentFactory<'T,'State> () + interface ISeqFactory<'T,'State> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) + + and SkipFactory<'T> (count:int) = + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) + + and SkipWhileFactory<'T> (predicate:'T->bool) = + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) + + and TakeWhileFactory<'T> (predicate:'T->bool) = + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, outOfBand, next, getPipeIdx pipeIdx) + + and TakeFactory<'T> (count:int) = + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, getPipeIdx pipeIdx) + + and TailFactory<'T> () = + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) + + and TruncateFactory<'T> (count:int) = + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, getPipeIdx pipeIdx) + + and WindowedFactory<'T> (windowSize:int) = + inherit SeqComponentFactory<'T, 'T[]> () + interface ISeqFactory<'T, 'T[]> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T[],'V>) : Consumer<'T,'V> = upcast Windowed (windowSize, next) + + and [] SeqComponent<'T,'U> (next:ICompletionChaining) = + inherit Consumer<'T,'U>() + + // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip + // and it can only do it at the start of a sequence + abstract Skipping : unit -> bool + + abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> + abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> + + interface ICompletionChaining with + member this.OnComplete terminatingIdx = + this.OnComplete terminatingIdx + next.OnComplete terminatingIdx + member this.OnDispose () = + try this.OnDispose () + finally next.OnDispose () + + default __.Skipping () = false + + default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) + default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) + + and Choose<'T,'U,'V> (choose:'T->option<'U>, next:Consumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) + + override __.ProcessNext (input:'T) : bool = + match choose input with + | Some value -> avoidTailCall (next.ProcessNext value) + | None -> false + + and Distinct<'T,'V when 'T: equality> (next:Consumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) + + override __.ProcessNext (input:'T) : bool = + if hashSet.Add input then + avoidTailCall (next.ProcessNext input) + else + false + + and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:Consumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) + + override __.ProcessNext (input:'T) : bool = + if hashSet.Add(keyFunction input) then + avoidTailCall (next.ProcessNext input) + else + false + + and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:Consumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) + + override __.ProcessNext (input:'T) : bool = + if cached.Value.Add input then + avoidTailCall (next.ProcessNext input) + else + false + + and Filter<'T,'V> (filter:'T->bool, next:Consumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) + + override __.ProcessNext (input:'T) : bool = + if filter input then + avoidTailCall (next.ProcessNext input) + else + false + + and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:Consumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) + + override __.ProcessNext (input:'T) : bool = + if filter input then + avoidTailCall (next.ProcessNext (map input)) + else + false + + and Map<'T,'U,'V> (map:'T->'U, next:Consumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) + + override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) + + override __.ProcessNext (input:'T) : bool = + avoidTailCall (next.ProcessNext (map input)) + + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = + inherit SeqComponent<'First,'V>(next) + + let input2 = enumerable2.GetEnumerator () + let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map + + override __.ProcessNext (input:'First) : bool = + if input2.MoveNext () then + avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) + else + outOfBand.StopFurtherProcessing pipeIdx + false + + override __.OnDispose () = + input2.Dispose () + + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = + inherit SeqComponent<'Second,'V>(next) + + let input1 = enumerable1.GetEnumerator () + let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map + + override __.ProcessNext (input:'Second) : bool = + if input1.MoveNext () then + avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) + else + outOfBand.StopFurtherProcessing pipeIdx + false + + override __.OnDispose () = + input1.Dispose () + + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = + inherit SeqComponent<'First,'V>(next) + + let input2 = enumerable2.GetEnumerator () + let input3 = enumerable3.GetEnumerator () + let map' = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt map + + override __.ProcessNext (input:'First) : bool = + if input2.MoveNext () && input3.MoveNext () then + avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) + else + outOfBand.StopFurtherProcessing pipeIdx + false + + override __.OnDispose () = + try input2.Dispose () + finally input3.Dispose () + + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:Consumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) + + override __.ProcessNext (input:'T) : bool = + let u = map input + if filter u then + avoidTailCall (next.ProcessNext u) + else + false + + and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:Consumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) + + let mutable idx = 0 + let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi + + override __.ProcessNext (input:'T) : bool = + idx <- idx + 1 + avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) + + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = + inherit SeqComponent<'First,'V>(next) + + let mutable idx = 0 + let input2 = enumerable2.GetEnumerator () + let mapi2' = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt map + + override __.ProcessNext (input:'First) : bool = + if input2.MoveNext () then + idx <- idx + 1 + avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) + else + outOfBand.StopFurtherProcessing pipeIdx + false + + override __.OnDispose () = + input2.Dispose () + + and Pairwise<'T,'V> (next:Consumer<'T*'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let mutable isFirst = true + let mutable lastValue = Unchecked.defaultof<'T> + + override __.ProcessNext (input:'T) : bool = + if isFirst then + lastValue <- input + isFirst <- false + false + else + let currentPair = lastValue, input + lastValue <- input + avoidTailCall (next.ProcessNext currentPair) + + and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:Consumer<'State,'V>) = + inherit SeqComponent<'T,'V>(next) + + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + let mutable foldResult = initialState + + override __.ProcessNext (input:'T) : bool = + foldResult <- f.Invoke(foldResult, input) + avoidTailCall (next.ProcessNext foldResult) + + and Skip<'T,'V> (skipCount:int, next:Consumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let mutable count = 0 + + override __.Skipping () = + if count < skipCount then + count <- count + 1 + true + else + false + + override __.ProcessNext (input:'T) : bool = + if count < skipCount then + count <- count + 1 + false + else + avoidTailCall (next.ProcessNext input) + + override __.OnComplete _ = + if count < skipCount then + let x = skipCount - count + invalidOpFmt "tried to skip {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + + and SkipWhile<'T,'V> (predicate:'T->bool, next:Consumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let mutable skip = true + + override __.ProcessNext (input:'T) : bool = + if skip then + skip <- predicate input + if skip then + false + else + avoidTailCall (next.ProcessNext input) + else + avoidTailCall (next.ProcessNext input) + + and Take<'T,'V> (takeCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipelineIdx:int) = + inherit Truncate<'T, 'V>(takeCount, outOfBand, next, pipelineIdx) + + override this.OnComplete terminatingIdx = + if terminatingIdx < pipelineIdx && this.Count < takeCount then + let x = takeCount - this.Count + invalidOpFmt "tried to take {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + + and TakeWhile<'T,'V> (predicate:'T->bool, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = + inherit SeqComponent<'T,'V>(next) + + override __.ProcessNext (input:'T) : bool = + if predicate input then + avoidTailCall (next.ProcessNext input) + else + outOfBand.StopFurtherProcessing pipeIdx + false + + and Tail<'T, 'V> (next:Consumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let mutable first = true + + override __.ProcessNext (input:'T) : bool = + if first then + first <- false + false + else + avoidTailCall (next.ProcessNext input) + + override this.OnComplete _ = + if first then + invalidArg "source" (SR.GetString(SR.notEnoughElements)) + + and Truncate<'T,'V> (truncateCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = + inherit SeqComponent<'T,'V>(next) + + let mutable count = 0 + + member __.Count = count + + override __.ProcessNext (input:'T) : bool = + if count < truncateCount then + count <- count + 1 + if count = truncateCount then + outOfBand.StopFurtherProcessing pipeIdx + avoidTailCall (next.ProcessNext input) + else + outOfBand.StopFurtherProcessing pipeIdx + false + + and Windowed<'T,'V> (windowSize: int, next:Consumer<'T[],'V>) = + inherit SeqComponent<'T,'V>(next) + + let circularBuffer = Array.zeroCreateUnchecked windowSize + let mutable idx = 0 + + let mutable priming = windowSize - 1 + + override __.ProcessNext (input:'T) : bool = + circularBuffer.[idx] <- input + + idx <- idx + 1 + if idx = windowSize then + idx <- 0 + + if priming > 0 then + priming <- priming - 1 + false + else + if windowSize < 32 then + let window = Array.init windowSize (fun i -> circularBuffer.[(idx+i) % windowSize]) + avoidTailCall (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) + avoidTailCall (next.ProcessNext window) + + type SeqProcessNextStates = + | InProcess = 0 + | NotStarted = 1 + | Finished = 2 + + type Result<'T>() = + let mutable haltedIdx = 0 + + member val Current = Unchecked.defaultof<'T> with get, set + member val SeqState = SeqProcessNextStates.NotStarted with get, set + member __.HaltedIdx = haltedIdx + + interface IOutOfBand with + member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx + + // SetResult<> is used at the end of the chain of SeqComponents to assign the final value + type SetResult<'T> (result:Result<'T>) = + inherit Consumer<'T,'T>() + + override __.ProcessNext (input:'T) : bool = + result.Current <- input + true + + type OutOfBand() = + let mutable haltedIdx = 0 + interface IOutOfBand with member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx + member __.HaltedIdx = haltedIdx + + module ForEach = + let enumerable (enumerable:IEnumerable<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + use enumerator = enumerable.GetEnumerator () + while (outOfBand.HaltedIdx = 0) && (enumerator.MoveNext ()) do + consumer.ProcessNext enumerator.Current |> ignore + + let array (array:array<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + let mutable idx = 0 + while (outOfBand.HaltedIdx = 0) && (idx < array.Length) do + consumer.ProcessNext array.[idx] |> ignore + idx <- idx + 1 + + let list (alist:list<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + let rec iterate lst = + match outOfBand.HaltedIdx, lst with + | 0, hd :: tl -> + consumer.ProcessNext hd |> ignore + iterate tl + | _ -> () + iterate alist + + let unfold (generator:'S->option<'T*'S>) state (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + let rec iterate current = + match outOfBand.HaltedIdx, generator current with + | 0, Some (item, next) -> + consumer.ProcessNext item |> ignore + iterate next + | _ -> () + + iterate state + + let makeIsSkipping (consumer:Consumer<'T,'U>) = + match consumer with + | :? SeqComponent<'T,'U> as c -> c.Skipping + | _ -> fun () -> false + + let init f (terminatingIdx:int) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + let mutable idx = -1 + let isSkipping = makeIsSkipping consumer + let mutable maybeSkipping = true + while (outOfBand.HaltedIdx = 0) && (idx < terminatingIdx) do + if maybeSkipping then + maybeSkipping <- isSkipping () + + if (not maybeSkipping) then + consumer.ProcessNext (f (idx+1)) |> ignore + + idx <- idx + 1 + + let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:ISeqFactory<'T,'U>) executeOn = + let pipeline = OutOfBand() + let result = f (fun () -> (pipeline:>IOutOfBand).StopFurtherProcessing (current.PipeIdx+1)) + let consumer = current.Create pipeline emptyPipeIdx result + try + executeOn pipeline consumer + (upcastICompletionChaining consumer).OnComplete pipeline.HaltedIdx + result + finally + (upcastICompletionChaining consumer).OnDispose () + + 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>, seqComponent:ICompletionChaining) = + interface IDisposable with + member __.Dispose() : unit = + seqComponent.OnDispose () + + interface IEnumerator with + member this.Current : obj = box ((upcastEnumerator 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.Current + 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 : (seq<'T>) -> IEnumerable<'T> + + default this.Append source = upcastEnumerable (AppendEnumerable [this; source]) + + interface IEnumerable with + member this.GetEnumerator () : IEnumerator = + let genericEnumerable = upcastEnumerable this + let genericEnumerator = genericEnumerable.GetEnumerator () + upcastEnumeratorNonGeneric genericEnumerator + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () + + interface ISeq<'T> with + member __.Compose _ = derivedClassShouldImplement () + member __.ForEach _ = derivedClassShouldImplement () + + and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, seqComponent) + + let rec moveNext () = + if (result.HaltedIdx = 0) && source.MoveNext () then + if seqComponent.ProcessNext source.Current then + true + else + moveNext () + else + result.SeqState <- SeqProcessNextStates.Finished + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + interface IDisposable with + member __.Dispose() = + try + source.Dispose () + finally + (upcastICompletionChaining seqComponent).OnDispose () + + and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:ISeqFactory<'T,'U>) = + inherit EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) + + interface ISeq<'U> with + member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + upcastSeq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) + + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.enumerable enumerable) + + 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 ((upcastEnumerator 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> = + upcastEnumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) + + override this.Append source = + upcastEnumerable (AppendEnumerable (source :: sources)) + + interface ISeq<'T> with + member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + upcastSeq (Enumerable<'T,'V>(this, next)) + + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.Instance (ForEach.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> = + upcastEnumerator (new ConcatEnumerator<_,_> (sources)) + + interface ISeq<'T> with + member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + upcastSeq (Enumerable<'T,'V>(this, next)) + + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) + + let create enumerable current = + upcastSeq (Enumerable(enumerable, current)) + + 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 = + upcastEnumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) + + interface ISeq<'T> with + member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + upcastSeq (Enumerable.Enumerable<'T,'V>(this, next)) + + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) + + + + module Array = + type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) + + let mutable idx = 0 + let mutable array = Unchecked.defaultof<_> + + let mutable initMoveNext = Unchecked.defaultof<_> + do + initMoveNext <- + fun () -> + result.SeqState <- SeqProcessNextStates.InProcess + array <- delayedArray () + initMoveNext <- ignore + + let rec moveNext () = + if (result.HaltedIdx = 0) && idx < array.Length then + idx <- idx+1 + if seqComponent.ProcessNext array.[idx-1] then + true + else + moveNext () + else + result.SeqState <- SeqProcessNextStates.Finished + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + false + + interface IEnumerator with + member __.MoveNext () = + initMoveNext () + moveNext () + + type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:ISeqFactory<'T,'U>) = + inherit Enumerable.EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + + interface ISeq<'U> with + member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + upcastSeq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) + + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.array (delayedArray ())) + + let createDelayed (delayedArray:unit->array<'T>) (current:ISeqFactory<'T,'U>) = + upcastSeq (Enumerable(delayedArray, current)) + + let create (array:array<'T>) (current:ISeqFactory<'T,'U>) = + createDelayed (fun () -> array) current + + let createDelayedId (delayedArray:unit -> array<'T>) = + createDelayed delayedArray IdentityFactory.Instance + + let createId (array:array<'T>) = + create array IdentityFactory.Instance + + module List = + type Enumerator<'T,'U>(alist:list<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) + + let mutable list = alist + + let rec moveNext current = + match result.HaltedIdx, current with + | 0, head::tail -> + if seqComponent.ProcessNext head then + list <- tail + true + else + moveNext tail + | _ -> + result.SeqState <- SeqProcessNextStates.Finished + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext list + + type Enumerable<'T,'U>(alist:list<'T>, current:ISeqFactory<'T,'U>) = + inherit Enumerable.EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + + interface ISeq<'U> with + member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + upcastSeq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) + + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.list alist) + + let create alist current = + upcastSeq (Enumerable(alist, current)) + + module Unfold = + type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) + + let mutable current = state + + let rec moveNext () = + match result.HaltedIdx, generator current with + | 0, Some (item, nextState) -> + current <- nextState + if seqComponent.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, current:ISeqFactory<'T,'U>) = + inherit Enumerable.EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + + interface ISeq<'U> with + member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + upcastSeq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) + + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.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, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) + + let isSkipping = + ForEach.makeIsSkipping seqComponent + + 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 seqComponent.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 + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:ISeqFactory<'T,'U>) = + inherit Enumerable.EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + + interface ISeq<'U> with + member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + upcastSeq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) + + member this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = + let terminatingIdx = getTerminatingIdx count + ForEach.execute createResult current (ForEach.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 self.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = () } + + type EnumerableDecider<'T>(count:Nullable, f:int->'T) = + 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.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + upcastSeq (Enumerable<'T,'V>(count, f, next)) + + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (upcastEnumerable this)) + + [] + let toComposer (source:seq<'T>) : ISeq<'T> = + checkNonNull "source" source + match source with + | :? ISeq<'T> as s -> s + | :? array<'T> as a -> upcastSeq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) + | :? list<'T> as a -> upcastSeq (List.Enumerable(a, IdentityFactory.Instance)) + | _ -> upcastSeq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) + + let inline foreach f (source:ISeq<_>) = + source.ForEach f + + let inline compose factory (source:ISeq<'T>) = + source.Compose factory + + [] + let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance + + [] + let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = + upcastSeq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) + + [] + let initInfinite<'T> (f:int->'T) : ISeq<'T> = + upcastSeq (new Init.EnumerableDecider<'T>(Nullable (), f)) + + [] + let init<'T> (count:int) (f:int->'T) : ISeq<'T> = + if count < 0 then invalidArgInputMustBeNonNegative "count" count + elif count = 0 then empty else + upcastSeq (new Init.EnumerableDecider<'T>(Nullable count, f)) + + [] + let iter f (source:ISeq<'T>) = + source + |> foreach (fun _ -> + { new Consumer<'T,'T> () with + override this.ProcessNext value = + f value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> ignore + + [] + let tryItem i (source:ISeq<'T>) = + if i < 0 then None else + source + |> foreach (fun halt -> + { new Folder<'T, Values>> (Values<_,_> (0, None)) with + override this.ProcessNext value = + if this.Value._1 = i then + this.Value._2 <- Some value + halt () + else + this.Value._1 <- this.Value._1 + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun item -> item.Value._2 + + [] + let iteri f (source:ISeq<'T>) = + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f + + source + |> foreach (fun _ -> + { new Folder<'T, int> (0) with + override this.ProcessNext value = + f.Invoke(this.Value, value) + this.Value <- this.Value + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> ignore + + [] + let exists f (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, bool> (false) with + override this.ProcessNext value = + if f value then + this.Value <- true + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun exists -> exists.Value + + [] + let inline contains element (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, bool> (false) with + override this.ProcessNext value = + if element = value then + this.Value <- true + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun contains -> contains.Value + + [] + let forall f (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, bool> (true) with + override this.ProcessNext value = + if not (f value) then + this.Value <- false + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun forall -> forall.Value + + [] + let filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = + source + |> compose (FilterFactory f) + + [] + let map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = + source + |> compose (MapFactory f) + + [] + let mapi f source = + source + |> compose (MapiFactory f) + + [] + let choose f source = + source + |> compose (ChooseFactory f) + + [] + let indexed source = + source + |> compose (MapiFactory (fun i x -> i,x)) + + [] + let tryPick f (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, Option<'U>> (None) with + override this.ProcessNext value = + match f value with + | (Some _) as some -> + this.Value <- some + halt () + | None -> () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun pick -> pick.Value + + [] + let tryFind f (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, Option<'T>> (None) with + override this.ProcessNext value = + if f value then + this.Value <- Some value + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun find -> find.Value \ No newline at end of file diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi new file mode 100644 index 00000000000..838cee6da37 --- /dev/null +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -0,0 +1,757 @@ +// 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 Composer = + module Core = + /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the + /// source of the chain. + type PipeIdx = int + type ``PipeIdx?`` = Nullable + + /// ICompletionChaining is used to correctly handle cleaning up of the pipeline. A + /// base implementation is provided in Consumer, and should not be overwritten. Consumer + /// provides it's own OnComplete and OnDispose function which should be used to handle + /// a particular consumers cleanup. + type ICompletionChaining = + /// OnComplete is used to determine if the object has been processed correctly, + /// and possibly throw exceptions to denote incorrect application (i.e. such as a Take + /// operation which didn't have a source at least as large as was required). It is + /// not called in the case of an exception being thrown whilst the stream is still + /// being processed. + abstract OnComplete : PipeIdx -> unit + /// OnDispose is used to cleanup the stream. It is always called at the last operation + /// after the enumeration has completed. + abstract OnDispose : unit -> unit + + type IOutOfBand = + abstract StopFurtherProcessing : PipeIdx -> unit + + /// Consumer is the base class of all elements within the pipeline + [] + type Consumer<'T,'U> = + interface ICompletionChaining + new : unit -> Consumer<'T,'U> + abstract member ProcessNext : input:'T -> bool + abstract member OnComplete : PipeIdx -> unit + abstract member OnDispose : unit -> unit + override OnComplete : PipeIdx -> unit + override OnDispose : unit -> unit + + /// 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 + + /// 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 ForEach function. + [] + type Folder<'T,'U> = + inherit Consumer<'T,'T> + new : init:'U -> Folder<'T,'U> + val mutable Value: 'U + + type ISeqFactory<'T,'U> = + abstract member Create : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> + abstract member PipeIdx : PipeIdx + + type ISeq<'T> = + inherit System.Collections.Generic.IEnumerable<'T> + abstract member Compose : ISeqFactory<'T,'U> -> ISeq<'U> + abstract member ForEach : f:((unit -> unit) -> 'a) -> 'a when 'a :> Consumer<'T,'T> + + open Core + + module internal Helpers = + val inline avoidTailCall : boolean:bool -> bool + val inline upcastSeq : t: #ISeq<'T> -> ISeq<'T> + val inline upcastFactory : + t: #ISeqFactory<'T,'U> -> ISeqFactory<'T,'U> + val inline upcastEnumerable : t:#IEnumerable<'T> -> IEnumerable<'T> + val inline upcastEnumerator : t:#IEnumerator<'T> ->IEnumerator<'T> + val inline upcastEnumeratorNonGeneric : + t:#IEnumerator -> IEnumerator + val inline upcastICompletionChaining : + t: #ICompletionChaining -> ICompletionChaining + + module internal Seq = + [] + type SeqComponentFactory<'T,'U> = + class + interface ISeqFactory<'T,'U> + new : unit -> SeqComponentFactory<'T,'U> + new : pipeIdx: ``PipeIdx?`` -> + SeqComponentFactory<'T,'U> + end + and ComposedFactory<'T,'U,'V> = + class + inherit SeqComponentFactory<'T,'V> + interface ISeqFactory<'T,'V> + private new : first: ISeqFactory<'T,'U> * + second: ISeqFactory<'U,'V> * + secondPipeIdx: PipeIdx -> + ComposedFactory<'T,'U,'V> + static member + Combine : first: ISeqFactory<'T,'U> -> + second: ISeqFactory<'U,'V> -> + ISeqFactory<'T,'V> + end + and ChooseFactory<'T,'U> = + class + inherit SeqComponentFactory<'T,'U> + interface ISeqFactory<'T,'U> + new : filter:('T -> 'U option) -> ChooseFactory<'T,'U> + end + and DistinctFactory<'T when 'T : equality> = + class + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> + new : unit -> DistinctFactory<'T> + end + and DistinctByFactory<'T,'Key when 'Key : equality> = + class + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> + new : keyFunction:('T -> 'Key) -> DistinctByFactory<'T,'Key> + end + and ExceptFactory<'T when 'T : equality> = + class + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> + new : itemsToExclude:seq<'T> -> ExceptFactory<'T> + end + and FilterFactory<'T> = + class + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> + new : filter:('T -> bool) -> FilterFactory<'T> + end + and IdentityFactory<'T> = + class + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> + new : unit -> IdentityFactory<'T> + static member Instance : IdentityFactory<'T> + end + and MapFactory<'T,'U> = + class + inherit SeqComponentFactory<'T,'U> + interface ISeqFactory<'T,'U> + new : map:('T -> 'U) -> MapFactory<'T,'U> + end + and Map2FirstFactory<'First,'Second,'U> = + class + inherit SeqComponentFactory<'First,'U> + interface ISeqFactory<'First,'U> + new : map:('First -> 'Second -> 'U) * + input2:IEnumerable<'Second> -> + Map2FirstFactory<'First,'Second,'U> + end + and Map2SecondFactory<'First,'Second,'U> = + class + inherit SeqComponentFactory<'Second,'U> + interface ISeqFactory<'Second,'U> + new : map:('First -> 'Second -> 'U) * + input1:IEnumerable<'First> -> + Map2SecondFactory<'First,'Second,'U> + end + and Map3Factory<'First,'Second,'Third,'U> = + class + inherit SeqComponentFactory<'First,'U> + interface ISeqFactory<'First,'U> + new : map:('First -> 'Second -> 'Third -> 'U) * + input2:IEnumerable<'Second> * + input3:IEnumerable<'Third> -> + Map3Factory<'First,'Second,'Third,'U> + end + and MapiFactory<'T,'U> = + class + inherit SeqComponentFactory<'T,'U> + interface ISeqFactory<'T,'U> + new : mapi:(int -> 'T -> 'U) -> MapiFactory<'T,'U> + end + and Mapi2Factory<'First,'Second,'U> = + class + inherit SeqComponentFactory<'First,'U> + interface ISeqFactory<'First,'U> + new : map:(int -> 'First -> 'Second -> 'U) * + input2:IEnumerable<'Second> -> + Mapi2Factory<'First,'Second,'U> + end + and PairwiseFactory<'T> = + class + inherit SeqComponentFactory<'T,('T * 'T)> + interface ISeqFactory<'T,('T * 'T)> + new : unit -> PairwiseFactory<'T> + end + and ScanFactory<'T,'State> = + class + inherit SeqComponentFactory<'T,'State> + interface ISeqFactory<'T,'State> + new : folder:('State -> 'T -> 'State) * initialState:'State -> + ScanFactory<'T,'State> + end + and SkipFactory<'T> = + class + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> + new : count:int -> SkipFactory<'T> + end + and SkipWhileFactory<'T> = + class + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> + new : predicate:('T -> bool) -> SkipWhileFactory<'T> + end + and TakeWhileFactory<'T> = + class + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> + new : predicate:('T -> bool) -> TakeWhileFactory<'T> + end + and TakeFactory<'T> = + class + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> + new : count:int -> TakeFactory<'T> + end + and TailFactory<'T> = + class + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> + new : unit -> TailFactory<'T> + end + and TruncateFactory<'T> = + class + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> + new : count:int -> TruncateFactory<'T> + end + and WindowedFactory<'T> = + class + inherit SeqComponentFactory<'T,'T []> + interface ISeqFactory<'T,'T []> + new : windowSize:int -> WindowedFactory<'T> + end + and [] SeqComponent<'T,'U> = + class + inherit Consumer<'T,'U> + interface ICompletionChaining + new : next: ICompletionChaining -> + SeqComponent<'T,'U> + abstract member + CreateFilter : filter:('T -> bool) -> SeqComponent<'T,'U> + abstract member + CreateMap : map:('S -> 'T) -> SeqComponent<'S,'U> + abstract member Skipping : unit -> bool + override + CreateFilter : filter:('T -> bool) -> SeqComponent<'T,'U> + override CreateMap : map:('S -> 'T) -> SeqComponent<'S,'U> + override Skipping : unit -> bool + end + and Choose<'T,'U,'V> = + class + inherit SeqComponent<'T,'V> + new : choose:('T -> 'U option) * next: Consumer<'U,'V> -> + Choose<'T,'U,'V> + override ProcessNext : input:'T -> bool + end + and Distinct<'T,'V when 'T : equality> = + class + inherit SeqComponent<'T,'V> + new : next: Consumer<'T,'V> -> Distinct<'T,'V> + override ProcessNext : input:'T -> bool + end + and DistinctBy<'T,'Key,'V when 'Key : equality> = + class + inherit SeqComponent<'T,'V> + new : keyFunction:('T -> 'Key) * next: Consumer<'T,'V> -> + DistinctBy<'T,'Key,'V> + override ProcessNext : input:'T -> bool + end + and Except<'T,'V when 'T : equality> = + class + inherit SeqComponent<'T,'V> + new : itemsToExclude:seq<'T> * next: Consumer<'T,'V> -> + Except<'T,'V> + override ProcessNext : input:'T -> bool + end + and Filter<'T,'V> = + class + inherit SeqComponent<'T,'V> + new : filter:('T -> bool) * next: Consumer<'T,'V> -> + Filter<'T,'V> + override CreateMap : map:('S -> 'T) -> SeqComponent<'S,'V> + override ProcessNext : input:'T -> bool + end + and FilterThenMap<'T,'U,'V> = + class + inherit SeqComponent<'T,'V> + new : filter:('T -> bool) * map:('T -> 'U) * + next: Consumer<'U,'V> -> + FilterThenMap<'T,'U,'V> + override ProcessNext : input:'T -> bool + end + and Map<'T,'U,'V> = + class + inherit SeqComponent<'T,'V> + new : map:('T -> 'U) * next: Consumer<'U,'V> -> + Map<'T,'U,'V> + override + CreateFilter : filter:('T -> bool) -> SeqComponent<'T,'V> + override ProcessNext : input:'T -> bool + end + and Map2First<'First,'Second,'U,'V> = + class + inherit SeqComponent<'First,'V> + new : map:('First -> 'Second -> 'U) * + enumerable2:IEnumerable<'Second> * + outOfBand: IOutOfBand * + next: Consumer<'U,'V> * pipeIdx:int -> + Map2First<'First,'Second,'U,'V> + override OnDispose : unit -> unit + override ProcessNext : input:'First -> bool + end + and Map2Second<'First,'Second,'U,'V> = + class + inherit SeqComponent<'Second,'V> + new : map:('First -> 'Second -> 'U) * + enumerable1:IEnumerable<'First> * + outOfBand: IOutOfBand * + next: Consumer<'U,'V> * pipeIdx:int -> + Map2Second<'First,'Second,'U,'V> + override OnDispose : unit -> unit + override ProcessNext : input:'Second -> bool + end + and Map3<'First,'Second,'Third,'U,'V> = + class + inherit SeqComponent<'First,'V> + new : map:('First -> 'Second -> 'Third -> 'U) * + enumerable2:IEnumerable<'Second> * + enumerable3:IEnumerable<'Third> * + outOfBand: IOutOfBand * + next: Consumer<'U,'V> * pipeIdx:int -> + Map3<'First,'Second,'Third,'U,'V> + override OnDispose : unit -> unit + override ProcessNext : input:'First -> bool + end + and MapThenFilter<'T,'U,'V> = + class + inherit SeqComponent<'T,'V> + new : map:('T -> 'U) * filter:('U -> bool) * + next: Consumer<'U,'V> -> + MapThenFilter<'T,'U,'V> + override ProcessNext : input:'T -> bool + end + and Mapi<'T,'U,'V> = + class + inherit SeqComponent<'T,'V> + new : mapi:(int -> 'T -> 'U) * next: Consumer<'U,'V> -> + Mapi<'T,'U,'V> + override ProcessNext : input:'T -> bool + end + and Mapi2<'First,'Second,'U,'V> = + class + inherit SeqComponent<'First,'V> + new : map:(int -> 'First -> 'Second -> 'U) * + enumerable2:IEnumerable<'Second> * + outOfBand: IOutOfBand * + next: Consumer<'U,'V> * pipeIdx:int -> + Mapi2<'First,'Second,'U,'V> + override OnDispose : unit -> unit + override ProcessNext : input:'First -> bool + end + and Pairwise<'T,'V> = + class + inherit SeqComponent<'T,'V> + new : next: Consumer<('T * 'T),'V> -> + Pairwise<'T,'V> + override ProcessNext : input:'T -> bool + end + and Scan<'T,'State,'V> = + class + inherit SeqComponent<'T,'V> + new : folder:('State -> 'T -> 'State) * initialState:'State * + next: Consumer<'State,'V> -> + Scan<'T,'State,'V> + override ProcessNext : input:'T -> bool + end + and Skip<'T,'V> = + class + inherit SeqComponent<'T,'V> + new : skipCount:int * next: Consumer<'T,'V> -> + Skip<'T,'V> + override OnComplete : PipeIdx -> unit + override ProcessNext : input:'T -> bool + override Skipping : unit -> bool + end + and SkipWhile<'T,'V> = + class + inherit SeqComponent<'T,'V> + new : predicate:('T -> bool) * next: Consumer<'T,'V> -> + SkipWhile<'T,'V> + override ProcessNext : input:'T -> bool + end + and Take<'T,'V> = + class + inherit Truncate<'T,'V> + new : takeCount:int * outOfBand: IOutOfBand * + next: Consumer<'T,'V> * pipelineIdx:int -> + Take<'T,'V> + override OnComplete : terminatingIdx: PipeIdx -> unit + end + and TakeWhile<'T,'V> = + class + inherit SeqComponent<'T,'V> + new : predicate:('T -> bool) * outOfBand: IOutOfBand * + next: Consumer<'T,'V> * pipeIdx:int -> + TakeWhile<'T,'V> + override ProcessNext : input:'T -> bool + end + and Tail<'T,'V> = + class + inherit SeqComponent<'T,'V> + new : next: Consumer<'T,'V> -> Tail<'T,'V> + override OnComplete : PipeIdx -> unit + override ProcessNext : input:'T -> bool + end + and Truncate<'T,'V> = + class + inherit SeqComponent<'T,'V> + new : truncateCount:int * outOfBand: IOutOfBand * + next: Consumer<'T,'V> * pipeIdx:int -> + Truncate<'T,'V> + override ProcessNext : input:'T -> bool + member Count : int + end + and Windowed<'T,'V> = + class + inherit SeqComponent<'T,'V> + new : windowSize:int * next: Consumer<'T [],'V> -> + Windowed<'T,'V> + override ProcessNext : input:'T -> bool + end + type SeqProcessNextStates = + | InProcess = 0 + | NotStarted = 1 + | Finished = 2 + type Result<'T> = + class + interface IOutOfBand + new : unit -> Result<'T> + member Current : 'T + member HaltedIdx : int + member SeqState : SeqProcessNextStates + member Current : 'T with set + member SeqState : SeqProcessNextStates with set + end + type SetResult<'T> = + class + inherit Consumer<'T,'T> + new : result: Result<'T> -> SetResult<'T> + override ProcessNext : input:'T -> bool + end + type OutOfBand = + class + interface IOutOfBand + new : unit -> OutOfBand + member HaltedIdx : int + end + module ForEach = begin + val enumerable : + enumerable:IEnumerable<'T> -> + outOfBand: OutOfBand -> + consumer: Consumer<'T,'U> -> unit + val array : + array:'T array -> + outOfBand: OutOfBand -> + consumer: Consumer<'T,'U> -> unit + val list : + alist:'T list -> + outOfBand: OutOfBand -> + consumer: Consumer<'T,'U> -> unit + val unfold : + generator:('S -> ('T * 'S) option) -> + state:'S -> + outOfBand: OutOfBand -> + consumer: Consumer<'T,'U> -> unit + val makeIsSkipping : + consumer: Consumer<'T,'U> -> (unit -> bool) + val init : + f:(int -> 'T) -> + terminatingIdx:int -> + outOfBand: OutOfBand -> + consumer: Consumer<'T,'U> -> unit + val execute : + f:((unit -> unit) -> 'a) -> + current: ISeqFactory<'T,'U> -> + executeOn:( OutOfBand -> Consumer<'T,'U> -> + unit) -> 'a when 'a :> Consumer<'U,'U> + end + module Enumerable = begin + type Empty<'T> = + class + interface IDisposable + interface IEnumerator + interface IEnumerator<'T> + new : unit -> Empty<'T> + end + type EmptyEnumerators<'T> = + class + new : unit -> EmptyEnumerators<'T> + static member Element : IEnumerator<'T> + end + [] + type EnumeratorBase<'T> = + class + interface IEnumerator<'T> + interface IEnumerator + interface IDisposable + new : result: Result<'T> * + seqComponent: ICompletionChaining -> + EnumeratorBase<'T> + end + and [] EnumerableBase<'T> = + class + interface ISeq<'T> + interface IEnumerable<'T> + interface IEnumerable + new : unit -> EnumerableBase<'T> + abstract member + Append : seq<'T> -> IEnumerable<'T> + override + Append : source:seq<'T> -> IEnumerable<'T> + end + and Enumerator<'T,'U> = + class + inherit EnumeratorBase<'U> + interface IDisposable + interface IEnumerator + new : source:IEnumerator<'T> * + seqComponent: Consumer<'T,'U> * + result: Result<'U> -> + Enumerator<'T,'U> + end + and Enumerable<'T,'U> = + class + inherit EnumerableBase<'U> + interface ISeq<'U> + interface IEnumerable<'U> + new : enumerable:IEnumerable<'T> * + current: ISeqFactory<'T,'U> -> + Enumerable<'T,'U> + end + and ConcatEnumerator<'T,'Collection when 'Collection :> seq<'T>> = + class + interface IDisposable + interface IEnumerator + interface IEnumerator<'T> + new : sources:seq<'Collection> -> + ConcatEnumerator<'T,'Collection> + end + and AppendEnumerable<'T> = + class + inherit EnumerableBase<'T> + interface ISeq<'T> + interface IEnumerable<'T> + new : sources:seq<'T> list -> AppendEnumerable<'T> + override + Append : source:seq<'T> -> + IEnumerable<'T> + end + and ConcatEnumerable<'T,'Collection when 'Collection :> seq<'T>> = + class + inherit EnumerableBase<'T> + interface ISeq<'T> + interface IEnumerable<'T> + new : sources:seq<'Collection> -> + ConcatEnumerable<'T,'Collection> + end + val create : + enumerable:IEnumerable<'a> -> + current: ISeqFactory<'a,'b> -> ISeq<'b> + end + module EmptyEnumerable = begin + type Enumerable<'T> = + class + inherit Enumerable.EnumerableBase<'T> + interface ISeq<'T> + interface IEnumerable<'T> + new : unit -> Enumerable<'T> + override + Append : source:seq<'T> -> IEnumerable<'T> + static member Instance : ISeq<'T> + end + end + module Array = begin + type Enumerator<'T,'U> = + class + inherit Enumerable.EnumeratorBase<'U> + interface IEnumerator + new : delayedArray:(unit -> 'T array) * + seqComponent: Consumer<'T,'U> * + result: Result<'U> -> Enumerator<'T,'U> + end + type Enumerable<'T,'U> = + class + inherit Enumerable.EnumerableBase<'U> + interface ISeq<'U> + interface IEnumerable<'U> + new : delayedArray:(unit -> 'T array) * + current: ISeqFactory<'T,'U> -> + Enumerable<'T,'U> + end + val createDelayed : + delayedArray:(unit -> 'T array) -> + current: ISeqFactory<'T,'U> -> ISeq<'U> + val create : + array:'T array -> + current: ISeqFactory<'T,'U> -> ISeq<'U> + val createDelayedId : + delayedArray:(unit -> 'T array) -> ISeq<'T> + val createId : array:'T array -> ISeq<'T> + end + module List = begin + type Enumerator<'T,'U> = + class + inherit Enumerable.EnumeratorBase<'U> + interface IEnumerator + new : alist:'T list * seqComponent: Consumer<'T,'U> * + result: Result<'U> -> Enumerator<'T,'U> + end + type Enumerable<'T,'U> = + class + inherit Enumerable.EnumerableBase<'U> + interface ISeq<'U> + interface IEnumerable<'U> + new : alist:'T list * current: ISeqFactory<'T,'U> -> + Enumerable<'T,'U> + end + val create : + alist:'a list -> + current: ISeqFactory<'a,'b> -> ISeq<'b> + end + module Unfold = begin + type Enumerator<'T,'U,'State> = + class + inherit Enumerable.EnumeratorBase<'U> + interface IEnumerator + new : generator:('State -> ('T * 'State) option) * state:'State * + seqComponent: Consumer<'T,'U> * + result: Result<'U> -> + Enumerator<'T,'U,'State> + end + type Enumerable<'T,'U,'GeneratorState> = + class + inherit Enumerable.EnumerableBase<'U> + interface ISeq<'U> + interface IEnumerable<'U> + new : generator:('GeneratorState -> ('T * 'GeneratorState) option) * + state:'GeneratorState * current: ISeqFactory<'T,'U> -> + Enumerable<'T,'U,'GeneratorState> + end + end + module Init = begin + val getTerminatingIdx : count:Nullable -> int + type Enumerator<'T,'U> = + class + inherit Enumerable.EnumeratorBase<'U> + interface IEnumerator + new : count:Nullable * f:(int -> 'T) * + seqComponent: Consumer<'T,'U> * + result: Result<'U> -> Enumerator<'T,'U> + end + type Enumerable<'T,'U> = + class + inherit Enumerable.EnumerableBase<'U> + interface ISeq<'U> + interface IEnumerable<'U> + new : count:Nullable * f:(int -> 'T) * + current: ISeqFactory<'T,'U> -> + Enumerable<'T,'U> + end + val upto : + lastOption:int option -> + f:(int -> 'U) -> IEnumerator<'U> + type EnumerableDecider<'T> = + class + inherit Enumerable.EnumerableBase<'T> + interface ISeq<'T> + interface IEnumerable<'T> + new : count:Nullable * f:(int -> 'T) -> + EnumerableDecider<'T> + end + end + [] + val toComposer : source:seq<'T> -> ISeq<'T> + val inline foreach : + f:((unit -> unit) -> 'a) -> source: ISeq<'b> -> 'a + when 'a :> Consumer<'b,'b> + val inline compose : + factory: ISeqFactory<'T,'a> -> + source: ISeq<'T> -> ISeq<'a> + [] + val empty<'T> : ISeq<'T> + [] + val unfold : + generator:('State -> ('T * 'State) option) -> + state:'State -> ISeq<'T> + [] + val initInfinite : f:(int -> 'T) -> ISeq<'T> + [] + val init : count:int -> f:(int -> 'T) -> ISeq<'T> + [] + val iter : f:('T -> unit) -> source: ISeq<'T> -> unit + [] + val tryItem : i:int -> source: ISeq<'T> -> 'T option + [] + val iteri : f:(int -> 'T -> unit) -> source: ISeq<'T> -> unit + [] + val exists : f:('T -> bool) -> source: ISeq<'T> -> bool + [] + val inline contains : + element:'T -> source: ISeq<'T> -> bool when 'T : equality + [] + val forall : f:('T -> bool) -> source: ISeq<'T> -> bool + [] + val filter : + f:('T -> bool) -> source: ISeq<'T> -> ISeq<'T> + [] + val map : + f:('T -> 'U) -> source: ISeq<'T> -> ISeq<'U> + [] + val mapi : + f:(int -> 'a -> 'b) -> + source: ISeq<'a> -> ISeq<'b> + [] + val choose : + f:('a -> 'b option) -> + source: ISeq<'a> -> ISeq<'b> + [] + val indexed : source: ISeq<'a> -> ISeq + [] + val tryPick : + f:('T -> 'U option) -> source: ISeq<'T> -> Option<'U> + [] + val tryFind : f:('T -> bool) -> source: ISeq<'T> -> Option<'T> + diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs new file mode 100644 index 00000000000..657c58d1681 --- /dev/null +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -0,0 +1,405 @@ +// 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 + #nowarn "52" // The value has been copied to ensure the original is not mutated by this operation + + open System + open System.Diagnostics + open System.Collections + open System.Collections.Generic + open Microsoft.FSharp.Core + open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators + open Microsoft.FSharp.Core.Operators + open Microsoft.FSharp.Control + open Microsoft.FSharp.Collections + + module internal IEnumerator = + + let noReset() = raise (new System.NotSupportedException(SR.GetString(SR.resetNotSupported))) + let notStarted() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationNotStarted))) + let alreadyFinished() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationAlreadyFinished))) + let check started = if not started then notStarted() + let dispose (r : System.IDisposable) = r.Dispose() + + let cast (e : IEnumerator) : IEnumerator<'T> = + { new IEnumerator<'T> with + member x.Current = unbox<'T> e.Current + interface IEnumerator with + member x.Current = unbox<'T> e.Current :> obj + member x.MoveNext() = e.MoveNext() + member x.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = + match e with + | :? System.IDisposable as e -> e.Dispose() + | _ -> () } + + /// A concrete implementation of an enumerator that returns no values + [] + type EmptyEnumerator<'T>() = + let mutable started = false + interface IEnumerator<'T> with + member x.Current = + check started + (alreadyFinished() : 'T) + + interface System.Collections.IEnumerator with + member x.Current = + check started + (alreadyFinished() : obj) + member x.MoveNext() = + if not started then started <- true + false + member x.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = () + + let Empty<'T> () = (new EmptyEnumerator<'T>() :> IEnumerator<'T>) + [] + type EmptyEnumerable<'T> = + | EmptyEnumerable + interface IEnumerable<'T> with + member x.GetEnumerator() = Empty<'T>() + interface IEnumerable with + member x.GetEnumerator() = (Empty<'T>() :> IEnumerator) + + let readAndClear r = + lock r (fun () -> match !r with None -> None | Some _ as res -> r := None; res) + + let generateWhileSome openf compute closef : IEnumerator<'U> = + let started = ref false + let curr = ref None + let state = ref (Some(openf())) + let getCurr() = + check !started + match !curr with None -> alreadyFinished() | Some x -> x + let start() = if not !started then (started := true) + + let dispose() = readAndClear state |> Option.iter closef + let finish() = (try dispose() finally curr := None) + { new IEnumerator<'U> with + member x.Current = getCurr() + interface IEnumerator with + member x.Current = box (getCurr()) + member x.MoveNext() = + start() + match !state with + | None -> false (* we started, then reached the end, then got another MoveNext *) + | Some s -> + match (try compute s with e -> finish(); reraise()) with + | None -> finish(); false + | Some _ as x -> curr := x; true + + member x.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = dispose() } + + [] + type Singleton<'T>(v:'T) = + let mutable started = false + interface IEnumerator<'T> with + member x.Current = v + interface IEnumerator with + member x.Current = box v + member x.MoveNext() = if started then false else (started <- true; true) + member x.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = () + + let Singleton x = (new Singleton<'T>(x) :> IEnumerator<'T>) + + let EnumerateThenFinally f (e : IEnumerator<'T>) = + { new IEnumerator<'T> with + member x.Current = e.Current + interface IEnumerator with + member x.Current = (e :> IEnumerator).Current + member x.MoveNext() = e.MoveNext() + member x.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = + try + e.Dispose() + finally + f() + } + + let inline checkNonNull argName arg = + match box arg with + | null -> nullArg argName + | _ -> () + + let mkSeq f = + { new IEnumerable<'U> with + member x.GetEnumerator() = f() + interface IEnumerable with + member x.GetEnumerator() = (f() :> IEnumerator) + } + +namespace Microsoft.FSharp.Core.CompilerServices + + open System + open System.Diagnostics + open Microsoft.FSharp.Core + open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators + open Microsoft.FSharp.Core.Operators + open Microsoft.FSharp.Control + open Microsoft.FSharp.Collections + open Microsoft.FSharp.Primitives.Basics + open System.Collections + open System.Collections.Generic + open Microsoft.FSharp.Collections.IEnumerator + + 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) + + let GenerateUsing (openf : unit -> ('U :> System.IDisposable)) compute = + Generate openf compute (fun (s:'U) -> s.Dispose()) + + let EnumerateFromFunctions opener moveNext current = + Generate + opener + (fun x -> if moveNext x then Some(current x) else None) + (fun x -> match box(x) with :? System.IDisposable as id -> id.Dispose() | _ -> ()) + + // A family of enumerators that can have additional 'finally' actions added to the enumerator through + // the use of mutation. This is used to 'push' the disposal action for a 'use' into the next enumerator. + // For example, + // seq { use x = ... + // while ... } + // results in the 'while' loop giving an adjustable enumerator. This is then adjusted by adding the disposal action + // from the 'use' into the enumerator. This means that we avoid constructing a two-deep enumerator chain in this + // common case. + type IFinallyEnumerator = + abstract AppendFinallyAction : (unit -> unit) -> unit + + /// A concrete implementation of IEnumerable that adds the given compensation to the "Dispose" chain of any + /// enumerators returned by the enumerable. + [] + type FinallyEnumerable<'T>(compensation: unit -> unit, restf: unit -> seq<'T>) = + interface IEnumerable<'T> with + member x.GetEnumerator() = + try + let ie = restf().GetEnumerator() + match ie with + | :? IFinallyEnumerator as a -> + a.AppendFinallyAction(compensation) + ie + | _ -> + IEnumerator.EnumerateThenFinally compensation ie + with e -> + compensation() + reraise() + interface IEnumerable with + member x.GetEnumerator() = ((x :> IEnumerable<'T>).GetEnumerator() :> IEnumerator) + + /// An optimized object for concatenating a sequence of enumerables + [] + type ConcatEnumerator<'T,'U when 'U :> seq<'T>>(sources: seq<'U>) = + let mutable outerEnum = sources.GetEnumerator() + let mutable currInnerEnum = IEnumerator.Empty() + + let mutable started = false + let mutable finished = false + let mutable compensations = [] + + [] // false = unchecked + val mutable private currElement : 'T + + member x.Finish() = + finished <- true + try + match currInnerEnum with + | null -> () + | _ -> + try + currInnerEnum.Dispose() + finally + currInnerEnum <- null + finally + try + match outerEnum with + | null -> () + | _ -> + try + outerEnum.Dispose() + finally + outerEnum <- null + finally + let rec iter comps = + match comps with + | [] -> () + | h::t -> + try h() finally iter t + try + compensations |> List.rev |> iter + finally + compensations <- [] + + member x.GetCurrent() = + IEnumerator.check started + if finished then IEnumerator.alreadyFinished() else x.currElement + + interface IFinallyEnumerator with + member x.AppendFinallyAction(f) = + compensations <- f :: compensations + + interface IEnumerator<'T> with + member x.Current = x.GetCurrent() + + interface IEnumerator with + member x.Current = box (x.GetCurrent()) + + member x.MoveNext() = + if not started then (started <- true) + if finished then false + else + let rec takeInner () = + // check the inner list + if currInnerEnum.MoveNext() then + x.currElement <- currInnerEnum.Current + true + else + // check the outer list + let rec takeOuter() = + if outerEnum.MoveNext() then + let ie = outerEnum.Current + // Optimization to detect the statically-allocated empty IEnumerables + match box ie with + | :? EmptyEnumerable<'T> -> + // This one is empty, just skip, don't call GetEnumerator, try again + takeOuter() + | _ -> + // OK, this one may not be empty. + // Don't forget to dispose of the enumerator for the inner list now we're done with it + currInnerEnum.Dispose() + currInnerEnum <- ie.GetEnumerator() + takeInner () + else + // We're done + x.Finish() + false + takeOuter() + takeInner () + + member x.Reset() = IEnumerator.noReset() + + interface System.IDisposable with + member x.Dispose() = + if not finished then + x.Finish() + + let EnumerateUsing (resource : 'T :> System.IDisposable) (rest: 'T -> #seq<'U>) = + (FinallyEnumerable((fun () -> match box resource with null -> () | _ -> resource.Dispose()), + (fun () -> rest resource :> seq<_>)) :> seq<_>) + + let mkConcatSeq (sources: seq<'U :> seq<'T>>) = + mkSeq (fun () -> new ConcatEnumerator<_,_>(sources) :> IEnumerator<'T>) + + let EnumerateWhile (g : unit -> bool) (b: seq<'T>) : seq<'T> = + let started = ref false + let curr = ref None + let getCurr() = + IEnumerator.check !started + match !curr with None -> IEnumerator.alreadyFinished() | Some x -> x + let start() = if not !started then (started := true) + + let finish() = (curr := None) + mkConcatSeq + (mkSeq (fun () -> + { new IEnumerator<_> with + member x.Current = getCurr() + interface IEnumerator with + member x.Current = box (getCurr()) + member x.MoveNext() = + start() + let keepGoing = (try g() with e -> finish (); reraise ()) in + if keepGoing then + curr := Some(b); true + else + finish(); false + member x.Reset() = IEnumerator.noReset() + interface System.IDisposable with + member x.Dispose() = () })) + + let EnumerateThenFinally (rest : seq<'T>) (compensation : unit -> unit) = + (FinallyEnumerable(compensation, (fun () -> rest)) :> seq<_>) + + let CreateEvent (add : 'Delegate -> unit) (remove : 'Delegate -> unit) (create : (obj -> 'Args -> unit) -> 'Delegate ) :IEvent<'Delegate,'Args> = + // Note, we implement each interface explicitly: this works around a bug in the CLR + // implementation on CompactFramework 3.7, used on Windows Phone 7 + { new obj() with + member x.ToString() = "" + interface IEvent<'Delegate,'Args> + interface IDelegateEvent<'Delegate> with + member x.AddHandler(h) = add h + member x.RemoveHandler(h) = remove h + interface System.IObservable<'Args> with + member x.Subscribe(r:IObserver<'Args>) = + let h = create (fun _ args -> r.OnNext(args)) + add h + { new System.IDisposable with + member x.Dispose() = remove h } } + + + [] + type GeneratedSequenceBase<'T>() = + let mutable redirectTo : GeneratedSequenceBase<'T> = Unchecked.defaultof<_> + let mutable redirect : bool = false + + abstract GetFreshEnumerator : unit -> IEnumerator<'T> + abstract GenerateNext : next:byref> -> int // 0 = Stop, 1 = Yield, 2 = Goto + abstract Close: unit -> unit + abstract CheckClose: bool + abstract LastGenerated : 'T + + //[] + member x.MoveNextImpl() = + let active = + if redirect then redirectTo + else x + let mutable target = null + match active.GenerateNext(&target) with + | 1 -> + true + | 2 -> + match target.GetEnumerator() with + | :? GeneratedSequenceBase<'T> as g when not active.CheckClose -> + redirectTo <- g + | e -> + redirectTo <- + { new GeneratedSequenceBase<'T>() with + member x.GetFreshEnumerator() = e + member x.GenerateNext(_) = if e.MoveNext() then 1 else 0 + member x.Close() = try e.Dispose() finally active.Close() + member x.CheckClose = true + member x.LastGenerated = e.Current } + redirect <- true + x.MoveNextImpl() + | _ (* 0 *) -> + false + + interface IEnumerable<'T> with + member x.GetEnumerator() = x.GetFreshEnumerator() + interface IEnumerable with + member x.GetEnumerator() = (x.GetFreshEnumerator() :> IEnumerator) + interface IEnumerator<'T> with + member x.Current = if redirect then redirectTo.LastGenerated else x.LastGenerated + member x.Dispose() = if redirect then redirectTo.Close() else x.Close() + interface IEnumerator with + member x.Current = box (if redirect then redirectTo.LastGenerated else x.LastGenerated) + + //[] + member x.MoveNext() = x.MoveNextImpl() + + member x.Reset() = raise <| new System.NotSupportedException() \ No newline at end of file diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi new file mode 100644 index 00000000000..8c915c921cb --- /dev/null +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -0,0 +1,150 @@ +// 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 internal IEnumerator = + val noReset : unit -> 'a + val notStarted : unit -> 'a + val alreadyFinished : unit -> 'a + val check : started:bool -> unit + val dispose : r:System.IDisposable -> unit + val cast : + e:System.Collections.IEnumerator -> + System.Collections.Generic.IEnumerator<'T> + [] + type EmptyEnumerator<'T> = + class + interface System.IDisposable + interface System.Collections.IEnumerator + interface System.Collections.Generic.IEnumerator<'T> + new : unit -> EmptyEnumerator<'T> + end + val Empty : unit -> System.Collections.Generic.IEnumerator<'T> + [] + type EmptyEnumerable<'T> = + | EmptyEnumerable + with + interface System.Collections.IEnumerable + interface System.Collections.Generic.IEnumerable<'T> + end + + val readAndClear : r:'a option ref -> 'a option + val generateWhileSome : + openf:(unit -> 'a) -> + compute:('a -> 'U option) -> + closef:('a -> unit) -> System.Collections.Generic.IEnumerator<'U> + [] + type Singleton<'T> = + class + interface System.IDisposable + interface System.Collections.IEnumerator + interface System.Collections.Generic.IEnumerator<'T> + new : v:'T -> Singleton<'T> + end + val Singleton : x:'T -> System.Collections.Generic.IEnumerator<'T> + val EnumerateThenFinally : + f:(unit -> unit) -> + e:System.Collections.Generic.IEnumerator<'T> -> + System.Collections.Generic.IEnumerator<'T> + val inline checkNonNull : argName:string -> arg:'a -> unit + val mkSeq : + f:(unit -> System.Collections.Generic.IEnumerator<'U>) -> + System.Collections.Generic.IEnumerable<'U> + +namespace Microsoft.FSharp.Core.CompilerServices + + open System + open System.Collections + open System.Collections.Generic + open Microsoft.FSharp.Core + open Microsoft.FSharp.Collections + + + [] + /// 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> + + /// The F# compiler emits calls to this function to + /// implement the while operator for F# sequence expressions. + /// + /// A function that indicates whether iteration should continue. + /// The input sequence. + /// + /// The result sequence. + val EnumerateWhile : guard:(unit -> bool) -> source:seq<'T> -> seq<'T> + + /// The F# compiler emits calls to this function to + /// implement the try/finally operator for F# sequence expressions. + /// + /// The input sequence. + /// A computation to be included in an enumerator's Dispose method. + /// + /// The result sequence. + val EnumerateThenFinally : source:seq<'T> -> compensation:(unit -> unit) -> seq<'T> + + /// The F# compiler emits calls to this function to implement the compiler-intrinsic + /// conversions from untyped System.Collections.IEnumerable sequences to typed sequences. + /// + /// An initializer function. + /// A function to iterate and test if end of sequence is reached. + /// A function to retrieve the current element. + /// + /// The resulting typed sequence. + val EnumerateFromFunctions: create:(unit -> 'T) -> moveNext:('T -> bool) -> current:('T -> 'U) -> seq<'U> + + /// The F# compiler emits calls to this function to implement the use operator for F# sequence + /// expressions. + /// + /// The resource to be used and disposed. + /// The input sequence. + /// + /// The result sequence. + val EnumerateUsing : resource:'T -> source:('T -> 'Collection) -> seq<'U> when 'T :> IDisposable and 'Collection :> seq<'U> + + /// Creates an anonymous event with the given handlers. + /// + /// A function to handle adding a delegate for the event to trigger. + /// A function to handle removing a delegate that the event triggers. + /// A function to produce the delegate type the event can trigger. + /// + /// The initialized event. + val CreateEvent : addHandler : ('Delegate -> unit) -> removeHandler : ('Delegate -> unit) -> createHandler : ((obj -> 'Args -> unit) -> 'Delegate) -> Microsoft.FSharp.Control.IEvent<'Delegate,'Args> + + [] + /// The F# compiler emits implementations of this type for compiled sequence expressions. + type GeneratedSequenceBase<'T> = + /// The F# compiler emits implementations of this type for compiled sequence expressions. + /// + /// A new sequence generator for the expression. + new : unit -> GeneratedSequenceBase<'T> + /// The F# compiler emits implementations of this type for compiled sequence expressions. + /// + /// A new enumerator for the sequence. + abstract GetFreshEnumerator : unit -> IEnumerator<'T> + /// The F# compiler emits implementations of this type for compiled sequence expressions. + /// + /// A reference to the sequence. + /// + /// A 0, 1, and 2 respectively indicate Stop, Yield, and Goto conditions for the sequence generator. + abstract GenerateNext : result:byref> -> int + /// The F# compiler emits implementations of this type for compiled sequence expressions. + abstract Close: unit -> unit + /// The F# compiler emits implementations of this type for compiled sequence expressions. + abstract CheckClose: bool + /// The F# compiler emits implementations of this type for compiled sequence expressions. + abstract LastGenerated : 'T + interface IEnumerable<'T> + interface IEnumerable + interface IEnumerator<'T> + interface IEnumerator + From 5aec5b304c6283d2448b027b17076c36a8b1c02a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 5 Nov 2016 10:59:20 +1100 Subject: [PATCH 122/286] Remove Helper from signature file Probably shouldn't be exposed in that manor in the first place, but secondly they caused a error in ci_part1. Used this as a chance to rename the module as well. --- src/fsharp/FSharp.Core/seq.fs | 46 ++++---- src/fsharp/FSharp.Core/seqcomposer.fs | 149 ++++++++++++------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 12 -- 3 files changed, 99 insertions(+), 108 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 8d9686b9431..aab6637c07e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -16,6 +16,11 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Primitives.Basics open Microsoft.FSharp.Collections.IEnumerator + module 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 enumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) + [] type CachedSeq<'T>(cleanup,res:seq<'T>) = interface System.IDisposable with @@ -34,7 +39,6 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Core.ICloneableExtensions #else #endif - let mkDelayedSeq (f: unit -> IEnumerable<'T>) = mkSeq (fun () -> f().GetEnumerator()) let inline indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) @@ -51,7 +55,7 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : seq<'T> = Composer.Seq.unfold generator state - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let empty<'T> = (EmptyEnumerable :> seq<'T>) @@ -59,12 +63,12 @@ namespace Microsoft.FSharp.Collections [] let initInfinite<'T> (f:int->'T) : IEnumerable<'T> = Composer.Seq.initInfinite f - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> = Composer.Seq.init count f - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let iter f (source : seq<'T>) = @@ -163,15 +167,15 @@ namespace Microsoft.FSharp.Collections let private seqFactory createSeqComponent (source:seq<'T>) = checkNonNull "source" source match source with - | :? Composer.Core.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose createSeqComponent) - | :? array<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.Seq.Array.create a createSeqComponent) - | :? list<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.Seq.List.create a createSeqComponent) - | _ -> Composer.Helpers.upcastEnumerable (Composer.Seq.Enumerable.create source createSeqComponent) + | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose createSeqComponent) + | :? array<'T> as a -> Upcast.enumerable (Composer.Seq.Array.create a createSeqComponent) + | :? list<'T> as a -> Upcast.enumerable (Composer.Seq.List.create a createSeqComponent) + | _ -> Upcast.enumerable (Composer.Seq.Enumerable.create source createSeqComponent) [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = Composer.Seq.filter f (toComposer source) - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let where f source = filter f source @@ -179,12 +183,12 @@ namespace Microsoft.FSharp.Collections [] let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> = Composer.Seq.map f (toComposer source) - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let mapi f source = Composer.Seq.mapi f (toComposer source) - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let mapi2 f source1 source2 = @@ -195,7 +199,7 @@ namespace Microsoft.FSharp.Collections let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = checkNonNull "source1" source1 match source1 with - | :? Composer.Core.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose (Composer.Seq.Map2FirstFactory (f, source2))) + | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose (Composer.Seq.Map2FirstFactory (f, source2))) | _ -> source2 |> seqFactory (Composer.Seq.Map2SecondFactory (f, source1)) [] @@ -207,12 +211,12 @@ namespace Microsoft.FSharp.Collections [] let choose f source = Composer.Seq.choose f (toComposer source) - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let indexed source = Composer.Seq.indexed (toComposer source) - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let zip source1 source2 = @@ -345,7 +349,7 @@ namespace Microsoft.FSharp.Collections checkNonNull "source2" source2 match source1 with | :? Composer.Seq.Enumerable.EnumerableBase<'T> as s -> s.Append source2 - | _ -> Composer.Helpers.upcastEnumerable (new Composer.Seq.Enumerable.AppendEnumerable<_>([source2; source1])) + | _ -> Upcast.enumerable (new Composer.Seq.Enumerable.AppendEnumerable<_>([source2; source1])) [] @@ -389,7 +393,7 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source : 'T array) = checkNonNull "source" source - Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createId source) + Upcast.enumerable (Composer.Seq.Array.createId source) [] let toArray (source : seq<'T>) = @@ -639,7 +643,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceBy keyf array array - Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedSort) + Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedSort) [] let sort source = @@ -648,7 +652,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlace array array - Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedSort) + Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedSort) [] let sortWith f source = @@ -657,7 +661,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceWith f array array - Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedSort) + Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedSort) [] let inline sortByDescending keyf source = @@ -994,7 +998,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.Reverse array array - Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedReverse) + Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedReverse) [] let permute f (source:seq<_>) = @@ -1003,7 +1007,7 @@ namespace Microsoft.FSharp.Collections source |> toArray |> Array.permute f - Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedPermute) + Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedPermute) [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 3f36e2c1469..6e007722a86 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -14,7 +14,7 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Control open Microsoft.FSharp.Collections open Microsoft.FSharp.Primitives.Basics - + [] module Composer = open IEnumerator @@ -95,22 +95,21 @@ namespace Microsoft.FSharp.Collections open Core - module internal Helpers = + 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 avoidTailCall boolean = match boolean with true -> true | false -> false + 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 upcastSeq (t:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) - let inline upcastFactory (t:#ISeqFactory<'T,'U>) : ISeqFactory<'T,'U> = (# "" t : ISeqFactory<'T,'U> #) - let inline upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) - let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) - let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline upcastICompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) - - open Helpers + let inline seq (t:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) + let inline factory (t:#ISeqFactory<'T,'U>) : ISeqFactory<'T,'U> = (# "" t : ISeqFactory<'T,'U> #) + let inline enumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) + let inline enumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) + let inline enumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) + let inline iCompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) module internal Seq = type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = @@ -128,7 +127,7 @@ namespace Microsoft.FSharp.Collections first.Create outOfBand pipeIdx (second.Create outOfBand (makePipeIdx secondPipeIdx) next) static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = - ComposedFactory(first, second, first.PipeIdx+1) |> upcastFactory + ComposedFactory(first, second, first.PipeIdx+1) |> Upcast.factory and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () @@ -271,7 +270,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = match choose input with - | Some value -> avoidTailCall (next.ProcessNext value) + | Some value -> TailCall.avoid (next.ProcessNext value) | None -> false and Distinct<'T,'V when 'T: equality> (next:Consumer<'T,'V>) = @@ -281,7 +280,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if hashSet.Add input then - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) else false @@ -292,7 +291,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if hashSet.Add(keyFunction input) then - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) else false @@ -303,7 +302,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if cached.Value.Add input then - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) else false @@ -314,7 +313,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if filter input then - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) else false @@ -323,7 +322,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if filter input then - avoidTailCall (next.ProcessNext (map input)) + TailCall.avoid (next.ProcessNext (map input)) else false @@ -333,7 +332,7 @@ namespace Microsoft.FSharp.Collections override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) override __.ProcessNext (input:'T) : bool = - avoidTailCall (next.ProcessNext (map input)) + TailCall.avoid (next.ProcessNext (map input)) and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) @@ -343,7 +342,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'First) : bool = if input2.MoveNext () then - avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) + TailCall.avoid (next.ProcessNext (map'.Invoke (input, input2.Current))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -359,7 +358,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'Second) : bool = if input1.MoveNext () then - avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) + TailCall.avoid (next.ProcessNext (map'.Invoke (input1.Current, input))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -376,7 +375,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'First) : bool = if input2.MoveNext () && input3.MoveNext () then - avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) + TailCall.avoid (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -391,7 +390,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = let u = map input if filter u then - avoidTailCall (next.ProcessNext u) + TailCall.avoid (next.ProcessNext u) else false @@ -403,7 +402,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = idx <- idx + 1 - avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) + TailCall.avoid (next.ProcessNext (mapi'.Invoke (idx-1, input))) and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) @@ -415,7 +414,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'First) : bool = if input2.MoveNext () then idx <- idx + 1 - avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) + TailCall.avoid (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -437,7 +436,7 @@ namespace Microsoft.FSharp.Collections else let currentPair = lastValue, input lastValue <- input - avoidTailCall (next.ProcessNext currentPair) + TailCall.avoid (next.ProcessNext currentPair) and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:Consumer<'State,'V>) = inherit SeqComponent<'T,'V>(next) @@ -447,7 +446,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = foldResult <- f.Invoke(foldResult, input) - avoidTailCall (next.ProcessNext foldResult) + TailCall.avoid (next.ProcessNext foldResult) and Skip<'T,'V> (skipCount:int, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -466,7 +465,7 @@ namespace Microsoft.FSharp.Collections count <- count + 1 false else - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) override __.OnComplete _ = if count < skipCount then @@ -485,9 +484,9 @@ namespace Microsoft.FSharp.Collections if skip then false else - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) else - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) and Take<'T,'V> (takeCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipelineIdx:int) = inherit Truncate<'T, 'V>(takeCount, outOfBand, next, pipelineIdx) @@ -503,7 +502,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if predicate input then - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) else outOfBand.StopFurtherProcessing pipeIdx false @@ -518,7 +517,7 @@ namespace Microsoft.FSharp.Collections first <- false false else - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) override this.OnComplete _ = if first then @@ -536,7 +535,7 @@ namespace Microsoft.FSharp.Collections count <- count + 1 if count = truncateCount then outOfBand.StopFurtherProcessing pipeIdx - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) else outOfBand.StopFurtherProcessing pipeIdx false @@ -562,12 +561,12 @@ namespace Microsoft.FSharp.Collections else if windowSize < 32 then let window = Array.init windowSize (fun i -> circularBuffer.[(idx+i) % windowSize]) - avoidTailCall (next.ProcessNext window) + 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) - avoidTailCall (next.ProcessNext window) + TailCall.avoid (next.ProcessNext window) type SeqProcessNextStates = | InProcess = 0 @@ -652,10 +651,10 @@ namespace Microsoft.FSharp.Collections let consumer = current.Create pipeline emptyPipeIdx result try executeOn pipeline consumer - (upcastICompletionChaining consumer).OnComplete pipeline.HaltedIdx + (Upcast.iCompletionChaining consumer).OnComplete pipeline.HaltedIdx result finally - (upcastICompletionChaining consumer).OnDispose () + (Upcast.iCompletionChaining consumer).OnDispose () module Enumerable = type Empty<'T>() = @@ -680,7 +679,7 @@ namespace Microsoft.FSharp.Collections seqComponent.OnDispose () interface IEnumerator with - member this.Current : obj = box ((upcastEnumerator this)).Current + 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 () @@ -699,13 +698,13 @@ namespace Microsoft.FSharp.Collections abstract member Append : (seq<'T>) -> IEnumerable<'T> - default this.Append source = upcastEnumerable (AppendEnumerable [this; source]) + default this.Append source = Upcast.enumerable (AppendEnumerable [this; source]) interface IEnumerable with member this.GetEnumerator () : IEnumerator = - let genericEnumerable = upcastEnumerable this + let genericEnumerable = Upcast.enumerable this let genericEnumerator = genericEnumerable.GetEnumerator () - upcastEnumeratorNonGeneric genericEnumerator + Upcast.enumeratorNonGeneric genericEnumerator interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () @@ -725,7 +724,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -738,7 +737,7 @@ namespace Microsoft.FSharp.Collections try source.Dispose () finally - (upcastICompletionChaining seqComponent).OnDispose () + (Upcast.iCompletionChaining seqComponent).OnDispose () and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:ISeqFactory<'T,'U>) = inherit EnumerableBase<'U>() @@ -746,11 +745,11 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) + Upcast.seq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.enumerable enumerable) @@ -782,7 +781,7 @@ namespace Microsoft.FSharp.Collections | _ -> failwith "library implementation error: all states should have been handled" interface IEnumerator with - member this.Current = box ((upcastEnumerator this)).Current + member this.Current = box ((Upcast.enumerator this)).Current member __.MoveNext () = state <- SeqProcessNextStates.InProcess moveNext () @@ -798,14 +797,14 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - upcastEnumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) + Upcast.enumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) override this.Append source = - upcastEnumerable (AppendEnumerable (source :: sources)) + Upcast.enumerable (AppendEnumerable (source :: sources)) interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable<'T,'V>(this, next)) + Upcast.seq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) @@ -815,17 +814,17 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - upcastEnumerator (new ConcatEnumerator<_,_> (sources)) + Upcast.enumerator (new ConcatEnumerator<_,_> (sources)) interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable<'T,'V>(this, next)) + Upcast.seq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) let create enumerable current = - upcastSeq (Enumerable(enumerable, current)) + Upcast.seq (Enumerable(enumerable, current)) module EmptyEnumerable = type Enumerable<'T> () = @@ -838,11 +837,11 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () : IEnumerator<'T> = IEnumerator.Empty<'T>() override this.Append source = - upcastEnumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) + Upcast.enumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable.Enumerable<'T,'V>(this, next)) + Upcast.seq (Enumerable.Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) @@ -873,7 +872,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -887,17 +886,17 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) + Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:ISeqFactory<'T,'U>) = - upcastSeq (Enumerable(delayedArray, current)) + Upcast.seq (Enumerable(delayedArray, current)) let create (array:array<'T>) (current:ISeqFactory<'T,'U>) = createDelayed (fun () -> array) current @@ -924,7 +923,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -938,17 +937,17 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) + Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.list alist) let create alist current = - upcastSeq (Enumerable(alist, current)) + Upcast.seq (Enumerable(alist, current)) module Unfold = type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, result:Result<'U>) = @@ -977,11 +976,11 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) + Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.unfold generator state) @@ -1037,7 +1036,7 @@ namespace Microsoft.FSharp.Collections raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else result.SeqState <- SeqProcessNextStates.Finished - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1051,11 +1050,11 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) + Upcast.seq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) member this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = let terminatingIdx = getTerminatingIdx count @@ -1123,19 +1122,19 @@ namespace Microsoft.FSharp.Collections interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable<'T,'V>(count, f, next)) + Upcast.seq (Enumerable<'T,'V>(count, f, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (upcastEnumerable this)) + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (Upcast.enumerable this)) [] let toComposer (source:seq<'T>) : ISeq<'T> = checkNonNull "source" source match source with | :? ISeq<'T> as s -> s - | :? array<'T> as a -> upcastSeq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) - | :? list<'T> as a -> upcastSeq (List.Enumerable(a, IdentityFactory.Instance)) - | _ -> upcastSeq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) + | :? array<'T> as a -> Upcast.seq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) + | :? list<'T> as a -> Upcast.seq (List.Enumerable(a, IdentityFactory.Instance)) + | _ -> Upcast.seq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) let inline foreach f (source:ISeq<_>) = source.ForEach f @@ -1148,17 +1147,17 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = - upcastSeq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) + Upcast.seq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) [] let initInfinite<'T> (f:int->'T) : ISeq<'T> = - upcastSeq (new Init.EnumerableDecider<'T>(Nullable (), f)) + Upcast.seq (new Init.EnumerableDecider<'T>(Nullable (), f)) [] let init<'T> (count:int) (f:int->'T) : ISeq<'T> = if count < 0 then invalidArgInputMustBeNonNegative "count" count elif count = 0 then empty else - upcastSeq (new Init.EnumerableDecider<'T>(Nullable count, f)) + Upcast.seq (new Init.EnumerableDecider<'T>(Nullable count, f)) [] let iter f (source:ISeq<'T>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 838cee6da37..522f35b06da 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -82,18 +82,6 @@ namespace Microsoft.FSharp.Collections open Core - module internal Helpers = - val inline avoidTailCall : boolean:bool -> bool - val inline upcastSeq : t: #ISeq<'T> -> ISeq<'T> - val inline upcastFactory : - t: #ISeqFactory<'T,'U> -> ISeqFactory<'T,'U> - val inline upcastEnumerable : t:#IEnumerable<'T> -> IEnumerable<'T> - val inline upcastEnumerator : t:#IEnumerator<'T> ->IEnumerator<'T> - val inline upcastEnumeratorNonGeneric : - t:#IEnumerator -> IEnumerator - val inline upcastICompletionChaining : - t: #ICompletionChaining -> ICompletionChaining - module internal Seq = [] type SeqComponentFactory<'T,'U> = From d45c1a42e7f5d33943b8c07d1625e8b0d222fae3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 5 Nov 2016 11:02:40 +1100 Subject: [PATCH 123/286] Update LinqAggreagates output Due to the change in the inline functions within Seq (i.e. sum etc.) there are significant changes within this file. --- .../Linq101Aggregates01.il.netfx4.bsl | 1518 +++++++++-------- 1 file changed, 813 insertions(+), 705 deletions(-) diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Aggregates01.il.netfx4.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Aggregates01.il.netfx4.bsl index 97e240269b4..9f4b80a6edf 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Aggregates01.il.netfx4.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Aggregates01.il.netfx4.bsl @@ -38,20 +38,20 @@ } .mresource public FSharpSignatureData.Linq101Aggregates01 { - // Offset: 0x00000000 Length: 0x0000060C + // Offset: 0x00000000 Length: 0x000005FA } .mresource public FSharpOptimizationData.Linq101Aggregates01 { - // Offset: 0x00000610 Length: 0x00000211 + // Offset: 0x00000600 Length: 0x00000211 } .module Linq101Aggregates01.exe -// MVID: {58067926-D281-4783-A745-038326790658} +// MVID: {581D1D27-D281-4783-A745-0383271D1D58} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00AC0000 +// Image base: 0x02BA0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -116,7 +116,7 @@ // Code size 196 (0xc4) .maxstack 6 .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 100001,100001 : 0,0 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\CodeGen\\EmittedIL\\QueryExpressionStepping\\Linq101Aggregates01.fs' + .line 100001,100001 : 0,0 'C:\\src\\visualfsharp\\tests\\fsharpqa\\Source\\CodeGen\\EmittedIL\\QueryExpressionStepping\\Linq101Aggregates01.fs' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/uniqueFactors@12::pc IL_0006: ldc.i4.1 @@ -823,6 +823,90 @@ } // end of class 'numSum@22-1' + .class auto autochar serializable sealed nested assembly beforefieldinit specialname 'numSum@22-3' + extends class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2 + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public specialname rtspecialname + instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f) cil managed + { + // Code size 18 (0x12) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'numSum@22-3'::f + IL_0007: nop + IL_0008: ldarg.0 + IL_0009: ldc.i4.0 + IL_000a: callvirt instance void class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2::.ctor(!1) + IL_000f: ldarg.0 + IL_0010: pop + IL_0011: ret + } // end of method 'numSum@22-3'::.ctor + + .method public hidebysig virtual instance bool + ProcessNext(int32 input) cil managed + { + // Code size 28 (0x1c) + .maxstack 8 + .line 22,22 : 9,16 '' + IL_0000: ldarg.0 + IL_0001: ldarg.0 + IL_0002: ldfld !1 class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2::Value + IL_0007: ldarg.0 + IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'numSum@22-3'::f + IL_000d: ldarg.1 + IL_000e: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0013: add.ovf + IL_0014: stfld !1 class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2::Value + IL_0019: nop + IL_001a: ldc.i4.0 + IL_001b: ret + } // end of method 'numSum@22-3'::ProcessNext + + } // end of class 'numSum@22-3' + + .class auto ansi serializable nested assembly beforefieldinit 'numSum@22-2' + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2> + { + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method assembly specialname rtspecialname + instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 14 (0xe) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2>::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'numSum@22-2'::f + IL_000d: ret + } // end of method 'numSum@22-2'::.ctor + + .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2 + Invoke(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 _arg1) cil managed + { + // Code size 13 (0xd) + .maxstack 8 + .line 22,22 : 9,16 '' + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'numSum@22-2'::f + IL_0007: newobj instance void Linq101Aggregates01/'numSum@22-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) + IL_000c: ret + } // end of method 'numSum@22-2'::Invoke + + } // end of class 'numSum@22-2' + .class auto autochar serializable sealed nested assembly beforefieldinit specialname totalChars@30 extends class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1 { @@ -1219,6 +1303,90 @@ } // end of class 'totalChars@31-1' + .class auto autochar serializable sealed nested assembly beforefieldinit specialname 'totalChars@31-3' + extends class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2 + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public specialname rtspecialname + instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f) cil managed + { + // Code size 18 (0x12) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'totalChars@31-3'::f + IL_0007: nop + IL_0008: ldarg.0 + IL_0009: ldc.i4.0 + IL_000a: callvirt instance void class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2::.ctor(!1) + IL_000f: ldarg.0 + IL_0010: pop + IL_0011: ret + } // end of method 'totalChars@31-3'::.ctor + + .method public hidebysig virtual instance bool + ProcessNext(string input) cil managed + { + // Code size 28 (0x1c) + .maxstack 8 + .line 31,31 : 9,25 '' + IL_0000: ldarg.0 + IL_0001: ldarg.0 + IL_0002: ldfld !1 class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2::Value + IL_0007: ldarg.0 + IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'totalChars@31-3'::f + IL_000d: ldarg.1 + IL_000e: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0013: add.ovf + IL_0014: stfld !1 class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2::Value + IL_0019: nop + IL_001a: ldc.i4.0 + IL_001b: ret + } // end of method 'totalChars@31-3'::ProcessNext + + } // end of class 'totalChars@31-3' + + .class auto ansi serializable nested assembly beforefieldinit 'totalChars@31-2' + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2> + { + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method assembly specialname rtspecialname + instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 14 (0xe) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2>::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'totalChars@31-2'::f + IL_000d: ret + } // end of method 'totalChars@31-2'::.ctor + + .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2 + Invoke(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 _arg1) cil managed + { + // Code size 13 (0xd) + .maxstack 8 + .line 31,31 : 9,25 '' + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'totalChars@31-2'::f + IL_0007: newobj instance void Linq101Aggregates01/'totalChars@31-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) + IL_000c: ret + } // end of method 'totalChars@31-2'::Invoke + + } // end of class 'totalChars@31-2' + .class auto ansi serializable nested assembly beforefieldinit categories@39 extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> { @@ -1723,6 +1891,90 @@ } // end of class 'sum@43-1' + .class auto autochar serializable sealed nested assembly beforefieldinit specialname 'sum@43-3' + extends class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2 + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public specialname rtspecialname + instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f) cil managed + { + // Code size 18 (0x12) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'sum@43-3'::f + IL_0007: nop + IL_0008: ldarg.0 + IL_0009: ldc.i4.0 + IL_000a: callvirt instance void class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2::.ctor(!1) + IL_000f: ldarg.0 + IL_0010: pop + IL_0011: ret + } // end of method 'sum@43-3'::.ctor + + .method public hidebysig virtual instance bool + ProcessNext(class [Utils]Utils/Product input) cil managed + { + // Code size 28 (0x1c) + .maxstack 8 + .line 43,43 : 13,33 '' + IL_0000: ldarg.0 + IL_0001: ldarg.0 + IL_0002: ldfld !1 class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2::Value + IL_0007: ldarg.0 + IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'sum@43-3'::f + IL_000d: ldarg.1 + IL_000e: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0013: add.ovf + IL_0014: stfld !1 class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2::Value + IL_0019: nop + IL_001a: ldc.i4.0 + IL_001b: ret + } // end of method 'sum@43-3'::ProcessNext + + } // end of class 'sum@43-3' + + .class auto ansi serializable nested assembly beforefieldinit 'sum@43-2' + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2> + { + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method assembly specialname rtspecialname + instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 f) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 14 (0xe) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2>::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'sum@43-2'::f + IL_000d: ret + } // end of method 'sum@43-2'::.ctor + + .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2 + Invoke(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 _arg1) cil managed + { + // Code size 13 (0xd) + .maxstack 8 + .line 43,43 : 13,33 '' + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 Linq101Aggregates01/'sum@43-2'::f + IL_0007: newobj instance void Linq101Aggregates01/'sum@43-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) + IL_000c: ret + } // end of method 'sum@43-2'::Invoke + + } // end of class 'sum@43-2' + .class auto ansi serializable nested assembly beforefieldinit 'categories@40-3' extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,int32>,object>> { @@ -1745,7 +1997,7 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,int32>,object> Invoke(class [System.Core]System.Linq.IGrouping`2 _arg2) cil managed { - // Code size 169 (0xa9) + // Code size 116 (0x74) .maxstack 10 .locals init ([0] class [System.Core]System.Linq.IGrouping`2 g, [1] int32 sum, @@ -1755,10 +2007,7 @@ [5] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 V_5, [6] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_6, [7] class [mscorlib]System.Collections.Generic.IEnumerable`1 V_7, - [8] class [mscorlib]System.Collections.Generic.IEnumerator`1 V_8, - [9] int32 V_9, - [10] int32 V_10, - [11] class [mscorlib]System.IDisposable V_11) + [8] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2> V_8) .line 40,40 : 38,39 '' IL_0000: nop IL_0001: ldarg.1 @@ -1793,70 +2042,25 @@ IL_0039: ldloc.s V_5 IL_003b: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() IL_0040: stloc.s V_7 - IL_0042: ldloc.s V_7 - IL_0044: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() + IL_0042: ldloc.s V_6 + IL_0044: newobj instance void Linq101Aggregates01/'sum@43-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) IL_0049: stloc.s V_8 - .try - { - IL_004b: ldc.i4.0 - IL_004c: stloc.s V_10 - IL_004e: ldloc.s V_8 - IL_0050: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() - IL_0055: brfalse.s IL_006d - - .line 43,43 : 13,33 '' - IL_0057: ldloc.s V_10 - IL_0059: ldloc.s V_6 - IL_005b: ldloc.s V_8 - IL_005d: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() - IL_0062: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_0067: add.ovf - IL_0068: stloc.s V_10 - .line 100001,100001 : 0,0 '' - IL_006a: nop - IL_006b: br.s IL_004e - - IL_006d: ldloc.s V_10 - IL_006f: stloc.s V_9 - IL_0071: leave.s IL_0091 - - } // end .try - finally - { - IL_0073: ldloc.s V_8 - IL_0075: isinst [mscorlib]System.IDisposable - IL_007a: stloc.s V_11 - IL_007c: ldloc.s V_11 - IL_007e: brfalse.s IL_0082 - - IL_0080: br.s IL_0084 - - IL_0082: br.s IL_008e - - .line 100001,100001 : 0,0 '' - IL_0084: ldloc.s V_11 - IL_0086: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_008b: ldnull - IL_008c: pop - IL_008d: endfinally - .line 100001,100001 : 0,0 '' - IL_008e: ldnull - IL_008f: pop - IL_0090: endfinally - .line 100001,100001 : 0,0 '' - } // end handler - IL_0091: ldloc.s V_9 - IL_0093: stloc.1 + IL_004b: ldloc.s V_7 + IL_004d: call class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/ISeq`1 [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToComposer(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0052: ldloc.s V_8 + IL_0054: callvirt instance !!0 class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/ISeq`1::ForEach>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!0>) + IL_0059: ldfld !1 class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2::Value + IL_005e: stloc.1 .line 45,45 : 9,28 '' - IL_0094: ldarg.0 - IL_0095: ldfld class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder Linq101Aggregates01/'categories@40-3'::builder@ - IL_009a: ldloc.0 - IL_009b: ldloc.1 - IL_009c: newobj instance void class [mscorlib]System.Tuple`2,int32>::.ctor(!0, + IL_005f: ldarg.0 + IL_0060: ldfld class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder Linq101Aggregates01/'categories@40-3'::builder@ + IL_0065: ldloc.0 + IL_0066: ldloc.1 + IL_0067: newobj instance void class [mscorlib]System.Tuple`2,int32>::.ctor(!0, !1) - IL_00a1: tail. - IL_00a3: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Yield,int32>,object>(!!0) - IL_00a8: ret + IL_006c: tail. + IL_006e: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Yield,int32>,object>(!!0) + IL_0073: ret } // end of method 'categories@40-3'::Invoke } // end of class 'categories@40-3' @@ -7987,7 +8191,7 @@ .method public static void main@() cil managed { .entrypoint - // Code size 1965 (0x7ad) + // Code size 1859 (0x743) .maxstack 13 .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 factorsOf300, [1] int32 uniqueFactors, @@ -8016,56 +8220,50 @@ [24] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 V_24, [25] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_25, [26] class [mscorlib]System.Collections.Generic.IEnumerable`1 V_26, - [27] class [mscorlib]System.Collections.Generic.IEnumerator`1 V_27, - [28] int32 V_28, - [29] int32 V_29, - [30] class [mscorlib]System.IDisposable V_30, - [31] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_31, - [32] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_32, - [33] class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> V_33, - [34] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 V_34, - [35] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_35, - [36] class [mscorlib]System.Collections.Generic.IEnumerable`1 V_36, - [37] class [mscorlib]System.Collections.Generic.IEnumerator`1 V_37, - [38] int32 V_38, - [39] int32 V_39, - [40] class [mscorlib]System.IDisposable V_40, + [27] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2> V_27, + [28] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_28, + [29] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_29, + [30] class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> V_30, + [31] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 V_31, + [32] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_32, + [33] class [mscorlib]System.Collections.Generic.IEnumerable`1 V_33, + [34] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2> V_34, + [35] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_35, + [36] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_36, + [37] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_37, + [38] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_38, + [39] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_39, + [40] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_40, [41] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_41, [42] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_42, [43] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_43, [44] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_44, [45] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_45, - [46] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_46, - [47] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_47, - [48] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_48, - [49] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_49, - [50] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_50, - [51] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_51, - [52] class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> V_52, - [53] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 V_53, - [54] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_54, - [55] class [mscorlib]System.Collections.Generic.IEnumerable`1 V_55, - [56] class [mscorlib]System.Collections.Generic.IEnumerator`1 V_56, - [57] float64 V_57, - [58] float64 V_58, - [59] int32 V_59, - [60] float64 V_60, - [61] int32 V_61, - [62] class [mscorlib]System.IDisposable V_62, - [63] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_63, - [64] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_64, - [65] class [mscorlib]System.Tuple`2,class [mscorlib]System.Collections.IEnumerable>,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64>> V_65, - [66] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable> V_66, - [67] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64> V_67, - [68] class [mscorlib]System.Collections.Generic.IEnumerable`1> V_68, - [69] class [mscorlib]System.Collections.Generic.IEnumerator`1> V_69, - [70] float64 V_70, - [71] float64 V_71, - [72] int32 V_72, - [73] float64 V_73, - [74] int32 V_74, - [75] class [mscorlib]System.IDisposable V_75, - [76] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_76) + [46] class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> V_46, + [47] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 V_47, + [48] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_48, + [49] class [mscorlib]System.Collections.Generic.IEnumerable`1 V_49, + [50] class [mscorlib]System.Collections.Generic.IEnumerator`1 V_50, + [51] float64 V_51, + [52] float64 V_52, + [53] int32 V_53, + [54] float64 V_54, + [55] int32 V_55, + [56] class [mscorlib]System.IDisposable V_56, + [57] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_57, + [58] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_58, + [59] class [mscorlib]System.Tuple`2,class [mscorlib]System.Collections.IEnumerable>,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64>> V_59, + [60] class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable> V_60, + [61] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64> V_61, + [62] class [mscorlib]System.Collections.Generic.IEnumerable`1> V_62, + [63] class [mscorlib]System.Collections.Generic.IEnumerator`1> V_63, + [64] float64 V_64, + [65] float64 V_65, + [66] int32 V_66, + [67] float64 V_67, + [68] int32 V_68, + [69] class [mscorlib]System.IDisposable V_69, + [70] class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder V_70) .line 8,8 : 1,31 '' IL_0000: nop IL_0001: ldc.i4.2 @@ -8171,739 +8369,649 @@ IL_00da: ldloc.s V_24 IL_00dc: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() IL_00e1: stloc.s V_26 - IL_00e3: ldloc.s V_26 - IL_00e5: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() + IL_00e3: ldloc.s V_25 + IL_00e5: newobj instance void Linq101Aggregates01/'numSum@22-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) IL_00ea: stloc.s V_27 - .try - { - IL_00ec: ldc.i4.0 - IL_00ed: stloc.s V_29 - IL_00ef: ldloc.s V_27 - IL_00f1: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() - IL_00f6: brfalse.s IL_010e - - .line 22,22 : 9,16 '' - IL_00f8: ldloc.s V_29 - IL_00fa: ldloc.s V_25 - IL_00fc: ldloc.s V_27 - IL_00fe: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() - IL_0103: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_0108: add.ovf - IL_0109: stloc.s V_29 - .line 100001,100001 : 0,0 '' - IL_010b: nop - IL_010c: br.s IL_00ef - - IL_010e: ldloc.s V_29 - IL_0110: stloc.s V_28 - IL_0112: leave.s IL_0132 - - } // end .try - finally - { - IL_0114: ldloc.s V_27 - IL_0116: isinst [mscorlib]System.IDisposable - IL_011b: stloc.s V_30 - IL_011d: ldloc.s V_30 - IL_011f: brfalse.s IL_0123 - - IL_0121: br.s IL_0125 - - IL_0123: br.s IL_012f - - .line 100001,100001 : 0,0 '' - IL_0125: ldloc.s V_30 - IL_0127: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_012c: ldnull - IL_012d: pop - IL_012e: endfinally - .line 100001,100001 : 0,0 '' - IL_012f: ldnull - IL_0130: pop - IL_0131: endfinally - .line 100001,100001 : 0,0 '' - } // end handler - IL_0132: ldloc.s V_28 - IL_0134: dup - IL_0135: stsfld int32 ''.$Linq101Aggregates01::numSum@19 - IL_013a: stloc.3 + IL_00ec: ldloc.s V_26 + IL_00ee: call class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/ISeq`1 [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToComposer(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_00f3: ldloc.s V_27 + IL_00f5: callvirt instance !!0 class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/ISeq`1::ForEach>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!0>) + IL_00fa: ldfld !1 class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2::Value + IL_00ff: dup + IL_0100: stsfld int32 ''.$Linq101Aggregates01::numSum@19 + IL_0105: stloc.3 .line 26,26 : 1,45 '' - IL_013b: ldstr "cherry" - IL_0140: ldstr "apple" - IL_0145: ldstr "blueberry" - IL_014a: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() - IL_014f: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_0106: ldstr "cherry" + IL_010b: ldstr "apple" + IL_0110: ldstr "blueberry" + IL_0115: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_011a: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_0154: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_011f: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_0159: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_0124: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_015e: dup - IL_015f: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::words@26 - IL_0164: stloc.s words - IL_0166: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_016b: stloc.s V_31 - IL_016d: ldloc.s V_31 - IL_016f: stloc.s V_32 - IL_0171: ldnull - IL_0172: ldnull - IL_0173: ldnull - IL_0174: ldc.i4.0 - IL_0175: ldnull - IL_0176: newobj instance void Linq101Aggregates01/totalChars@30::.ctor(string, + IL_0129: dup + IL_012a: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::words@26 + IL_012f: stloc.s words + IL_0131: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_0136: stloc.s V_28 + IL_0138: ldloc.s V_28 + IL_013a: stloc.s V_29 + IL_013c: ldnull + IL_013d: ldnull + IL_013e: ldnull + IL_013f: ldc.i4.0 + IL_0140: ldnull + IL_0141: newobj instance void Linq101Aggregates01/totalChars@30::.ctor(string, string, class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, string) - IL_017b: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0180: newobj instance void Linq101Aggregates01/'totalChars@31-1'::.ctor() - IL_0185: newobj instance void class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::.ctor(!0, + IL_0146: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_014b: newobj instance void Linq101Aggregates01/'totalChars@31-1'::.ctor() + IL_0150: newobj instance void class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::.ctor(!0, !1) - IL_018a: stloc.s V_33 - IL_018c: ldloc.s V_33 - IL_018e: call instance !0 class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::get_Item1() - IL_0193: stloc.s V_34 - IL_0195: ldloc.s V_33 - IL_0197: call instance !1 class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::get_Item2() - IL_019c: stloc.s V_35 - IL_019e: ldloc.s V_34 - IL_01a0: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() - IL_01a5: stloc.s V_36 - IL_01a7: ldloc.s V_36 - IL_01a9: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() - IL_01ae: stloc.s V_37 - .try - { - IL_01b0: ldc.i4.0 - IL_01b1: stloc.s V_39 - IL_01b3: ldloc.s V_37 - IL_01b5: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() - IL_01ba: brfalse.s IL_01d2 - - .line 31,31 : 9,25 '' - IL_01bc: ldloc.s V_39 - IL_01be: ldloc.s V_35 - IL_01c0: ldloc.s V_37 - IL_01c2: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() - IL_01c7: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_01cc: add.ovf - IL_01cd: stloc.s V_39 - .line 100001,100001 : 0,0 '' - IL_01cf: nop - IL_01d0: br.s IL_01b3 - - IL_01d2: ldloc.s V_39 - IL_01d4: stloc.s V_38 - IL_01d6: leave.s IL_01f6 - - } // end .try - finally - { - IL_01d8: ldloc.s V_37 - IL_01da: isinst [mscorlib]System.IDisposable - IL_01df: stloc.s V_40 - IL_01e1: ldloc.s V_40 - IL_01e3: brfalse.s IL_01e7 - - IL_01e5: br.s IL_01e9 - - IL_01e7: br.s IL_01f3 - - .line 100001,100001 : 0,0 '' - IL_01e9: ldloc.s V_40 - IL_01eb: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_01f0: ldnull - IL_01f1: pop - IL_01f2: endfinally - .line 100001,100001 : 0,0 '' - IL_01f3: ldnull - IL_01f4: pop - IL_01f5: endfinally - .line 100001,100001 : 0,0 '' - } // end handler - IL_01f6: ldloc.s V_38 - IL_01f8: dup - IL_01f9: stsfld int32 ''.$Linq101Aggregates01::totalChars@28 - IL_01fe: stloc.s totalChars + IL_0155: stloc.s V_30 + IL_0157: ldloc.s V_30 + IL_0159: call instance !0 class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::get_Item1() + IL_015e: stloc.s V_31 + IL_0160: ldloc.s V_30 + IL_0162: call instance !1 class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::get_Item2() + IL_0167: stloc.s V_32 + IL_0169: ldloc.s V_31 + IL_016b: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() + IL_0170: stloc.s V_33 + IL_0172: ldloc.s V_32 + IL_0174: newobj instance void Linq101Aggregates01/'totalChars@31-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) + IL_0179: stloc.s V_34 + IL_017b: ldloc.s V_33 + IL_017d: call class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/ISeq`1 [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToComposer(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0182: ldloc.s V_34 + IL_0184: callvirt instance !!0 class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/ISeq`1::ForEach>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!0>) + IL_0189: ldfld !1 class [FSharp.Core]Microsoft.FSharp.Collections.ComposerModule/Core/Folder`2::Value + IL_018e: dup + IL_018f: stsfld int32 ''.$Linq101Aggregates01::totalChars@28 + IL_0194: stloc.s totalChars .line 35,35 : 1,32 '' - IL_0200: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [Utils]Utils::getProductList() - IL_0205: dup - IL_0206: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::products@35 - IL_020b: stloc.s products + IL_0196: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [Utils]Utils::getProductList() + IL_019b: dup + IL_019c: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::products@35 + IL_01a1: stloc.s products .line 37,46 : 1,21 '' - IL_020d: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_0212: stloc.s V_41 - IL_0214: ldloc.s V_41 - IL_0216: ldloc.s V_41 - IL_0218: ldloc.s V_41 - IL_021a: ldloc.s V_41 - IL_021c: ldloc.s V_41 - IL_021e: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_0223: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1 - IL_0228: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_022d: ldloc.s V_41 - IL_022f: newobj instance void Linq101Aggregates01/categories@39::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_0234: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_01a3: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_01a8: stloc.s V_35 + IL_01aa: ldloc.s V_35 + IL_01ac: ldloc.s V_35 + IL_01ae: ldloc.s V_35 + IL_01b0: ldloc.s V_35 + IL_01b2: ldloc.s V_35 + IL_01b4: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_01b9: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1 + IL_01be: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_01c3: ldloc.s V_35 + IL_01c5: newobj instance void Linq101Aggregates01/categories@39::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_01ca: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0239: newobj instance void Linq101Aggregates01/'categories@40-1'::.ctor() - IL_023e: newobj instance void Linq101Aggregates01/'categories@40-2'::.ctor() - IL_0243: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_01cf: newobj instance void Linq101Aggregates01/'categories@40-1'::.ctor() + IL_01d4: newobj instance void Linq101Aggregates01/'categories@40-2'::.ctor() + IL_01d9: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0248: ldloc.s V_41 - IL_024a: newobj instance void Linq101Aggregates01/'categories@40-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_024f: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,int32>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_01de: ldloc.s V_35 + IL_01e0: newobj instance void Linq101Aggregates01/'categories@40-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_01e5: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,int32>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0254: newobj instance void Linq101Aggregates01/'categories@45-4'::.ctor() - IL_0259: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,int32>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_01ea: newobj instance void Linq101Aggregates01/'categories@45-4'::.ctor() + IL_01ef: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,int32>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_025e: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_0263: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0268: dup - IL_0269: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories@37 - IL_026e: stloc.s categories - IL_0270: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_0275: stloc.s V_42 - IL_0277: ldloc.s V_42 - IL_0279: ldc.i4.0 - IL_027a: ldc.i4.0 - IL_027b: ldnull - IL_027c: ldc.i4.0 - IL_027d: ldc.i4.0 - IL_027e: newobj instance void Linq101Aggregates01/minNum@49::.ctor(int32, + IL_01f4: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_01f9: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_01fe: dup + IL_01ff: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories@37 + IL_0204: stloc.s categories + IL_0206: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_020b: stloc.s V_36 + IL_020d: ldloc.s V_36 + IL_020f: ldc.i4.0 + IL_0210: ldc.i4.0 + IL_0211: ldnull + IL_0212: ldc.i4.0 + IL_0213: ldc.i4.0 + IL_0214: newobj instance void Linq101Aggregates01/minNum@49::.ctor(int32, int32, class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, int32) - IL_0283: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0288: newobj instance void Linq101Aggregates01/'minNum@49-1'::.ctor() - IL_028d: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MinBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0219: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_021e: newobj instance void Linq101Aggregates01/'minNum@49-1'::.ctor() + IL_0223: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MinBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0292: dup - IL_0293: stsfld int32 ''.$Linq101Aggregates01::minNum@49 - IL_0298: stloc.s minNum - IL_029a: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_029f: stloc.s V_43 - IL_02a1: ldloc.s V_43 - IL_02a3: ldnull - IL_02a4: ldnull - IL_02a5: ldnull - IL_02a6: ldc.i4.0 - IL_02a7: ldnull - IL_02a8: newobj instance void Linq101Aggregates01/shortestWord@52::.ctor(string, + IL_0228: dup + IL_0229: stsfld int32 ''.$Linq101Aggregates01::minNum@49 + IL_022e: stloc.s minNum + IL_0230: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_0235: stloc.s V_37 + IL_0237: ldloc.s V_37 + IL_0239: ldnull + IL_023a: ldnull + IL_023b: ldnull + IL_023c: ldc.i4.0 + IL_023d: ldnull + IL_023e: newobj instance void Linq101Aggregates01/shortestWord@52::.ctor(string, string, class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, string) - IL_02ad: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_02b2: newobj instance void Linq101Aggregates01/'shortestWord@52-1'::.ctor() - IL_02b7: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MinBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0243: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0248: newobj instance void Linq101Aggregates01/'shortestWord@52-1'::.ctor() + IL_024d: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MinBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_02bc: dup - IL_02bd: stsfld int32 ''.$Linq101Aggregates01::shortestWord@52 - IL_02c2: stloc.s shortestWord + IL_0252: dup + IL_0253: stsfld int32 ''.$Linq101Aggregates01::shortestWord@52 + IL_0258: stloc.s shortestWord .line 55,61 : 1,21 '' - IL_02c4: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_02c9: stloc.s V_44 - IL_02cb: ldloc.s V_44 - IL_02cd: ldloc.s V_44 - IL_02cf: ldloc.s V_44 - IL_02d1: ldloc.s V_44 - IL_02d3: ldloc.s V_44 - IL_02d5: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_02da: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1 - IL_02df: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_02e4: ldloc.s V_44 - IL_02e6: newobj instance void Linq101Aggregates01/categories2@57::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_02eb: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_025a: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_025f: stloc.s V_38 + IL_0261: ldloc.s V_38 + IL_0263: ldloc.s V_38 + IL_0265: ldloc.s V_38 + IL_0267: ldloc.s V_38 + IL_0269: ldloc.s V_38 + IL_026b: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_0270: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1 + IL_0275: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_027a: ldloc.s V_38 + IL_027c: newobj instance void Linq101Aggregates01/categories2@57::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_0281: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_02f0: newobj instance void Linq101Aggregates01/'categories2@58-1'::.ctor() - IL_02f5: newobj instance void Linq101Aggregates01/'categories2@58-2'::.ctor() - IL_02fa: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0286: newobj instance void Linq101Aggregates01/'categories2@58-1'::.ctor() + IL_028b: newobj instance void Linq101Aggregates01/'categories2@58-2'::.ctor() + IL_0290: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_02ff: ldloc.s V_44 - IL_0301: newobj instance void Linq101Aggregates01/'categories2@58-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_0306: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0295: ldloc.s V_38 + IL_0297: newobj instance void Linq101Aggregates01/'categories2@58-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_029c: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_030b: newobj instance void Linq101Aggregates01/'categories2@60-4'::.ctor() - IL_0310: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_02a1: newobj instance void Linq101Aggregates01/'categories2@60-4'::.ctor() + IL_02a6: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0315: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_031a: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_031f: dup - IL_0320: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories2@55 - IL_0325: stloc.s categories2 + IL_02ab: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_02b0: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_02b5: dup + IL_02b6: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories2@55 + IL_02bb: stloc.s categories2 .line 64,71 : 1,21 '' - IL_0327: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_032c: stloc.s V_45 - IL_032e: ldloc.s V_45 - IL_0330: ldloc.s V_45 - IL_0332: ldloc.s V_45 - IL_0334: ldloc.s V_45 - IL_0336: ldloc.s V_45 - IL_0338: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_033d: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1 - IL_0342: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0347: ldloc.s V_45 - IL_0349: newobj instance void Linq101Aggregates01/categories3@66::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_034e: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_02bd: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_02c2: stloc.s V_39 + IL_02c4: ldloc.s V_39 + IL_02c6: ldloc.s V_39 + IL_02c8: ldloc.s V_39 + IL_02ca: ldloc.s V_39 + IL_02cc: ldloc.s V_39 + IL_02ce: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_02d3: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1 + IL_02d8: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_02dd: ldloc.s V_39 + IL_02df: newobj instance void Linq101Aggregates01/categories3@66::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_02e4: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0353: newobj instance void Linq101Aggregates01/'categories3@67-1'::.ctor() - IL_0358: newobj instance void Linq101Aggregates01/'categories3@67-2'::.ctor() - IL_035d: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_02e9: newobj instance void Linq101Aggregates01/'categories3@67-1'::.ctor() + IL_02ee: newobj instance void Linq101Aggregates01/'categories3@67-2'::.ctor() + IL_02f3: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0362: ldloc.s V_45 - IL_0364: newobj instance void Linq101Aggregates01/'categories3@67-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_0369: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`3,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_02f8: ldloc.s V_39 + IL_02fa: newobj instance void Linq101Aggregates01/'categories3@67-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_02ff: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`3,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_036e: newobj instance void Linq101Aggregates01/'categories3@70-4'::.ctor() - IL_0373: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0304: newobj instance void Linq101Aggregates01/'categories3@70-4'::.ctor() + IL_0309: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0378: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2>,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_037d: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0382: dup - IL_0383: stsfld class [mscorlib]System.Tuple`2>[] ''.$Linq101Aggregates01::categories3@64 - IL_0388: stloc.s categories3 - IL_038a: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_038f: stloc.s V_46 - IL_0391: ldloc.s V_46 - IL_0393: ldc.i4.0 - IL_0394: ldc.i4.0 - IL_0395: ldnull - IL_0396: ldc.i4.0 - IL_0397: ldc.i4.0 - IL_0398: newobj instance void Linq101Aggregates01/maxNum@74::.ctor(int32, + IL_030e: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2>,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_0313: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0318: dup + IL_0319: stsfld class [mscorlib]System.Tuple`2>[] ''.$Linq101Aggregates01::categories3@64 + IL_031e: stloc.s categories3 + IL_0320: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_0325: stloc.s V_40 + IL_0327: ldloc.s V_40 + IL_0329: ldc.i4.0 + IL_032a: ldc.i4.0 + IL_032b: ldnull + IL_032c: ldc.i4.0 + IL_032d: ldc.i4.0 + IL_032e: newobj instance void Linq101Aggregates01/maxNum@74::.ctor(int32, int32, class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, int32) - IL_039d: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_03a2: newobj instance void Linq101Aggregates01/'maxNum@74-1'::.ctor() - IL_03a7: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MaxBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0333: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0338: newobj instance void Linq101Aggregates01/'maxNum@74-1'::.ctor() + IL_033d: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MaxBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_03ac: dup - IL_03ad: stsfld int32 ''.$Linq101Aggregates01::maxNum@74 - IL_03b2: stloc.s maxNum - IL_03b4: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_03b9: stloc.s V_47 - IL_03bb: ldloc.s V_47 - IL_03bd: ldnull - IL_03be: ldnull - IL_03bf: ldnull - IL_03c0: ldc.i4.0 - IL_03c1: ldnull - IL_03c2: newobj instance void Linq101Aggregates01/longestLength@77::.ctor(string, + IL_0342: dup + IL_0343: stsfld int32 ''.$Linq101Aggregates01::maxNum@74 + IL_0348: stloc.s maxNum + IL_034a: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_034f: stloc.s V_41 + IL_0351: ldloc.s V_41 + IL_0353: ldnull + IL_0354: ldnull + IL_0355: ldnull + IL_0356: ldc.i4.0 + IL_0357: ldnull + IL_0358: newobj instance void Linq101Aggregates01/longestLength@77::.ctor(string, string, class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, string) - IL_03c7: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_03cc: newobj instance void Linq101Aggregates01/'longestLength@77-1'::.ctor() - IL_03d1: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MaxBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_035d: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0362: newobj instance void Linq101Aggregates01/'longestLength@77-1'::.ctor() + IL_0367: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MaxBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_03d6: dup - IL_03d7: stsfld int32 ''.$Linq101Aggregates01::longestLength@77 - IL_03dc: stloc.s longestLength + IL_036c: dup + IL_036d: stsfld int32 ''.$Linq101Aggregates01::longestLength@77 + IL_0372: stloc.s longestLength .line 80,86 : 1,21 '' - IL_03de: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_03e3: stloc.s V_48 - IL_03e5: ldloc.s V_48 - IL_03e7: ldloc.s V_48 - IL_03e9: ldloc.s V_48 - IL_03eb: ldloc.s V_48 - IL_03ed: ldloc.s V_48 - IL_03ef: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_03f4: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1 - IL_03f9: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_03fe: ldloc.s V_48 - IL_0400: newobj instance void Linq101Aggregates01/categories4@82::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_0405: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0374: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_0379: stloc.s V_42 + IL_037b: ldloc.s V_42 + IL_037d: ldloc.s V_42 + IL_037f: ldloc.s V_42 + IL_0381: ldloc.s V_42 + IL_0383: ldloc.s V_42 + IL_0385: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_038a: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1 + IL_038f: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0394: ldloc.s V_42 + IL_0396: newobj instance void Linq101Aggregates01/categories4@82::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_039b: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_040a: newobj instance void Linq101Aggregates01/'categories4@83-1'::.ctor() - IL_040f: newobj instance void Linq101Aggregates01/'categories4@83-2'::.ctor() - IL_0414: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_03a0: newobj instance void Linq101Aggregates01/'categories4@83-1'::.ctor() + IL_03a5: newobj instance void Linq101Aggregates01/'categories4@83-2'::.ctor() + IL_03aa: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0419: ldloc.s V_48 - IL_041b: newobj instance void Linq101Aggregates01/'categories4@83-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_0420: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_03af: ldloc.s V_42 + IL_03b1: newobj instance void Linq101Aggregates01/'categories4@83-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_03b6: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0425: newobj instance void Linq101Aggregates01/'categories4@85-4'::.ctor() - IL_042a: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_03bb: newobj instance void Linq101Aggregates01/'categories4@85-4'::.ctor() + IL_03c0: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_042f: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_0434: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0439: dup - IL_043a: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories4@80 - IL_043f: stloc.s categories4 + IL_03c5: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_03ca: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_03cf: dup + IL_03d0: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories4@80 + IL_03d5: stloc.s categories4 .line 89,96 : 1,21 '' - IL_0441: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_0446: stloc.s V_49 - IL_0448: ldloc.s V_49 - IL_044a: ldloc.s V_49 - IL_044c: ldloc.s V_49 - IL_044e: ldloc.s V_49 - IL_0450: ldloc.s V_49 - IL_0452: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_0457: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1 - IL_045c: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0461: ldloc.s V_49 - IL_0463: newobj instance void Linq101Aggregates01/categories5@91::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_0468: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_03d7: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_03dc: stloc.s V_43 + IL_03de: ldloc.s V_43 + IL_03e0: ldloc.s V_43 + IL_03e2: ldloc.s V_43 + IL_03e4: ldloc.s V_43 + IL_03e6: ldloc.s V_43 + IL_03e8: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_03ed: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1 + IL_03f2: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_03f7: ldloc.s V_43 + IL_03f9: newobj instance void Linq101Aggregates01/categories5@91::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_03fe: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_046d: newobj instance void Linq101Aggregates01/'categories5@92-1'::.ctor() - IL_0472: newobj instance void Linq101Aggregates01/'categories5@92-2'::.ctor() - IL_0477: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0403: newobj instance void Linq101Aggregates01/'categories5@92-1'::.ctor() + IL_0408: newobj instance void Linq101Aggregates01/'categories5@92-2'::.ctor() + IL_040d: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_047c: ldloc.s V_49 - IL_047e: newobj instance void Linq101Aggregates01/'categories5@92-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_0483: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`3,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0412: ldloc.s V_43 + IL_0414: newobj instance void Linq101Aggregates01/'categories5@92-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_0419: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`3,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0488: newobj instance void Linq101Aggregates01/'categories5@95-4'::.ctor() - IL_048d: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_041e: newobj instance void Linq101Aggregates01/'categories5@95-4'::.ctor() + IL_0423: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0492: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2>,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_0497: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_049c: dup - IL_049d: stsfld class [mscorlib]System.Tuple`2>[] ''.$Linq101Aggregates01::categories5@89 - IL_04a2: stloc.s categories5 + IL_0428: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2>,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_042d: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0432: dup + IL_0433: stsfld class [mscorlib]System.Tuple`2>[] ''.$Linq101Aggregates01::categories5@89 + IL_0438: stloc.s categories5 .line 99,99 : 1,66 '' - IL_04a4: ldc.r8 5. - IL_04ad: ldc.r8 4. - IL_04b6: ldc.r8 1. - IL_04bf: ldc.r8 3. - IL_04c8: ldc.r8 9. - IL_04d1: ldc.r8 8. - IL_04da: ldc.r8 6. - IL_04e3: ldc.r8 7. - IL_04ec: ldc.r8 2. - IL_04f5: ldc.r8 0.0 - IL_04fe: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() - IL_0503: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_043a: ldc.r8 5. + IL_0443: ldc.r8 4. + IL_044c: ldc.r8 1. + IL_0455: ldc.r8 3. + IL_045e: ldc.r8 9. + IL_0467: ldc.r8 8. + IL_0470: ldc.r8 6. + IL_0479: ldc.r8 7. + IL_0482: ldc.r8 2. + IL_048b: ldc.r8 0.0 + IL_0494: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_0499: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_0508: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_049e: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_050d: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_04a3: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_0512: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_04a8: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_0517: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_04ad: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_051c: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_04b2: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_0521: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_04b7: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_0526: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_04bc: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_052b: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_04c1: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_0530: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_04c6: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_0535: dup - IL_0536: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::numbers2@99 - IL_053b: stloc.s numbers2 - IL_053d: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_0542: stloc.s V_50 - IL_0544: ldloc.s V_50 - IL_0546: stloc.s V_51 - IL_0548: ldc.r8 0.0 - IL_0551: ldc.r8 0.0 - IL_055a: ldnull - IL_055b: ldc.i4.0 - IL_055c: ldc.r8 0.0 - IL_0565: newobj instance void Linq101Aggregates01/averageNum@100::.ctor(float64, + IL_04cb: dup + IL_04cc: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::numbers2@99 + IL_04d1: stloc.s numbers2 + IL_04d3: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_04d8: stloc.s V_44 + IL_04da: ldloc.s V_44 + IL_04dc: stloc.s V_45 + IL_04de: ldc.r8 0.0 + IL_04e7: ldc.r8 0.0 + IL_04f0: ldnull + IL_04f1: ldc.i4.0 + IL_04f2: ldc.r8 0.0 + IL_04fb: newobj instance void Linq101Aggregates01/averageNum@100::.ctor(float64, float64, class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, float64) - IL_056a: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_056f: newobj instance void Linq101Aggregates01/'averageNum@100-1'::.ctor() - IL_0574: newobj instance void class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::.ctor(!0, + IL_0500: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0505: newobj instance void Linq101Aggregates01/'averageNum@100-1'::.ctor() + IL_050a: newobj instance void class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::.ctor(!0, !1) - IL_0579: stloc.s V_52 - IL_057b: ldloc.s V_52 - IL_057d: call instance !0 class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::get_Item1() - IL_0582: stloc.s V_53 - IL_0584: ldloc.s V_52 - IL_0586: call instance !1 class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::get_Item2() - IL_058b: stloc.s V_54 - IL_058d: ldloc.s V_53 - IL_058f: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() - IL_0594: stloc.s V_55 - IL_0596: ldloc.s V_55 - IL_0598: box class [mscorlib]System.Collections.Generic.IEnumerable`1 - IL_059d: brfalse.s IL_05a1 - - IL_059f: br.s IL_05b4 + IL_050f: stloc.s V_46 + IL_0511: ldloc.s V_46 + IL_0513: call instance !0 class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::get_Item1() + IL_0518: stloc.s V_47 + IL_051a: ldloc.s V_46 + IL_051c: call instance !1 class [mscorlib]System.Tuple`2,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::get_Item2() + IL_0521: stloc.s V_48 + IL_0523: ldloc.s V_47 + IL_0525: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() + IL_052a: stloc.s V_49 + IL_052c: ldloc.s V_49 + IL_052e: box class [mscorlib]System.Collections.Generic.IEnumerable`1 + IL_0533: brfalse.s IL_0537 + + IL_0535: br.s IL_054a .line 100001,100001 : 0,0 '' - IL_05a1: ldstr "source" - IL_05a6: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string) - IL_05ab: call !!0 [FSharp.Core]Microsoft.FSharp.Core.Operators::Raise(class [mscorlib]System.Exception) - IL_05b0: pop + IL_0537: ldstr "source" + IL_053c: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string) + IL_0541: call !!0 [FSharp.Core]Microsoft.FSharp.Core.Operators::Raise(class [mscorlib]System.Exception) + IL_0546: pop .line 100001,100001 : 0,0 '' - IL_05b1: nop - IL_05b2: br.s IL_05b5 + IL_0547: nop + IL_0548: br.s IL_054b .line 100001,100001 : 0,0 '' .line 100001,100001 : 0,0 '' - IL_05b4: nop - IL_05b5: ldloc.s V_55 - IL_05b7: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() - IL_05bc: stloc.s V_56 + IL_054a: nop + IL_054b: ldloc.s V_49 + IL_054d: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() + IL_0552: stloc.s V_50 .try { - IL_05be: ldc.r8 0.0 - IL_05c7: stloc.s V_58 - IL_05c9: ldc.i4.0 - IL_05ca: stloc.s V_59 - IL_05cc: ldloc.s V_56 - IL_05ce: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() - IL_05d3: brfalse.s IL_05f1 - - IL_05d5: ldloc.s V_58 - IL_05d7: ldloc.s V_54 - IL_05d9: ldloc.s V_56 - IL_05db: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() - IL_05e0: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_05e5: add - IL_05e6: stloc.s V_58 + IL_0554: ldc.r8 0.0 + IL_055d: stloc.s V_52 + IL_055f: ldc.i4.0 + IL_0560: stloc.s V_53 + IL_0562: ldloc.s V_50 + IL_0564: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() + IL_0569: brfalse.s IL_0587 + + IL_056b: ldloc.s V_52 + IL_056d: ldloc.s V_48 + IL_056f: ldloc.s V_50 + IL_0571: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() + IL_0576: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_057b: add + IL_057c: stloc.s V_52 .line 100,100 : 47,58 '' - IL_05e8: ldloc.s V_59 - IL_05ea: ldc.i4.1 - IL_05eb: add - IL_05ec: stloc.s V_59 + IL_057e: ldloc.s V_53 + IL_0580: ldc.i4.1 + IL_0581: add + IL_0582: stloc.s V_53 .line 100001,100001 : 0,0 '' - IL_05ee: nop - IL_05ef: br.s IL_05cc + IL_0584: nop + IL_0585: br.s IL_0562 - IL_05f1: ldloc.s V_59 - IL_05f3: brtrue.s IL_05f7 + IL_0587: ldloc.s V_53 + IL_0589: brtrue.s IL_058d - IL_05f5: br.s IL_05f9 + IL_058b: br.s IL_058f - IL_05f7: br.s IL_060c + IL_058d: br.s IL_05a2 .line 100001,100001 : 0,0 '' - IL_05f9: ldstr "source" - IL_05fe: newobj instance void [mscorlib]System.InvalidOperationException::.ctor(string) - IL_0603: call !!0 [FSharp.Core]Microsoft.FSharp.Core.Operators::Raise(class [mscorlib]System.Exception) - IL_0608: pop + IL_058f: ldstr "source" + IL_0594: newobj instance void [mscorlib]System.InvalidOperationException::.ctor(string) + IL_0599: call !!0 [FSharp.Core]Microsoft.FSharp.Core.Operators::Raise(class [mscorlib]System.Exception) + IL_059e: pop .line 100001,100001 : 0,0 '' - IL_0609: nop - IL_060a: br.s IL_060d + IL_059f: nop + IL_05a0: br.s IL_05a3 .line 100001,100001 : 0,0 '' .line 100001,100001 : 0,0 '' - IL_060c: nop - IL_060d: ldloc.s V_58 - IL_060f: stloc.s V_60 - IL_0611: ldloc.s V_59 - IL_0613: stloc.s V_61 - IL_0615: ldloc.s V_60 - IL_0617: ldloc.s V_61 - IL_0619: conv.r8 - IL_061a: div - IL_061b: stloc.s V_57 - IL_061d: leave.s IL_063d + IL_05a2: nop + IL_05a3: ldloc.s V_52 + IL_05a5: stloc.s V_54 + IL_05a7: ldloc.s V_53 + IL_05a9: stloc.s V_55 + IL_05ab: ldloc.s V_54 + IL_05ad: ldloc.s V_55 + IL_05af: conv.r8 + IL_05b0: div + IL_05b1: stloc.s V_51 + IL_05b3: leave.s IL_05d3 } // end .try finally { - IL_061f: ldloc.s V_56 - IL_0621: isinst [mscorlib]System.IDisposable - IL_0626: stloc.s V_62 - IL_0628: ldloc.s V_62 - IL_062a: brfalse.s IL_062e + IL_05b5: ldloc.s V_50 + IL_05b7: isinst [mscorlib]System.IDisposable + IL_05bc: stloc.s V_56 + IL_05be: ldloc.s V_56 + IL_05c0: brfalse.s IL_05c4 - IL_062c: br.s IL_0630 + IL_05c2: br.s IL_05c6 - IL_062e: br.s IL_063a + IL_05c4: br.s IL_05d0 .line 100001,100001 : 0,0 '' - IL_0630: ldloc.s V_62 - IL_0632: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_0637: ldnull - IL_0638: pop - IL_0639: endfinally + IL_05c6: ldloc.s V_56 + IL_05c8: callvirt instance void [mscorlib]System.IDisposable::Dispose() + IL_05cd: ldnull + IL_05ce: pop + IL_05cf: endfinally .line 100001,100001 : 0,0 '' - IL_063a: ldnull - IL_063b: pop - IL_063c: endfinally + IL_05d0: ldnull + IL_05d1: pop + IL_05d2: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_063d: ldloc.s V_57 - IL_063f: dup - IL_0640: stsfld float64 ''.$Linq101Aggregates01::averageNum@100 - IL_0645: stloc.s averageNum - IL_0647: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_064c: stloc.s V_63 - IL_064e: ldloc.s V_63 - IL_0650: stloc.s V_64 - IL_0652: ldloc.s V_63 - IL_0654: ldloc.s V_63 - IL_0656: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_words() - IL_065b: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1 - IL_0660: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0665: ldloc.s V_63 - IL_0667: newobj instance void Linq101Aggregates01/averageLength@105::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_066c: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_05d3: ldloc.s V_51 + IL_05d5: dup + IL_05d6: stsfld float64 ''.$Linq101Aggregates01::averageNum@100 + IL_05db: stloc.s averageNum + IL_05dd: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_05e2: stloc.s V_57 + IL_05e4: ldloc.s V_57 + IL_05e6: stloc.s V_58 + IL_05e8: ldloc.s V_57 + IL_05ea: ldloc.s V_57 + IL_05ec: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_words() + IL_05f1: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1 + IL_05f6: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_05fb: ldloc.s V_57 + IL_05fd: newobj instance void Linq101Aggregates01/averageLength@105::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_0602: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0671: newobj instance void Linq101Aggregates01/'averageLength@107-1'::.ctor() - IL_0676: newobj instance void class [mscorlib]System.Tuple`2,class [mscorlib]System.Collections.IEnumerable>,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64>>::.ctor(!0, + IL_0607: newobj instance void Linq101Aggregates01/'averageLength@107-1'::.ctor() + IL_060c: newobj instance void class [mscorlib]System.Tuple`2,class [mscorlib]System.Collections.IEnumerable>,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64>>::.ctor(!0, !1) - IL_067b: stloc.s V_65 - IL_067d: ldloc.s V_65 - IL_067f: call instance !0 class [mscorlib]System.Tuple`2,class [mscorlib]System.Collections.IEnumerable>,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64>>::get_Item1() - IL_0684: stloc.s V_66 - IL_0686: ldloc.s V_65 - IL_0688: call instance !1 class [mscorlib]System.Tuple`2,class [mscorlib]System.Collections.IEnumerable>,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64>>::get_Item2() - IL_068d: stloc.s V_67 - IL_068f: ldloc.s V_66 - IL_0691: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_0696: stloc.s V_68 - IL_0698: ldloc.s V_68 - IL_069a: box class [mscorlib]System.Collections.Generic.IEnumerable`1> - IL_069f: brfalse.s IL_06a3 - - IL_06a1: br.s IL_06b6 + IL_0611: stloc.s V_59 + IL_0613: ldloc.s V_59 + IL_0615: call instance !0 class [mscorlib]System.Tuple`2,class [mscorlib]System.Collections.IEnumerable>,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64>>::get_Item1() + IL_061a: stloc.s V_60 + IL_061c: ldloc.s V_59 + IL_061e: call instance !1 class [mscorlib]System.Tuple`2,class [mscorlib]System.Collections.IEnumerable>,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64>>::get_Item2() + IL_0623: stloc.s V_61 + IL_0625: ldloc.s V_60 + IL_0627: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_062c: stloc.s V_62 + IL_062e: ldloc.s V_62 + IL_0630: box class [mscorlib]System.Collections.Generic.IEnumerable`1> + IL_0635: brfalse.s IL_0639 + + IL_0637: br.s IL_064c .line 100001,100001 : 0,0 '' - IL_06a3: ldstr "source" - IL_06a8: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string) - IL_06ad: call !!0 [FSharp.Core]Microsoft.FSharp.Core.Operators::Raise(class [mscorlib]System.Exception) - IL_06b2: pop + IL_0639: ldstr "source" + IL_063e: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string) + IL_0643: call !!0 [FSharp.Core]Microsoft.FSharp.Core.Operators::Raise(class [mscorlib]System.Exception) + IL_0648: pop .line 100001,100001 : 0,0 '' - IL_06b3: nop - IL_06b4: br.s IL_06b7 + IL_0649: nop + IL_064a: br.s IL_064d .line 100001,100001 : 0,0 '' .line 100001,100001 : 0,0 '' - IL_06b6: nop - IL_06b7: ldloc.s V_68 - IL_06b9: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1>::GetEnumerator() - IL_06be: stloc.s V_69 + IL_064c: nop + IL_064d: ldloc.s V_62 + IL_064f: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1>::GetEnumerator() + IL_0654: stloc.s V_63 .try { - IL_06c0: ldc.r8 0.0 - IL_06c9: stloc.s V_71 - IL_06cb: ldc.i4.0 - IL_06cc: stloc.s V_72 - IL_06ce: ldloc.s V_69 - IL_06d0: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() - IL_06d5: brfalse.s IL_06f3 - - IL_06d7: ldloc.s V_71 - IL_06d9: ldloc.s V_67 - IL_06db: ldloc.s V_69 - IL_06dd: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1>::get_Current() - IL_06e2: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64>::Invoke(!0) - IL_06e7: add - IL_06e8: stloc.s V_71 + IL_0656: ldc.r8 0.0 + IL_065f: stloc.s V_65 + IL_0661: ldc.i4.0 + IL_0662: stloc.s V_66 + IL_0664: ldloc.s V_63 + IL_0666: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() + IL_066b: brfalse.s IL_0689 + + IL_066d: ldloc.s V_65 + IL_066f: ldloc.s V_61 + IL_0671: ldloc.s V_63 + IL_0673: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1>::get_Current() + IL_0678: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64>::Invoke(!0) + IL_067d: add + IL_067e: stloc.s V_65 .line 107,107 : 9,21 '' - IL_06ea: ldloc.s V_72 - IL_06ec: ldc.i4.1 - IL_06ed: add - IL_06ee: stloc.s V_72 + IL_0680: ldloc.s V_66 + IL_0682: ldc.i4.1 + IL_0683: add + IL_0684: stloc.s V_66 .line 100001,100001 : 0,0 '' - IL_06f0: nop - IL_06f1: br.s IL_06ce + IL_0686: nop + IL_0687: br.s IL_0664 - IL_06f3: ldloc.s V_72 - IL_06f5: brtrue.s IL_06f9 + IL_0689: ldloc.s V_66 + IL_068b: brtrue.s IL_068f - IL_06f7: br.s IL_06fb + IL_068d: br.s IL_0691 - IL_06f9: br.s IL_070e + IL_068f: br.s IL_06a4 .line 100001,100001 : 0,0 '' - IL_06fb: ldstr "source" - IL_0700: newobj instance void [mscorlib]System.InvalidOperationException::.ctor(string) - IL_0705: call !!0 [FSharp.Core]Microsoft.FSharp.Core.Operators::Raise(class [mscorlib]System.Exception) - IL_070a: pop + IL_0691: ldstr "source" + IL_0696: newobj instance void [mscorlib]System.InvalidOperationException::.ctor(string) + IL_069b: call !!0 [FSharp.Core]Microsoft.FSharp.Core.Operators::Raise(class [mscorlib]System.Exception) + IL_06a0: pop .line 100001,100001 : 0,0 '' - IL_070b: nop - IL_070c: br.s IL_070f + IL_06a1: nop + IL_06a2: br.s IL_06a5 .line 100001,100001 : 0,0 '' .line 100001,100001 : 0,0 '' - IL_070e: nop - IL_070f: ldloc.s V_71 - IL_0711: stloc.s V_73 - IL_0713: ldloc.s V_72 - IL_0715: stloc.s V_74 - IL_0717: ldloc.s V_73 - IL_0719: ldloc.s V_74 - IL_071b: conv.r8 - IL_071c: div - IL_071d: stloc.s V_70 - IL_071f: leave.s IL_073f + IL_06a4: nop + IL_06a5: ldloc.s V_65 + IL_06a7: stloc.s V_67 + IL_06a9: ldloc.s V_66 + IL_06ab: stloc.s V_68 + IL_06ad: ldloc.s V_67 + IL_06af: ldloc.s V_68 + IL_06b1: conv.r8 + IL_06b2: div + IL_06b3: stloc.s V_64 + IL_06b5: leave.s IL_06d5 } // end .try finally { - IL_0721: ldloc.s V_69 - IL_0723: isinst [mscorlib]System.IDisposable - IL_0728: stloc.s V_75 - IL_072a: ldloc.s V_75 - IL_072c: brfalse.s IL_0730 + IL_06b7: ldloc.s V_63 + IL_06b9: isinst [mscorlib]System.IDisposable + IL_06be: stloc.s V_69 + IL_06c0: ldloc.s V_69 + IL_06c2: brfalse.s IL_06c6 - IL_072e: br.s IL_0732 + IL_06c4: br.s IL_06c8 - IL_0730: br.s IL_073c + IL_06c6: br.s IL_06d2 .line 100001,100001 : 0,0 '' - IL_0732: ldloc.s V_75 - IL_0734: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_0739: ldnull - IL_073a: pop - IL_073b: endfinally + IL_06c8: ldloc.s V_69 + IL_06ca: callvirt instance void [mscorlib]System.IDisposable::Dispose() + IL_06cf: ldnull + IL_06d0: pop + IL_06d1: endfinally .line 100001,100001 : 0,0 '' - IL_073c: ldnull - IL_073d: pop - IL_073e: endfinally + IL_06d2: ldnull + IL_06d3: pop + IL_06d4: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_073f: ldloc.s V_70 - IL_0741: dup - IL_0742: stsfld float64 ''.$Linq101Aggregates01::averageLength@103 - IL_0747: stloc.s averageLength + IL_06d5: ldloc.s V_64 + IL_06d7: dup + IL_06d8: stsfld float64 ''.$Linq101Aggregates01::averageLength@103 + IL_06dd: stloc.s averageLength .line 111,117 : 1,21 '' - IL_0749: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_074e: stloc.s V_76 - IL_0750: ldloc.s V_76 - IL_0752: ldloc.s V_76 - IL_0754: ldloc.s V_76 - IL_0756: ldloc.s V_76 - IL_0758: ldloc.s V_76 - IL_075a: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_075f: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1 - IL_0764: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0769: ldloc.s V_76 - IL_076b: newobj instance void Linq101Aggregates01/categories6@113::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_0770: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_06df: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_06e4: stloc.s V_70 + IL_06e6: ldloc.s V_70 + IL_06e8: ldloc.s V_70 + IL_06ea: ldloc.s V_70 + IL_06ec: ldloc.s V_70 + IL_06ee: ldloc.s V_70 + IL_06f0: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_06f5: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1 + IL_06fa: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_06ff: ldloc.s V_70 + IL_0701: newobj instance void Linq101Aggregates01/categories6@113::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_0706: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0775: newobj instance void Linq101Aggregates01/'categories6@114-1'::.ctor() - IL_077a: newobj instance void Linq101Aggregates01/'categories6@114-2'::.ctor() - IL_077f: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_070b: newobj instance void Linq101Aggregates01/'categories6@114-1'::.ctor() + IL_0710: newobj instance void Linq101Aggregates01/'categories6@114-2'::.ctor() + IL_0715: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0784: ldloc.s V_76 - IL_0786: newobj instance void Linq101Aggregates01/'categories6@114-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_078b: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_071a: ldloc.s V_70 + IL_071c: newobj instance void Linq101Aggregates01/'categories6@114-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_0721: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0790: newobj instance void Linq101Aggregates01/'categories6@116-4'::.ctor() - IL_0795: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0726: newobj instance void Linq101Aggregates01/'categories6@116-4'::.ctor() + IL_072b: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_079a: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_079f: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_07a4: dup - IL_07a5: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories6@111 - IL_07aa: stloc.s categories6 - IL_07ac: ret + IL_0730: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_0735: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_073a: dup + IL_073b: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories6@111 + IL_0740: stloc.s categories6 + IL_0742: ret } // end of method $Linq101Aggregates01::main@ } // end of class ''.$Linq101Aggregates01 From 9c4782da2e67fb5e86ce33431a456d4f3cbe6d39 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 5 Nov 2016 15:37:03 +1100 Subject: [PATCH 124/286] Modified item/tryItem to use skip Unit tests check that the item call object the lazy nature of the Seq.init --- src/fsharp/FSharp.Core/seq.fs | 68 ++++++++++---------------- src/fsharp/FSharp.Core/seqcomposer.fs | 34 +++++++------ src/fsharp/FSharp.Core/seqcomposer.fsi | 6 ++- 3 files changed, 47 insertions(+), 61 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index aab6637c07e..edefb6a630f 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -45,10 +45,18 @@ namespace Microsoft.FSharp.Collections [] let toComposer (source:seq<'T>): Composer.Core.ISeq<'T> = Composer.Seq.toComposer source - + let inline foreach f (source:seq<_>) = Composer.Seq.foreach f (toComposer source) + let private seqFactory createSeqComponent (source:seq<'T>) = + checkNonNull "source" source + match source with + | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose createSeqComponent) + | :? array<'T> as a -> Upcast.enumerable (Composer.Seq.Array.create a createSeqComponent) + | :? list<'T> as a -> Upcast.enumerable (Composer.Seq.List.create a createSeqComponent) + | _ -> Upcast.enumerable (Composer.Seq.Enumerable.create source createSeqComponent) + [] let delay f = mkDelayedSeq f @@ -74,28 +82,25 @@ namespace Microsoft.FSharp.Collections let iter f (source : seq<'T>) = Composer.Seq.iter f (toComposer source) + [] + let tryHead (source : seq<_>) = + Composer.Seq.tryHead (toComposer source) + + [] + let skip count (source: seq<_>) = + source |> seqFactory (Composer.Seq.SkipFactory (count, invalidOpFmt)) + + let invalidArgumnetIndex = invalidArgFmt "index" + [] let item i (source : seq<'T>) = if i < 0 then invalidArgInputMustBeNonNegative "index" i else - source - |> foreach (fun halt -> - { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values<_,_,_> (0, false, Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - if this.Value._1 = i then - this.Value._2 <- true - this.Value._3 <- value - halt () - else - this.Value._1 <- this.Value._1 + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - override this.OnComplete _ = - if not this.Value._2 then - let index = i - this.Value._1 + 1 - invalidArgFmt "index" - "{0}\nseq was short by {1} {2}" - [|SR.GetString SR.notEnoughElements; index; (if index=1 then "element" else "elements")|] - }) - |> fun item -> item.Value._3 + source + |> seqFactory (Composer.Seq.SkipFactory (i, invalidArgumnetIndex)) + |> tryHead + |> function + | None -> invalidArgFmt "index" "{0}\nseq was short by 1 element" [|SR.GetString SR.notEnoughElements|] + | Some value -> value [] let tryItem i (source:seq<'T>) = @@ -164,14 +169,6 @@ namespace Microsoft.FSharp.Collections let revamp3 f (ie1 : seq<_>) (source2 : seq<_>) (source3 : seq<_>) = mkSeq (fun () -> f (ie1.GetEnumerator()) (source2.GetEnumerator()) (source3.GetEnumerator())) - let private seqFactory createSeqComponent (source:seq<'T>) = - checkNonNull "source" source - match source with - | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose createSeqComponent) - | :? array<'T> as a -> Upcast.enumerable (Composer.Seq.Array.create a createSeqComponent) - | :? list<'T> as a -> Upcast.enumerable (Composer.Seq.List.create a createSeqComponent) - | _ -> Upcast.enumerable (Composer.Seq.Enumerable.create source createSeqComponent) - [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = Composer.Seq.filter f (toComposer source) @@ -879,10 +876,6 @@ namespace Microsoft.FSharp.Collections let takeWhile p (source: seq<_>) = source |> seqFactory (Composer.Seq.TakeWhileFactory p) - [] - let skip count (source: seq<_>) = - source |> seqFactory (Composer.Seq.SkipFactory count) - [] let skipWhile p (source: seq<_>) = source |> seqFactory (Composer.Seq.SkipWhileFactory p) @@ -927,17 +920,6 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun exists -> exists.Value - [] - let tryHead (source : seq<_>) = - source - |> foreach (fun halt -> - { new Composer.Core.Folder<'T, Option<'T>> (None) with - override this.ProcessNext value = - this.Value <- Some value - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun head -> head.Value - [] let head (source : seq<_>) = match tryHead source with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 6e007722a86..f5324016f7f 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -207,10 +207,10 @@ namespace Microsoft.FSharp.Collections interface ISeqFactory<'T,'State> with member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) - and SkipFactory<'T> (count:int) = + and SkipFactory<'T> (count:int, onNotEnoughElements) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, onNotEnoughElements, next) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () @@ -448,7 +448,7 @@ namespace Microsoft.FSharp.Collections foldResult <- f.Invoke(foldResult, input) TailCall.avoid (next.ProcessNext foldResult) - and Skip<'T,'V> (skipCount:int, next:Consumer<'T,'V>) = + and Skip<'T,'V> (skipCount:int, notEnoughElements:string->array->unit, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -470,7 +470,7 @@ namespace Microsoft.FSharp.Collections override __.OnComplete _ = if count < skipCount then let x = skipCount - count - invalidOpFmt "tried to skip {0} {1} past the end of the seq" + notEnoughElements "{0}\ntried to skip {1} {2} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] and SkipWhile<'T,'V> (predicate:'T->bool, next:Consumer<'T,'V>) = @@ -640,7 +640,7 @@ namespace Microsoft.FSharp.Collections if maybeSkipping then maybeSkipping <- isSkipping () - if (not maybeSkipping) then + if not maybeSkipping then consumer.ProcessNext (f (idx+1)) |> ignore idx <- idx + 1 @@ -1169,20 +1169,22 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore - [] - let tryItem i (source:ISeq<'T>) = - if i < 0 then None else - source + [] + let tryHead (source:ISeq<'T>) = + source |> foreach (fun halt -> - { new Folder<'T, Values>> (Values<_,_> (0, None)) with + { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = - if this.Value._1 = i then - this.Value._2 <- Some value - halt () - else - this.Value._1 <- this.Value._1 + 1 + this.Value <- Some value + halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun item -> item.Value._2 + |> fun head -> head.Value + + [] + let tryItem i (source:ISeq<'T>) = + if i < 0 then None else + source.Compose (SkipFactory(i, fun _ _ -> ())) + |> tryHead [] let iteri f (source:ISeq<'T>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 522f35b06da..e0c19da96bc 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -203,7 +203,7 @@ namespace Microsoft.FSharp.Collections class inherit SeqComponentFactory<'T,'T> interface ISeqFactory<'T,'T> - new : count:int -> SkipFactory<'T> + new : count:int * notEnoughElements:(string->array->unit) -> SkipFactory<'T> end and SkipWhileFactory<'T> = class @@ -387,7 +387,7 @@ namespace Microsoft.FSharp.Collections and Skip<'T,'V> = class inherit SeqComponent<'T,'V> - new : skipCount:int * next: Consumer<'T,'V> -> + new : skipCount:int * exceptionOnNotEnoughElements:(string->array->unit) * next: Consumer<'T,'V> -> Skip<'T,'V> override OnComplete : PipeIdx -> unit override ProcessNext : input:'T -> bool @@ -710,6 +710,8 @@ namespace Microsoft.FSharp.Collections val init : count:int -> f:(int -> 'T) -> ISeq<'T> [] val iter : f:('T -> unit) -> source: ISeq<'T> -> unit + [] + val tryHead : source: ISeq<'T> -> 'T option [] val tryItem : i:int -> source: ISeq<'T> -> 'T option [] From a73cee47adb75dda7e0dd640ae22d778be9f0100 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 6 Nov 2016 08:56:59 +1100 Subject: [PATCH 125/286] Patch up the surface area. Still subject to change. --- .../SurfaceArea.coreclr.fs | 58 +++++++++++++++++++ .../SurfaceArea.net40.fs | 58 +++++++++++++++++++ .../SurfaceArea.portable259.fs | 58 +++++++++++++++++++ .../SurfaceArea.portable47.fs | 58 +++++++++++++++++++ .../SurfaceArea.portable7.fs | 58 +++++++++++++++++++ .../SurfaceArea.portable78.fs | 58 +++++++++++++++++++ .../fsharpqa/Source/Misc/LongSourceFile01.fs | 58 +++++++++++++++++++ 7 files changed, 406 insertions(+) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs index cd7c9087a50..8b8c19eb713 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs @@ -207,6 +207,63 @@ Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.ICom Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] Structural[T]() Microsoft.FSharp.Collections.ComparisonIdentity: System.String ToString() Microsoft.FSharp.Collections.ComparisonIdentity: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: TResult Value +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void .ctor(TResult) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+IOutOfBand: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Consumer`2 Create[V](IOutOfBand, System.Nullable`1[System.Int32], Consumer`2) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Int32 PipeIdx +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Int32 get_PipeIdx() +Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T]: ISeq`1 Compose[TResult](ISeqFactory`2) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T]: a ForEach[a](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit],a]) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Void .ctor(a, b) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: a _1 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: b _2 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Void .ctor(a, b, c) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: a _1 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: b _2 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: c _3 +Microsoft.FSharp.Collections.ComposerModule+Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+IOutOfBand +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c] +Microsoft.FSharp.Collections.ComposerModule+Core: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule: Microsoft.FSharp.Collections.ComposerModule+Core +Microsoft.FSharp.Collections.ComposerModule: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule: System.Type GetType() Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Int32 Cons Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Int32 Empty @@ -432,6 +489,7 @@ Microsoft.FSharp.Collections.SeqModule: Boolean Exists[T](Microsoft.FSharp.Core. Microsoft.FSharp.Collections.SeqModule: Boolean ForAll2[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 ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Boolean IsEmpty[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: ISeq`1 ToComposer[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], System.Collections.Generic.IEnumerable`1[T], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs index 0fdcc27abea..f446ac887cc 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs @@ -194,6 +194,63 @@ Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.ICom Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] Structural[T]() Microsoft.FSharp.Collections.ComparisonIdentity: System.String ToString() Microsoft.FSharp.Collections.ComparisonIdentity: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: TResult Value +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void .ctor(TResult) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+IOutOfBand: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Consumer`2 Create[V](IOutOfBand, System.Nullable`1[System.Int32], Consumer`2) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Int32 PipeIdx +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Int32 get_PipeIdx() +Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T]: ISeq`1 Compose[TResult](ISeqFactory`2) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T]: a ForEach[a](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit],a]) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Void .ctor(a, b) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: a _1 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: b _2 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Void .ctor(a, b, c) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: a _1 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: b _2 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: c _3 +Microsoft.FSharp.Collections.ComposerModule+Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+IOutOfBand +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c] +Microsoft.FSharp.Collections.ComposerModule+Core: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule: Microsoft.FSharp.Collections.ComposerModule+Core +Microsoft.FSharp.Collections.ComposerModule: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule: System.Type GetType() Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Int32 Cons Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Int32 Empty @@ -419,6 +476,7 @@ Microsoft.FSharp.Collections.SeqModule: Boolean Exists[T](Microsoft.FSharp.Core. Microsoft.FSharp.Collections.SeqModule: Boolean ForAll2[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 ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Boolean IsEmpty[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: ISeq`1 ToComposer[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], System.Collections.Generic.IEnumerable`1[T], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs index cf8156e3fc8..35ea8abf8a2 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs @@ -181,6 +181,63 @@ Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.ICom Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] Structural[T]() Microsoft.FSharp.Collections.ComparisonIdentity: System.String ToString() Microsoft.FSharp.Collections.ComparisonIdentity: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: TResult Value +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void .ctor(TResult) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+IOutOfBand: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Consumer`2 Create[V](IOutOfBand, System.Nullable`1[System.Int32], Consumer`2) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Int32 PipeIdx +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Int32 get_PipeIdx() +Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T]: ISeq`1 Compose[TResult](ISeqFactory`2) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T]: a ForEach[a](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit],a]) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Void .ctor(a, b) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: a _1 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: b _2 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Void .ctor(a, b, c) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: a _1 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: b _2 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: c _3 +Microsoft.FSharp.Collections.ComposerModule+Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+IOutOfBand +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c] +Microsoft.FSharp.Collections.ComposerModule+Core: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule: Microsoft.FSharp.Collections.ComposerModule+Core +Microsoft.FSharp.Collections.ComposerModule: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule: System.Type GetType() Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Int32 Cons Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Int32 Empty @@ -406,6 +463,7 @@ Microsoft.FSharp.Collections.SeqModule: Boolean Exists[T](Microsoft.FSharp.Core. Microsoft.FSharp.Collections.SeqModule: Boolean ForAll2[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 ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Boolean IsEmpty[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: ISeq`1 ToComposer[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], System.Collections.Generic.IEnumerable`1[T], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs index 9c63e5a4931..c16bd7d1b49 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs @@ -178,6 +178,63 @@ Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.ICom Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] Structural[T]() Microsoft.FSharp.Collections.ComparisonIdentity: System.String ToString() Microsoft.FSharp.Collections.ComparisonIdentity: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: TResult Value +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void .ctor(TResult) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+IOutOfBand: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Consumer`2 Create[V](IOutOfBand, System.Nullable`1[System.Int32], Consumer`2) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Int32 PipeIdx +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Int32 get_PipeIdx() +Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T]: ISeq`1 Compose[TResult](ISeqFactory`2) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T]: a ForEach[a](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit],a]) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Void .ctor(a, b) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: a _1 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: b _2 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Void .ctor(a, b, c) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: a _1 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: b _2 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: c _3 +Microsoft.FSharp.Collections.ComposerModule+Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+IOutOfBand +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c] +Microsoft.FSharp.Collections.ComposerModule+Core: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule: Microsoft.FSharp.Collections.ComposerModule+Core +Microsoft.FSharp.Collections.ComposerModule: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule: System.Type GetType() Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Int32 Cons Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Int32 Empty @@ -403,6 +460,7 @@ Microsoft.FSharp.Collections.SeqModule: Boolean Exists[T](Microsoft.FSharp.Core. Microsoft.FSharp.Collections.SeqModule: Boolean ForAll2[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 ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Boolean IsEmpty[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: ISeq`1 ToComposer[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], System.Collections.Generic.IEnumerable`1[T], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs index 7c003fea400..1de212c21f0 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs @@ -194,6 +194,63 @@ Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.ICom Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] Structural[T]() Microsoft.FSharp.Collections.ComparisonIdentity: System.String ToString() Microsoft.FSharp.Collections.ComparisonIdentity: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: TResult Value +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void .ctor(TResult) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+IOutOfBand: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Consumer`2 Create[V](IOutOfBand, System.Nullable`1[System.Int32], Consumer`2) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Int32 PipeIdx +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Int32 get_PipeIdx() +Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T]: ISeq`1 Compose[TResult](ISeqFactory`2) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T]: a ForEach[a](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit],a]) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Void .ctor(a, b) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: a _1 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: b _2 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Void .ctor(a, b, c) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: a _1 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: b _2 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: c _3 +Microsoft.FSharp.Collections.ComposerModule+Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+IOutOfBand +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c] +Microsoft.FSharp.Collections.ComposerModule+Core: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule: Microsoft.FSharp.Collections.ComposerModule+Core +Microsoft.FSharp.Collections.ComposerModule: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule: System.Type GetType() Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Int32 Cons Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Int32 Empty @@ -419,6 +476,7 @@ Microsoft.FSharp.Collections.SeqModule: Boolean Exists[T](Microsoft.FSharp.Core. Microsoft.FSharp.Collections.SeqModule: Boolean ForAll2[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 ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Boolean IsEmpty[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: ISeq`1 ToComposer[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], System.Collections.Generic.IEnumerable`1[T], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs index 4f1d01c64b6..f4f4479b4ce 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs @@ -181,6 +181,63 @@ Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.ICom Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] Structural[T]() Microsoft.FSharp.Collections.ComparisonIdentity: System.String ToString() Microsoft.FSharp.Collections.ComparisonIdentity: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: TResult Value +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void .ctor(TResult) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+IOutOfBand: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Consumer`2 Create[V](IOutOfBand, System.Nullable`1[System.Int32], Consumer`2) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Int32 PipeIdx +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Int32 get_PipeIdx() +Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T]: ISeq`1 Compose[TResult](ISeqFactory`2) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T]: a ForEach[a](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit],a]) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Void .ctor(a, b) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: a _1 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: b _2 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Void .ctor(a, b, c) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: a _1 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: b _2 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: c _3 +Microsoft.FSharp.Collections.ComposerModule+Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+IOutOfBand +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c] +Microsoft.FSharp.Collections.ComposerModule+Core: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule: Microsoft.FSharp.Collections.ComposerModule+Core +Microsoft.FSharp.Collections.ComposerModule: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule: System.Type GetType() Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Int32 Cons Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Int32 Empty @@ -406,6 +463,7 @@ Microsoft.FSharp.Collections.SeqModule: Boolean Exists[T](Microsoft.FSharp.Core. Microsoft.FSharp.Collections.SeqModule: Boolean ForAll2[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 ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Boolean IsEmpty[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: ISeq`1 ToComposer[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], System.Collections.Generic.IEnumerable`1[T], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 FindIndexBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) diff --git a/tests/fsharpqa/Source/Misc/LongSourceFile01.fs b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs index 970a5f77ff6..ce49bd6d74d 100644 --- a/tests/fsharpqa/Source/Misc/LongSourceFile01.fs +++ b/tests/fsharpqa/Source/Misc/LongSourceFile01.fs @@ -163,6 +163,63 @@ Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.ICom Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] Structural[T]() Microsoft.FSharp.Collections.ComparisonIdentity: System.String ToString() Microsoft.FSharp.Collections.ComparisonIdentity: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void .ctor() +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult]: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Boolean ProcessNext(T) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: TResult Value +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void .ctor(TResult) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult]: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining: Void OnComplete(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining: Void OnDispose() +Microsoft.FSharp.Collections.ComposerModule+Core+IOutOfBand: Void StopFurtherProcessing(Int32) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Consumer`2 Create[V](IOutOfBand, System.Nullable`1[System.Int32], Consumer`2) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Int32 PipeIdx +Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult]: Int32 get_PipeIdx() +Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T]: ISeq`1 Compose[TResult](ISeqFactory`2) +Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T]: a ForEach[a](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit],a]) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: Void .ctor(a, b) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: a _1 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b]: b _2 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: Void .ctor(a, b, c) +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: a _1 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: b _2 +Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c]: c _3 +Microsoft.FSharp.Collections.ComposerModule+Core: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule+Core: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Consumer`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Folder`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ICompletionChaining +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+IOutOfBand +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ISeqFactory`2[T,TResult] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+ISeq`1[T] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Values`2[a,b] +Microsoft.FSharp.Collections.ComposerModule+Core: Microsoft.FSharp.Collections.ComposerModule+Core+Values`3[a,b,c] +Microsoft.FSharp.Collections.ComposerModule+Core: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule+Core: System.Type GetType() +Microsoft.FSharp.Collections.ComposerModule: Boolean Equals(System.Object) +Microsoft.FSharp.Collections.ComposerModule: Int32 GetHashCode() +Microsoft.FSharp.Collections.ComposerModule: Microsoft.FSharp.Collections.ComposerModule+Core +Microsoft.FSharp.Collections.ComposerModule: System.String ToString() +Microsoft.FSharp.Collections.ComposerModule: System.Type GetType() Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Boolean Equals(System.Object) Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Int32 Cons Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Int32 Empty @@ -348,6 +405,7 @@ Microsoft.FSharp.Collections.SeqModule: Boolean Exists[T](Microsoft.FSharp.Core. Microsoft.FSharp.Collections.SeqModule: Boolean ForAll2[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 ForAll[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Boolean IsEmpty[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: ISeq`1 ToComposer[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 CompareWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], System.Collections.Generic.IEnumerable`1[T], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Int32 GetHashCode() From f9da5a1a22e292c74e15fe0740523d8e0f99a811 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 13 Nov 2016 19:23:54 +1100 Subject: [PATCH 126/286] Starting the exposure of the inlinable Composer - Still hidden via internal module - simplified PipeIdx, no need for optional now - Made ISeqFactory an abstract class instead of interface so as not to require a stub implementation of PipeIdx in every object expression (or alternatively if the abstract class was used with the interface, then explicit declaration of the interface as well) - filter and map changed to inline versions --- src/fsharp/FSharp.Core/seq.fs | 2 +- src/fsharp/FSharp.Core/seqcomposer.fs | 330 ++++++++++--------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 204 +++++---------- 3 files changed, 197 insertions(+), 339 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index edefb6a630f..76683849427 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -50,11 +50,11 @@ namespace Microsoft.FSharp.Collections Composer.Seq.foreach f (toComposer source) let private seqFactory createSeqComponent (source:seq<'T>) = - checkNonNull "source" source match source with | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose createSeqComponent) | :? array<'T> as a -> Upcast.enumerable (Composer.Seq.Array.create a createSeqComponent) | :? list<'T> as a -> Upcast.enumerable (Composer.Seq.List.create a createSeqComponent) + | null -> nullArg "source" | _ -> Upcast.enumerable (Composer.Seq.Enumerable.create source createSeqComponent) [] diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index f5324016f7f..1b5340e3576 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -21,10 +21,6 @@ namespace Microsoft.FSharp.Collections module Core = type PipeIdx = int - type ``PipeIdx?`` = Nullable - let emptyPipeIdx = Nullable () - let inline getPipeIdx (maybePipeIdx:``PipeIdx?``) = if maybePipeIdx.HasValue then maybePipeIdx.Value else 1 - let inline makePipeIdx (pipeIdx:PipeIdx) = Nullable pipeIdx type ICompletionChaining = abstract OnComplete : PipeIdx -> unit @@ -84,13 +80,16 @@ namespace Microsoft.FSharp.Collections Value = init } - type ISeqFactory<'T,'U> = + [] + type SeqFactory<'T,'U> () = abstract PipeIdx : PipeIdx - abstract Create<'V> : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> + abstract Create<'V> : IOutOfBand -> PipeIdx -> Consumer<'U,'V> -> Consumer<'T,'V> + + default __.PipeIdx = 1 type ISeq<'T> = inherit IEnumerable<'T> - abstract member Compose<'U> : (ISeqFactory<'T,'U>) -> ISeq<'U> + abstract member Compose<'U> : (SeqFactory<'T,'U>) -> ISeq<'U> abstract member ForEach<'consumer when 'consumer :> Consumer<'T,'T>> : f:((unit->unit)->'consumer) -> 'consumer open Core @@ -105,152 +104,118 @@ 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:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) - let inline factory (t:#ISeqFactory<'T,'U>) : ISeqFactory<'T,'U> = (# "" t : ISeqFactory<'T,'U> #) let inline enumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) let inline enumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline enumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline iCompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) module internal Seq = - type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = - new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) - - interface ISeqFactory<'T,'U> with - member __.PipeIdx = getPipeIdx pipeIdx - member __.Create<'V> (_:IOutOfBand) (_:``PipeIdx?``) (_:Consumer<'U,'V>) : Consumer<'T,'V> = failwith "library implementation error: Create on base factory should not be called" + type ComposedFactory<'T,'U,'V> private (first:SeqFactory<'T,'U>, second:SeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = + inherit SeqFactory<'T,'V>() - and ComposedFactory<'T,'U,'V> private (first:ISeqFactory<'T,'U>, second:ISeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = - inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) + override __.PipeIdx = + secondPipeIdx - interface ISeqFactory<'T,'V> with - member this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = - first.Create outOfBand pipeIdx (second.Create outOfBand (makePipeIdx secondPipeIdx) next) + override this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'V,'W>) : Consumer<'T,'W> = + first.Create outOfBand pipeIdx (second.Create outOfBand secondPipeIdx next) - static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = - ComposedFactory(first, second, first.PipeIdx+1) |> Upcast.factory + static member Combine (first:SeqFactory<'T,'U>) (second:SeqFactory<'U,'V>) : SeqFactory<'T,'V> = + upcast ComposedFactory(first, second, first.PipeIdx+1) and ChooseFactory<'T,'U> (filter:'T->option<'U>) = - inherit SeqComponentFactory<'T,'U> () - interface ISeqFactory<'T,'U> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) + inherit SeqFactory<'T,'U> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) and DistinctFactory<'T when 'T: equality> () = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) - - and FilterFactory<'T> (filter:'T->bool) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = - match next with - | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter - | _ -> upcast Filter (filter, next) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) and IdentityFactory<'T> () = - inherit SeqComponentFactory<'T,'T> () - static let singleton = IdentityFactory<'T>() - interface ISeqFactory<'T,'T> with - member __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next + inherit SeqFactory<'T,'T> () + static let singleton : SeqFactory<'T,'T> = upcast (IdentityFactory<'T>()) + override __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next static member Instance = singleton - and MapFactory<'T,'U> (map:'T->'U) = - inherit SeqComponentFactory<'T,'U> () - interface ISeqFactory<'T,'U> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = - match next with - | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map - | _ -> upcast Map<_,_,_> (map, next) - and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = - inherit SeqComponentFactory<'First,'U> () - interface ISeqFactory<'First,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, outOfBand, next, getPipeIdx pipeIdx) + inherit SeqFactory<'First,'U> () + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, outOfBand, next, pipeIdx) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = - inherit SeqComponentFactory<'Second,'U> () - interface ISeqFactory<'Second,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, outOfBand, next, getPipeIdx pipeIdx) + inherit SeqFactory<'Second,'U> () + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, outOfBand, next, pipeIdx) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = - inherit SeqComponentFactory<'First,'U> () - interface ISeqFactory<'First,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, outOfBand, next, getPipeIdx pipeIdx) + inherit SeqFactory<'First,'U> () + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, outOfBand, next, pipeIdx) and MapiFactory<'T,'U> (mapi:int->'T->'U) = - inherit SeqComponentFactory<'T,'U> () - interface ISeqFactory<'T,'U> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) + inherit SeqFactory<'T,'U> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = - inherit SeqComponentFactory<'First,'U> () - interface ISeqFactory<'First,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, outOfBand, next, getPipeIdx pipeIdx) + inherit SeqFactory<'First,'U> () + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, outOfBand, next, pipeIdx) and PairwiseFactory<'T> () = - inherit SeqComponentFactory<'T,'T*'T> () - interface ISeqFactory<'T,'T*'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) + inherit SeqFactory<'T,'T*'T> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = - inherit SeqComponentFactory<'T,'State> () - interface ISeqFactory<'T,'State> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) + inherit SeqFactory<'T,'State> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) and SkipFactory<'T> (count:int, onNotEnoughElements) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, onNotEnoughElements, next) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, onNotEnoughElements, next) and SkipWhileFactory<'T> (predicate:'T->bool) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, outOfBand, next, getPipeIdx pipeIdx) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, outOfBand, next, pipeIdx) and TakeFactory<'T> (count:int) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, getPipeIdx pipeIdx) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, pipeIdx) and TailFactory<'T> () = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, getPipeIdx pipeIdx) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, pipeIdx) and WindowedFactory<'T> (windowSize:int) = - inherit SeqComponentFactory<'T, 'T[]> () - interface ISeqFactory<'T, 'T[]> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T[],'V>) : Consumer<'T,'V> = upcast Windowed (windowSize, next) - - and [] SeqComponent<'T,'U> (next:ICompletionChaining) = - inherit Consumer<'T,'U>() + inherit SeqFactory<'T, 'T[]> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T[],'V>) : Consumer<'T,'V> = upcast Windowed (windowSize, next) + and ISkipping = // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip // and it can only do it at the start of a sequence abstract Skipping : unit -> bool - abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> - abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> + and [] SeqComponentSimple<'T,'U> (next:ICompletionChaining) = + inherit Consumer<'T,'U>() + + interface ICompletionChaining with + member this.OnComplete terminatingIdx = + next.OnComplete terminatingIdx + member this.OnDispose () = + next.OnDispose () + + and [] SeqComponent<'T,'U> (next:ICompletionChaining) = + inherit Consumer<'T,'U>() interface ICompletionChaining with member this.OnComplete terminatingIdx = @@ -260,13 +225,8 @@ namespace Microsoft.FSharp.Collections try this.OnDispose () finally next.OnDispose () - default __.Skipping () = false - - default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) - default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) - and Choose<'T,'U,'V> (choose:'T->option<'U>, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) override __.ProcessNext (input:'T) : bool = match choose input with @@ -274,7 +234,7 @@ namespace Microsoft.FSharp.Collections | None -> false and Distinct<'T,'V when 'T: equality> (next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) @@ -285,7 +245,7 @@ namespace Microsoft.FSharp.Collections false and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) @@ -296,7 +256,7 @@ namespace Microsoft.FSharp.Collections false and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) @@ -306,36 +266,8 @@ namespace Microsoft.FSharp.Collections else false - and Filter<'T,'V> (filter:'T->bool, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) - - override __.ProcessNext (input:'T) : bool = - if filter input then - TailCall.avoid (next.ProcessNext input) - else - false - - and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - override __.ProcessNext (input:'T) : bool = - if filter input then - TailCall.avoid (next.ProcessNext (map input)) - else - false - - and Map<'T,'U,'V> (map:'T->'U, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) - - override __.ProcessNext (input:'T) : bool = - TailCall.avoid (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(next) + inherit SeqComponent<'First,'V>(Upcast.iCompletionChaining next) let input2 = enumerable2.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -351,7 +283,7 @@ namespace Microsoft.FSharp.Collections input2.Dispose () and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'Second,'V>(next) + inherit SeqComponent<'Second,'V>(Upcast.iCompletionChaining next) let input1 = enumerable1.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -367,7 +299,7 @@ namespace Microsoft.FSharp.Collections input1.Dispose () and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(next) + inherit SeqComponent<'First,'V>(Upcast.iCompletionChaining next) let input2 = enumerable2.GetEnumerator () let input3 = enumerable3.GetEnumerator () @@ -384,18 +316,8 @@ namespace Microsoft.FSharp.Collections try input2.Dispose () finally input3.Dispose () - and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - override __.ProcessNext (input:'T) : bool = - let u = map input - if filter u then - TailCall.avoid (next.ProcessNext u) - else - false - and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let mutable idx = 0 let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi @@ -405,7 +327,7 @@ namespace Microsoft.FSharp.Collections TailCall.avoid (next.ProcessNext (mapi'.Invoke (idx-1, input))) and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(next) + inherit SeqComponent<'First,'V>(Upcast.iCompletionChaining next) let mutable idx = 0 let input2 = enumerable2.GetEnumerator () @@ -423,7 +345,7 @@ namespace Microsoft.FSharp.Collections input2.Dispose () and Pairwise<'T,'V> (next:Consumer<'T*'T,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let mutable isFirst = true let mutable lastValue = Unchecked.defaultof<'T> @@ -439,7 +361,7 @@ namespace Microsoft.FSharp.Collections TailCall.avoid (next.ProcessNext currentPair) and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:Consumer<'State,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let mutable foldResult = initialState @@ -449,16 +371,17 @@ namespace Microsoft.FSharp.Collections TailCall.avoid (next.ProcessNext foldResult) and Skip<'T,'V> (skipCount:int, notEnoughElements:string->array->unit, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let mutable count = 0 - override __.Skipping () = - if count < skipCount then - count <- count + 1 - true - else - false + interface ISkipping with + member __.Skipping () = + if count < skipCount then + count <- count + 1 + true + else + false override __.ProcessNext (input:'T) : bool = if count < skipCount then @@ -474,7 +397,7 @@ namespace Microsoft.FSharp.Collections [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] and SkipWhile<'T,'V> (predicate:'T->bool, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let mutable skip = true @@ -498,7 +421,7 @@ namespace Microsoft.FSharp.Collections [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] and TakeWhile<'T,'V> (predicate:'T->bool, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) override __.ProcessNext (input:'T) : bool = if predicate input then @@ -508,7 +431,7 @@ namespace Microsoft.FSharp.Collections false and Tail<'T, 'V> (next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let mutable first = true @@ -524,7 +447,7 @@ namespace Microsoft.FSharp.Collections invalidArg "source" (SR.GetString(SR.notEnoughElements)) and Truncate<'T,'V> (truncateCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let mutable count = 0 @@ -541,7 +464,7 @@ namespace Microsoft.FSharp.Collections false and Windowed<'T,'V> (windowSize: int, next:Consumer<'T[],'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let circularBuffer = Array.zeroCreateUnchecked windowSize let mutable idx = 0 @@ -628,8 +551,8 @@ namespace Microsoft.FSharp.Collections iterate state let makeIsSkipping (consumer:Consumer<'T,'U>) = - match consumer with - | :? SeqComponent<'T,'U> as c -> c.Skipping + match box consumer with + | :? ISkipping as skip -> skip.Skipping | _ -> fun () -> false let init f (terminatingIdx:int) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = @@ -645,10 +568,10 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 - let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:ISeqFactory<'T,'U>) executeOn = + let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:SeqFactory<'T,'U>) executeOn = let pipeline = OutOfBand() let result = f (fun () -> (pipeline:>IOutOfBand).StopFurtherProcessing (current.PipeIdx+1)) - let consumer = current.Create pipeline emptyPipeIdx result + let consumer = current.Create pipeline 0 result try executeOn pipeline consumer (Upcast.iCompletionChaining consumer).OnComplete pipeline.HaltedIdx @@ -739,16 +662,16 @@ namespace Microsoft.FSharp.Collections finally (Upcast.iCompletionChaining seqComponent).OnDispose () - and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:ISeqFactory<'T,'U>) = + and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqFactory<'T,'U>) = inherit EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result 0 (SetResult<'U> result), result)) interface ISeq<'U> with - member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = @@ -803,7 +726,7 @@ namespace Microsoft.FSharp.Collections Upcast.enumerable (AppendEnumerable (source :: sources)) interface ISeq<'T> with - member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = @@ -817,7 +740,7 @@ namespace Microsoft.FSharp.Collections Upcast.enumerator (new ConcatEnumerator<_,_> (sources)) interface ISeq<'T> with - member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = @@ -840,7 +763,7 @@ namespace Microsoft.FSharp.Collections Upcast.enumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) interface ISeq<'T> with - member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable.Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = @@ -880,25 +803,25 @@ namespace Microsoft.FSharp.Collections initMoveNext () moveNext () - type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:ISeqFactory<'T,'U>) = + type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Create result 0 (SetResult<'U> result), result)) interface ISeq<'U> with - member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.array (delayedArray ())) - let createDelayed (delayedArray:unit->array<'T>) (current:ISeqFactory<'T,'U>) = + let createDelayed (delayedArray:unit->array<'T>) (current:SeqFactory<'T,'U>) = Upcast.seq (Enumerable(delayedArray, current)) - let create (array:array<'T>) (current:ISeqFactory<'T,'U>) = + let create (array:array<'T>) (current:SeqFactory<'T,'U>) = createDelayed (fun () -> array) current let createDelayedId (delayedArray:unit -> array<'T>) = @@ -931,16 +854,16 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext list - type Enumerable<'T,'U>(alist:list<'T>, current:ISeqFactory<'T,'U>) = + type Enumerable<'T,'U>(alist:list<'T>, current:SeqFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Create result 0 (SetResult<'U> result), result)) interface ISeq<'U> with - member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = @@ -970,16 +893,16 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:ISeqFactory<'T,'U>) = + type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:SeqFactory<'T,'U>) = 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, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result 0 (SetResult<'U> result), result)) interface ISeq<'U> with - member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = @@ -1044,16 +967,16 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:ISeqFactory<'T,'U>) = + type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqFactory<'T,'U>) = 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, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(count, f, current.Create result 0 (SetResult<'U> result), result)) interface ISeq<'U> with - member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) member this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = @@ -1121,7 +1044,7 @@ namespace Microsoft.FSharp.Collections upto (if count.HasValue then Some (count.Value-1) else None) f interface ISeq<'T> with - member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable<'T,'V>(count, f, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = @@ -1129,17 +1052,17 @@ namespace Microsoft.FSharp.Collections [] let toComposer (source:seq<'T>) : ISeq<'T> = - checkNonNull "source" source match source with | :? ISeq<'T> as s -> s | :? array<'T> as a -> Upcast.seq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) | :? list<'T> as a -> Upcast.seq (List.Enumerable(a, IdentityFactory.Instance)) + | null -> nullArg "source" | _ -> Upcast.seq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) let inline foreach f (source:ISeq<_>) = source.ForEach f - let inline compose factory (source:ISeq<'T>) = + let inline compose (factory:#SeqFactory<_,_>) (source:ISeq<'T>) = source.Compose factory [] @@ -1234,16 +1157,23 @@ namespace Microsoft.FSharp.Collections halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun forall -> forall.Value - + [] - let filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source - |> compose (FilterFactory f) + let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { new SeqComponentSimple<'T,'V>(Upcast.iCompletionChaining next) with + member __.ProcessNext input = + if f input then TailCall.avoid (next.ProcessNext input) + else false } } [] - let map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = - source - |> compose (MapFactory f) + let inline map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = + source |> compose { new SeqFactory<'T,'U>() with + member __.Create _ _ next = + upcast { new SeqComponentSimple<'T,'V>(Upcast.iCompletionChaining next) with + member __.ProcessNext input = + TailCall.avoid (next.ProcessNext (f input)) } } [] let mapi f source = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index e0c19da96bc..b09338141b0 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -14,7 +14,6 @@ namespace Microsoft.FSharp.Collections /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the /// source of the chain. type PipeIdx = int - type ``PipeIdx?`` = Nullable /// ICompletionChaining is used to correctly handle cleaning up of the pipeline. A /// base implementation is provided in Consumer, and should not be overwritten. Consumer @@ -71,102 +70,75 @@ namespace Microsoft.FSharp.Collections new : init:'U -> Folder<'T,'U> val mutable Value: 'U - type ISeqFactory<'T,'U> = - abstract member Create : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> - abstract member PipeIdx : PipeIdx + [] + type SeqFactory<'T,'U> = + new : unit -> SeqFactory<'T,'U> + abstract PipeIdx : PipeIdx + abstract member Create : IOutOfBand -> PipeIdx -> Consumer<'U,'V> -> Consumer<'T,'V> type ISeq<'T> = inherit System.Collections.Generic.IEnumerable<'T> - abstract member Compose : ISeqFactory<'T,'U> -> ISeq<'U> + abstract member Compose : SeqFactory<'T,'U> -> ISeq<'U> abstract member ForEach : f:((unit -> unit) -> 'a) -> 'a when 'a :> Consumer<'T,'T> open Core module internal Seq = - [] - type SeqComponentFactory<'T,'U> = - class - interface ISeqFactory<'T,'U> - new : unit -> SeqComponentFactory<'T,'U> - new : pipeIdx: ``PipeIdx?`` -> - SeqComponentFactory<'T,'U> - end - and ComposedFactory<'T,'U,'V> = + type ComposedFactory<'T,'U,'V> = class - inherit SeqComponentFactory<'T,'V> - interface ISeqFactory<'T,'V> - private new : first: ISeqFactory<'T,'U> * - second: ISeqFactory<'U,'V> * + inherit SeqFactory<'T,'V> + private new : first: SeqFactory<'T,'U> * + second: SeqFactory<'U,'V> * secondPipeIdx: PipeIdx -> ComposedFactory<'T,'U,'V> static member - Combine : first: ISeqFactory<'T,'U> -> - second: ISeqFactory<'U,'V> -> - ISeqFactory<'T,'V> + Combine : first: SeqFactory<'T,'U> -> + second: SeqFactory<'U,'V> -> + SeqFactory<'T,'V> end and ChooseFactory<'T,'U> = class - inherit SeqComponentFactory<'T,'U> - interface ISeqFactory<'T,'U> + inherit SeqFactory<'T,'U> new : filter:('T -> 'U option) -> ChooseFactory<'T,'U> end and DistinctFactory<'T when 'T : equality> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : unit -> DistinctFactory<'T> end and DistinctByFactory<'T,'Key when 'Key : equality> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : keyFunction:('T -> 'Key) -> DistinctByFactory<'T,'Key> end and ExceptFactory<'T when 'T : equality> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : itemsToExclude:seq<'T> -> ExceptFactory<'T> end - and FilterFactory<'T> = - class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> - new : filter:('T -> bool) -> FilterFactory<'T> - end and IdentityFactory<'T> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : unit -> IdentityFactory<'T> - static member Instance : IdentityFactory<'T> - end - and MapFactory<'T,'U> = - class - inherit SeqComponentFactory<'T,'U> - interface ISeqFactory<'T,'U> - new : map:('T -> 'U) -> MapFactory<'T,'U> + static member Instance : SeqFactory<'T,'T> end and Map2FirstFactory<'First,'Second,'U> = class - inherit SeqComponentFactory<'First,'U> - interface ISeqFactory<'First,'U> + inherit SeqFactory<'First,'U> new : map:('First -> 'Second -> 'U) * input2:IEnumerable<'Second> -> Map2FirstFactory<'First,'Second,'U> end and Map2SecondFactory<'First,'Second,'U> = class - inherit SeqComponentFactory<'Second,'U> - interface ISeqFactory<'Second,'U> + inherit SeqFactory<'Second,'U> new : map:('First -> 'Second -> 'U) * input1:IEnumerable<'First> -> Map2SecondFactory<'First,'Second,'U> end and Map3Factory<'First,'Second,'Third,'U> = class - inherit SeqComponentFactory<'First,'U> - interface ISeqFactory<'First,'U> + inherit SeqFactory<'First,'U> new : map:('First -> 'Second -> 'Third -> 'U) * input2:IEnumerable<'Second> * input3:IEnumerable<'Third> -> @@ -174,88 +146,79 @@ namespace Microsoft.FSharp.Collections end and MapiFactory<'T,'U> = class - inherit SeqComponentFactory<'T,'U> - interface ISeqFactory<'T,'U> + inherit SeqFactory<'T,'U> new : mapi:(int -> 'T -> 'U) -> MapiFactory<'T,'U> end and Mapi2Factory<'First,'Second,'U> = class - inherit SeqComponentFactory<'First,'U> - interface ISeqFactory<'First,'U> + inherit SeqFactory<'First,'U> new : map:(int -> 'First -> 'Second -> 'U) * input2:IEnumerable<'Second> -> Mapi2Factory<'First,'Second,'U> end and PairwiseFactory<'T> = class - inherit SeqComponentFactory<'T,('T * 'T)> - interface ISeqFactory<'T,('T * 'T)> + inherit SeqFactory<'T,('T * 'T)> new : unit -> PairwiseFactory<'T> end and ScanFactory<'T,'State> = class - inherit SeqComponentFactory<'T,'State> - interface ISeqFactory<'T,'State> + inherit SeqFactory<'T,'State> new : folder:('State -> 'T -> 'State) * initialState:'State -> ScanFactory<'T,'State> end and SkipFactory<'T> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : count:int * notEnoughElements:(string->array->unit) -> SkipFactory<'T> end and SkipWhileFactory<'T> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : predicate:('T -> bool) -> SkipWhileFactory<'T> end and TakeWhileFactory<'T> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : predicate:('T -> bool) -> TakeWhileFactory<'T> end and TakeFactory<'T> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : count:int -> TakeFactory<'T> end and TailFactory<'T> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : unit -> TailFactory<'T> end and TruncateFactory<'T> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : count:int -> TruncateFactory<'T> end and WindowedFactory<'T> = class - inherit SeqComponentFactory<'T,'T []> - interface ISeqFactory<'T,'T []> + inherit SeqFactory<'T,'T []> new : windowSize:int -> WindowedFactory<'T> end + and ISkipping = + interface + abstract member Skipping : unit -> bool + end + and [] SeqComponentSimple<'T,'U> = + class + inherit Consumer<'T,'U> + interface ICompletionChaining + new : next:ICompletionChaining -> + SeqComponentSimple<'T,'U> + end and [] SeqComponent<'T,'U> = class - inherit Consumer<'T,'U> - interface ICompletionChaining - new : next: ICompletionChaining -> - SeqComponent<'T,'U> - abstract member - CreateFilter : filter:('T -> bool) -> SeqComponent<'T,'U> - abstract member - CreateMap : map:('S -> 'T) -> SeqComponent<'S,'U> - abstract member Skipping : unit -> bool - override - CreateFilter : filter:('T -> bool) -> SeqComponent<'T,'U> - override CreateMap : map:('S -> 'T) -> SeqComponent<'S,'U> - override Skipping : unit -> bool + inherit Consumer<'T,'U> + interface ICompletionChaining + new : next:ICompletionChaining -> + SeqComponent<'T,'U> end and Choose<'T,'U,'V> = class @@ -284,31 +247,6 @@ namespace Microsoft.FSharp.Collections Except<'T,'V> override ProcessNext : input:'T -> bool end - and Filter<'T,'V> = - class - inherit SeqComponent<'T,'V> - new : filter:('T -> bool) * next: Consumer<'T,'V> -> - Filter<'T,'V> - override CreateMap : map:('S -> 'T) -> SeqComponent<'S,'V> - override ProcessNext : input:'T -> bool - end - and FilterThenMap<'T,'U,'V> = - class - inherit SeqComponent<'T,'V> - new : filter:('T -> bool) * map:('T -> 'U) * - next: Consumer<'U,'V> -> - FilterThenMap<'T,'U,'V> - override ProcessNext : input:'T -> bool - end - and Map<'T,'U,'V> = - class - inherit SeqComponent<'T,'V> - new : map:('T -> 'U) * next: Consumer<'U,'V> -> - Map<'T,'U,'V> - override - CreateFilter : filter:('T -> bool) -> SeqComponent<'T,'V> - override ProcessNext : input:'T -> bool - end and Map2First<'First,'Second,'U,'V> = class inherit SeqComponent<'First,'V> @@ -343,14 +281,6 @@ namespace Microsoft.FSharp.Collections override OnDispose : unit -> unit override ProcessNext : input:'First -> bool end - and MapThenFilter<'T,'U,'V> = - class - inherit SeqComponent<'T,'V> - new : map:('T -> 'U) * filter:('U -> bool) * - next: Consumer<'U,'V> -> - MapThenFilter<'T,'U,'V> - override ProcessNext : input:'T -> bool - end and Mapi<'T,'U,'V> = class inherit SeqComponent<'T,'V> @@ -387,11 +317,11 @@ namespace Microsoft.FSharp.Collections and Skip<'T,'V> = class inherit SeqComponent<'T,'V> + interface ISkipping new : skipCount:int * exceptionOnNotEnoughElements:(string->array->unit) * next: Consumer<'T,'V> -> Skip<'T,'V> override OnComplete : PipeIdx -> unit override ProcessNext : input:'T -> bool - override Skipping : unit -> bool end and SkipWhile<'T,'V> = class @@ -492,7 +422,7 @@ namespace Microsoft.FSharp.Collections consumer: Consumer<'T,'U> -> unit val execute : f:((unit -> unit) -> 'a) -> - current: ISeqFactory<'T,'U> -> + current: SeqFactory<'T,'U> -> executeOn:( OutOfBand -> Consumer<'T,'U> -> unit) -> 'a when 'a :> Consumer<'U,'U> end @@ -546,7 +476,7 @@ namespace Microsoft.FSharp.Collections interface ISeq<'U> interface IEnumerable<'U> new : enumerable:IEnumerable<'T> * - current: ISeqFactory<'T,'U> -> + current: SeqFactory<'T,'U> -> Enumerable<'T,'U> end and ConcatEnumerator<'T,'Collection when 'Collection :> seq<'T>> = @@ -577,7 +507,7 @@ namespace Microsoft.FSharp.Collections end val create : enumerable:IEnumerable<'a> -> - current: ISeqFactory<'a,'b> -> ISeq<'b> + current: SeqFactory<'a,'b> -> ISeq<'b> end module EmptyEnumerable = begin type Enumerable<'T> = @@ -606,15 +536,15 @@ namespace Microsoft.FSharp.Collections interface ISeq<'U> interface IEnumerable<'U> new : delayedArray:(unit -> 'T array) * - current: ISeqFactory<'T,'U> -> + current: SeqFactory<'T,'U> -> Enumerable<'T,'U> end val createDelayed : delayedArray:(unit -> 'T array) -> - current: ISeqFactory<'T,'U> -> ISeq<'U> + current: SeqFactory<'T,'U> -> ISeq<'U> val create : array:'T array -> - current: ISeqFactory<'T,'U> -> ISeq<'U> + current: SeqFactory<'T,'U> -> ISeq<'U> val createDelayedId : delayedArray:(unit -> 'T array) -> ISeq<'T> val createId : array:'T array -> ISeq<'T> @@ -632,12 +562,12 @@ namespace Microsoft.FSharp.Collections inherit Enumerable.EnumerableBase<'U> interface ISeq<'U> interface IEnumerable<'U> - new : alist:'T list * current: ISeqFactory<'T,'U> -> + new : alist:'T list * current: SeqFactory<'T,'U> -> Enumerable<'T,'U> end val create : alist:'a list -> - current: ISeqFactory<'a,'b> -> ISeq<'b> + current: SeqFactory<'a,'b> -> ISeq<'b> end module Unfold = begin type Enumerator<'T,'U,'State> = @@ -655,7 +585,7 @@ namespace Microsoft.FSharp.Collections interface ISeq<'U> interface IEnumerable<'U> new : generator:('GeneratorState -> ('T * 'GeneratorState) option) * - state:'GeneratorState * current: ISeqFactory<'T,'U> -> + state:'GeneratorState * current: SeqFactory<'T,'U> -> Enumerable<'T,'U,'GeneratorState> end end @@ -675,7 +605,7 @@ namespace Microsoft.FSharp.Collections interface ISeq<'U> interface IEnumerable<'U> new : count:Nullable * f:(int -> 'T) * - current: ISeqFactory<'T,'U> -> + current: SeqFactory<'T,'U> -> Enumerable<'T,'U> end val upto : @@ -695,9 +625,6 @@ namespace Microsoft.FSharp.Collections val inline foreach : f:((unit -> unit) -> 'a) -> source: ISeq<'b> -> 'a when 'a :> Consumer<'b,'b> - val inline compose : - factory: ISeqFactory<'T,'a> -> - source: ISeq<'T> -> ISeq<'a> [] val empty<'T> : ISeq<'T> [] @@ -723,12 +650,13 @@ namespace Microsoft.FSharp.Collections element:'T -> source: ISeq<'T> -> bool when 'T : equality [] val forall : f:('T -> bool) -> source: ISeq<'T> -> bool - [] - val filter : - f:('T -> bool) -> source: ISeq<'T> -> ISeq<'T> - [] - val map : - f:('T -> 'U) -> source: ISeq<'T> -> ISeq<'U> + + [] + val inline filter : f:('T -> bool) -> source: ISeq<'T> -> ISeq<'T> + + [] + val inline map : f:('T -> 'U) -> source: ISeq<'T> -> ISeq<'U> + [] val mapi : f:(int -> 'a -> 'b) -> From 485b57cb1561af69fd9b86d3c35fe247b6c21816 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 16 Nov 2016 19:54:50 +1100 Subject: [PATCH 127/286] Fix incorrect pipeIdx --- src/fsharp/FSharp.Core/seqcomposer.fs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 1b5340e3576..5ce74e73f5e 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -87,6 +87,8 @@ namespace Microsoft.FSharp.Collections default __.PipeIdx = 1 + member this.Build outOfBand next = this.Create outOfBand 1 next + type ISeq<'T> = inherit IEnumerable<'T> abstract member Compose<'U> : (SeqFactory<'T,'U>) -> ISeq<'U> @@ -571,7 +573,7 @@ namespace Microsoft.FSharp.Collections let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:SeqFactory<'T,'U>) executeOn = let pipeline = OutOfBand() let result = f (fun () -> (pipeline:>IOutOfBand).StopFurtherProcessing (current.PipeIdx+1)) - let consumer = current.Create pipeline 0 result + let consumer = current.Build pipeline result try executeOn pipeline consumer (Upcast.iCompletionChaining consumer).OnComplete pipeline.HaltedIdx @@ -668,7 +670,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result 0 (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Build result (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -809,7 +811,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Create result 0 (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Build result (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -860,7 +862,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Create result 0 (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Build result (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -899,7 +901,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result 0 (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Build result (SetResult<'U> result), result)) interface ISeq<'U> with member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -973,7 +975,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(count, f, current.Create result 0 (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(count, f, current.Build result (SetResult<'U> result), result)) interface ISeq<'U> with member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = From 78c884be58dfb82a3b870933c9c637a272f70a1a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 17 Nov 2016 19:50:07 +1100 Subject: [PATCH 128/286] Hack to stop tail calls on ICompletionChaining passing a reference as an argument in a funciton stops the F# compiler from outputting a tail instruction for that function. None of these functions will be significantly deep as to warrant the need for a tail call. --- src/fsharp/FSharp.Core/seqcomposer.fs | 48 +++++++++++++++----------- src/fsharp/FSharp.Core/seqcomposer.fsi | 4 +-- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 5ce74e73f5e..205c2b90fe1 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -23,8 +23,8 @@ namespace Microsoft.FSharp.Collections type PipeIdx = int type ICompletionChaining = - abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit + abstract OnComplete : stopTailCall:byref*PipeIdx -> unit + abstract OnDispose : stopTailCall:byref -> unit type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit @@ -40,10 +40,10 @@ namespace Microsoft.FSharp.Collections default __.OnDispose () = () interface ICompletionChaining with - member this.OnComplete terminatingIdx = + member this.OnComplete (_, terminatingIdx) = this.OnComplete terminatingIdx - member this.OnDispose () = + member this.OnDispose _ = try this.OnDispose () finally () @@ -211,21 +211,21 @@ namespace Microsoft.FSharp.Collections inherit Consumer<'T,'U>() interface ICompletionChaining with - member this.OnComplete terminatingIdx = - next.OnComplete terminatingIdx - member this.OnDispose () = - next.OnDispose () + member this.OnComplete (stopTailCall, terminatingIdx) = + next.OnComplete (&stopTailCall, terminatingIdx) + member this.OnDispose stopTailCall = + next.OnDispose (&stopTailCall) and [] SeqComponent<'T,'U> (next:ICompletionChaining) = inherit Consumer<'T,'U>() interface ICompletionChaining with - member this.OnComplete terminatingIdx = + member this.OnComplete (stopTailCall, terminatingIdx) = this.OnComplete terminatingIdx - next.OnComplete terminatingIdx - member this.OnDispose () = + next.OnComplete (&stopTailCall, terminatingIdx) + member this.OnDispose stopTailCall = try this.OnDispose () - finally next.OnDispose () + finally next.OnDispose (&stopTailCall) and Choose<'T,'U,'V> (choose:'T->option<'U>, next:Consumer<'U,'V>) = inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) @@ -576,10 +576,12 @@ namespace Microsoft.FSharp.Collections let consumer = current.Build pipeline result try executeOn pipeline consumer - (Upcast.iCompletionChaining consumer).OnComplete pipeline.HaltedIdx + let mutable stopTailCall = () + (Upcast.iCompletionChaining consumer).OnComplete (&stopTailCall, pipeline.HaltedIdx) result finally - (Upcast.iCompletionChaining consumer).OnDispose () + let mutable stopTailCall = () + (Upcast.iCompletionChaining consumer).OnDispose (&stopTailCall) module Enumerable = type Empty<'T>() = @@ -601,7 +603,8 @@ namespace Microsoft.FSharp.Collections type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ICompletionChaining) = interface IDisposable with member __.Dispose() : unit = - seqComponent.OnDispose () + let mutable stopTailCall = () + seqComponent.OnDispose (&stopTailCall) interface IEnumerator with member this.Current : obj = box ((Upcast.enumerator this)).Current @@ -649,7 +652,8 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx + let mutable stopTailCall = () + (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -662,7 +666,8 @@ namespace Microsoft.FSharp.Collections try source.Dispose () finally - (Upcast.iCompletionChaining seqComponent).OnDispose () + let mutable stopTailCall = () + (Upcast.iCompletionChaining seqComponent).OnDispose (&stopTailCall) and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqFactory<'T,'U>) = inherit EnumerableBase<'U>() @@ -797,7 +802,8 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx + let mutable stopTailCall = () + (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -848,7 +854,8 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx + let mutable stopTailCall = () + (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -961,7 +968,8 @@ namespace Microsoft.FSharp.Collections raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else result.SeqState <- SeqProcessNextStates.Finished - (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx + let mutable stopTailCall = () + (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index b09338141b0..b90d832e01d 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -25,10 +25,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 OnComplete : PipeIdx -> unit + abstract OnComplete : stopTail:byref*PipeIdx -> unit /// OnDispose is used to cleanup the stream. It is always called at the last operation /// after the enumeration has completed. - abstract OnDispose : unit -> unit + abstract OnDispose : stopTail:byref -> unit type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit From 2bde270b1c597ca2c863fd3e5610263465becd4e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 21 Nov 2016 19:50:23 +1100 Subject: [PATCH 129/286] mapi to inline version - added a mapi_adapt version for non-inlined --- src/fsharp/FSharp.Core/seq.fs | 5 ++- src/fsharp/FSharp.Core/seqcomposer.fs | 55 +++++++++++++++----------- src/fsharp/FSharp.Core/seqcomposer.fsi | 44 ++++++++++----------- 3 files changed, 55 insertions(+), 49 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 76683849427..7d66b87b75e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -183,8 +183,9 @@ namespace Microsoft.FSharp.Collections |> Upcast.enumerable [] - let mapi f source = - Composer.Seq.mapi f (toComposer source) + let mapi f source = + let f' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f + Composer.Seq.mapi_adapt f' (toComposer source) |> Upcast.enumerable [] diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 205c2b90fe1..6ebe4e26cf8 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -20,11 +20,11 @@ namespace Microsoft.FSharp.Collections open IEnumerator module Core = - type PipeIdx = int + type PipeIdx = int type ICompletionChaining = - abstract OnComplete : stopTailCall:byref*PipeIdx -> unit - abstract OnDispose : stopTailCall:byref -> unit + abstract OnComplete : stopTailCall:byref * PipeIdx -> unit + abstract OnDispose : stopTailCall:byref -> unit type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit @@ -34,7 +34,7 @@ namespace Microsoft.FSharp.Collections abstract ProcessNext : input:'T -> bool abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit + abstract OnDispose : unit -> unit default __.OnComplete _ = () default __.OnDispose () = () @@ -158,10 +158,6 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'First,'U> () override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, outOfBand, next, pipeIdx) - and MapiFactory<'T,'U> (mapi:int->'T->'U) = - inherit SeqFactory<'T,'U> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) - and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqFactory<'First,'U> () override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, outOfBand, next, pipeIdx) @@ -216,6 +212,16 @@ namespace Microsoft.FSharp.Collections member this.OnDispose stopTailCall = next.OnDispose (&stopTailCall) + and [] SeqComponentSimpleValue<'T,'U,'Value> = + inherit SeqComponentSimple<'T,'U> + + val mutable Value : 'Value + + new (next, init) = { + inherit SeqComponentSimple<'T,'U>(next) + Value = init + } + and [] SeqComponent<'T,'U> (next:ICompletionChaining) = inherit Consumer<'T,'U>() @@ -318,16 +324,6 @@ namespace Microsoft.FSharp.Collections try input2.Dispose () finally input3.Dispose () - and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) - - let mutable idx = 0 - let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi - - override __.ProcessNext (input:'T) : bool = - idx <- idx + 1 - TailCall.avoid (next.ProcessNext (mapi'.Invoke (idx-1, input))) - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(Upcast.iCompletionChaining next) @@ -1186,9 +1182,21 @@ namespace Microsoft.FSharp.Collections TailCall.avoid (next.ProcessNext (f input)) } } [] - let mapi f source = - source - |> compose (MapiFactory f) + let inline mapi f source = + source |> compose { new SeqFactory<'T,'U>() with + member __.Create _ _ next = + upcast { new SeqComponentSimpleValue<'T,'V,int>(Upcast.iCompletionChaining next, -1) with + override this.ProcessNext (input:'T) : bool = + this.Value <- this.Value + 1 + TailCall.avoid (next.ProcessNext (f this.Value input)) } } + + let mapi_adapt (f:OptimizedClosures.FSharpFunc<_,_,_>) source = + source |> compose { new SeqFactory<'T,'U>() with + member __.Create _ _ next = + upcast { new SeqComponentSimpleValue<'T,'V,int>(Upcast.iCompletionChaining next, -1) with + override this.ProcessNext (input:'T) : bool = + this.Value <- this.Value + 1 + TailCall.avoid (next.ProcessNext (f.Invoke (this.Value, input))) } } [] let choose f source = @@ -1196,9 +1204,8 @@ namespace Microsoft.FSharp.Collections |> compose (ChooseFactory f) [] - let indexed source = - source - |> compose (MapiFactory (fun i x -> i,x)) + let inline indexed source = + mapi (fun i x -> i,x) source [] let tryPick f (source:ISeq<'T>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index b90d832e01d..c9bdf2fdb3e 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -25,10 +25,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 OnComplete : stopTail:byref*PipeIdx -> unit + abstract OnComplete : 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 OnDispose : stopTail:byref -> unit + abstract OnDispose : stopTailCall:byref -> unit type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit @@ -144,11 +144,6 @@ namespace Microsoft.FSharp.Collections input3:IEnumerable<'Third> -> Map3Factory<'First,'Second,'Third,'U> end - and MapiFactory<'T,'U> = - class - inherit SeqFactory<'T,'U> - new : mapi:(int -> 'T -> 'U) -> MapiFactory<'T,'U> - end and Mapi2Factory<'First,'Second,'U> = class inherit SeqFactory<'First,'U> @@ -206,13 +201,21 @@ namespace Microsoft.FSharp.Collections interface abstract member Skipping : unit -> bool end + and [] SeqComponentSimple<'T,'U> = class inherit Consumer<'T,'U> interface ICompletionChaining - new : next:ICompletionChaining -> - SeqComponentSimple<'T,'U> + new : next:ICompletionChaining -> SeqComponentSimple<'T,'U> end + + and [] SeqComponentSimpleValue<'T,'U,'Value> = + class + inherit SeqComponentSimple<'T,'U> + val mutable Value : 'Value + new : next:ICompletionChaining*value:'Value -> SeqComponentSimpleValue<'T,'U,'Value> + end + and [] SeqComponent<'T,'U> = class inherit Consumer<'T,'U> @@ -220,6 +223,7 @@ namespace Microsoft.FSharp.Collections new : next:ICompletionChaining -> SeqComponent<'T,'U> end + and Choose<'T,'U,'V> = class inherit SeqComponent<'T,'V> @@ -281,13 +285,6 @@ namespace Microsoft.FSharp.Collections override OnDispose : unit -> unit override ProcessNext : input:'First -> bool end - and Mapi<'T,'U,'V> = - class - inherit SeqComponent<'T,'V> - new : mapi:(int -> 'T -> 'U) * next: Consumer<'U,'V> -> - Mapi<'T,'U,'V> - override ProcessNext : input:'T -> bool - end and Mapi2<'First,'Second,'U,'V> = class inherit SeqComponent<'First,'V> @@ -658,15 +655,16 @@ namespace Microsoft.FSharp.Collections val inline map : f:('T -> 'U) -> source: ISeq<'T> -> ISeq<'U> [] - val mapi : - f:(int -> 'a -> 'b) -> - source: ISeq<'a> -> ISeq<'b> + val inline mapi : f:(int->'a->'b) -> source: ISeq<'a> -> ISeq<'b> + + val mapi_adapt : f:OptimizedClosures.FSharpFunc -> source: ISeq<'a> -> ISeq<'b> + [] - val choose : - f:('a -> 'b option) -> - source: ISeq<'a> -> ISeq<'b> + val choose : f:('a->option<'b>) -> source: ISeq<'a> -> ISeq<'b> + [] - val indexed : source: ISeq<'a> -> ISeq + val inline indexed : source: ISeq<'a> -> ISeq + [] val tryPick : f:('T -> 'U option) -> source: ISeq<'T> -> Option<'U> From 90472073352224b79b5b328fa2029a45794f16f5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:31:04 +1100 Subject: [PATCH 130/286] Removed old choose function --- src/fsharp/FSharp.Core/seq.fs | 588 ++++++++++++++++++++++++++++++++++ 1 file changed, 588 insertions(+) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 7d66b87b75e..1ec7eac7a90 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1,5 +1,593 @@ // 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 Microsoft.FSharp.Core + open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators + open Microsoft.FSharp.Core.Operators + open Microsoft.FSharp.Control + open Microsoft.FSharp.Collections + + module IEnumerator = + + let noReset() = raise (new System.NotSupportedException(SR.GetString(SR.resetNotSupported))) + let notStarted() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationNotStarted))) + let alreadyFinished() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationAlreadyFinished))) + let check started = if not started then notStarted() + let dispose (r : System.IDisposable) = r.Dispose() + + let cast (e : IEnumerator) : IEnumerator<'T> = + { new IEnumerator<'T> with + member x.Current = unbox<'T> e.Current + interface IEnumerator with + member x.Current = unbox<'T> e.Current :> obj + member x.MoveNext() = e.MoveNext() + member x.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = + match e with + | :? System.IDisposable as e -> e.Dispose() + | _ -> () } + + /// A concrete implementation of an enumerator that returns no values + [] + type EmptyEnumerator<'T>() = + let mutable started = false + interface IEnumerator<'T> with + member x.Current = + check started + (alreadyFinished() : 'T) + + interface System.Collections.IEnumerator with + member x.Current = + check started + (alreadyFinished() : obj) + member x.MoveNext() = + if not started then started <- true + false + member x.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = () + + let Empty<'T> () = (new EmptyEnumerator<'T>() :> IEnumerator<'T>) + + let rec tryItem index (e : IEnumerator<'T>) = + if not (e.MoveNext()) then None + elif index = 0 then Some(e.Current) + else tryItem (index-1) e + + let rec nth index (e : IEnumerator<'T>) = + if not (e.MoveNext()) then + let shortBy = index + 1 + invalidArgFmt "index" + "{0}\nseq was short by {1} {2}" + [|SR.GetString SR.notEnoughElements; shortBy; (if shortBy = 1 then "element" else "elements")|] + if index = 0 then e.Current + else nth (index-1) e + + [] + type MapEnumeratorState = + | NotStarted + | InProcess + | Finished + + [] + type MapEnumerator<'T> () = + let mutable state = NotStarted + [] + val mutable private curr : 'T + + member this.GetCurrent () = + match state with + | NotStarted -> notStarted() + | Finished -> alreadyFinished() + | InProcess -> () + this.curr + + abstract DoMoveNext : byref<'T> -> bool + abstract Dispose : unit -> unit + + interface IEnumerator<'T> with + member this.Current = this.GetCurrent() + + interface IEnumerator with + member this.Current = box(this.GetCurrent()) + member this.MoveNext () = + state <- InProcess + if this.DoMoveNext(&this.curr) then + true + else + state <- Finished + false + member this.Reset() = noReset() + interface System.IDisposable with + member this.Dispose() = this.Dispose() + + let mapi2 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) : IEnumerator<_> = + let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) + let i = ref (-1) + upcast + { new MapEnumerator<_>() with + member this.DoMoveNext curr = + i := !i + 1 + if (e1.MoveNext() && e2.MoveNext()) then + curr <- f.Invoke(!i, e1.Current, e2.Current) + true + else + false + member this.Dispose() = + try + e1.Dispose() + finally + e2.Dispose() + } + + let map3 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) (e3 : IEnumerator<_>) : IEnumerator<_> = + let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) + upcast + { new MapEnumerator<_>() with + member this.DoMoveNext curr = + let n1 = e1.MoveNext() + let n2 = e2.MoveNext() + let n3 = e3.MoveNext() + + if n1 && n2 && n3 then + curr <- f.Invoke(e1.Current, e2.Current, e3.Current) + true + else + false + member this.Dispose() = + try + e1.Dispose() + finally + try + e2.Dispose() + finally + e3.Dispose() + } + + let unfold f x : IEnumerator<_> = + let state = ref x + upcast + { new MapEnumerator<_>() with + member this.DoMoveNext curr = + match f !state with + | None -> false + | Some(r,s) -> + curr <- r + state := s + true + member this.Dispose() = () + } + + let upto lastOption f = + match lastOption with + | Some b when b<0 -> Empty() // a request for -ve length returns empty sequence + | _ -> + let unstarted = -1 // index value means unstarted (and no valid index) + let completed = -2 // index value means completed (and no valid index) + let unreachable = -3 // index is unreachable from 0,1,2,3,... + let finalIndex = match lastOption with + | Some b -> b // here b>=0, a valid end value. + | None -> unreachable // run "forever", well as far as Int32.MaxValue since indexing with a bounded type. + // The Current value for a valid index is "f i". + // Lazy<_> values are used as caches, to store either the result or an exception if thrown. + // These "Lazy<_>" caches are created only on the first call to current and forced immediately. + // The lazy creation of the cache nodes means enumerations that skip many Current values are not delayed by GC. + // For example, the full enumeration of Seq.initInfinite in the tests. + // state + let index = ref unstarted + // a Lazy node to cache the result/exception + let current = ref (Unchecked.defaultof<_>) + let setIndex i = index := i; current := (Unchecked.defaultof<_>) // cache node unprimed, initialised on demand. + let getCurrent() = + if !index = unstarted then notStarted() + if !index = completed then alreadyFinished() + match box !current with + | null -> current := Lazy<_>.Create(fun () -> f !index) + | _ -> () + // forced or re-forced immediately. + (!current).Force() + { new IEnumerator<'U> with + member x.Current = getCurrent() + interface IEnumerator with + member x.Current = box (getCurrent()) + member x.MoveNext() = + if !index = completed then + false + elif !index = unstarted then + setIndex 0 + true + else ( + if !index = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + if !index = finalIndex then + false + else + setIndex (!index + 1) + true + ) + member self.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = () } + + let readAndClear r = + lock r (fun () -> match !r with None -> None | Some _ as res -> r := None; res) + + let generateWhileSome openf compute closef : IEnumerator<'U> = + let started = ref false + let curr = ref None + let state = ref (Some(openf())) + let getCurr() = + check !started + match !curr with None -> alreadyFinished() | Some x -> x + let start() = if not !started then (started := true) + + let dispose() = readAndClear state |> Option.iter closef + let finish() = (try dispose() finally curr := None) + { new IEnumerator<'U> with + member x.Current = getCurr() + interface IEnumerator with + member x.Current = box (getCurr()) + member x.MoveNext() = + start() + match !state with + | None -> false (* we started, then reached the end, then got another MoveNext *) + | Some s -> + match (try compute s with e -> finish(); reraise()) with + | None -> finish(); false + | Some _ as x -> curr := x; true + + member x.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = dispose() } + + [] + type ArrayEnumerator<'T>(arr: 'T array) = + let mutable curr = -1 + let mutable len = arr.Length + member x.Get() = + if curr >= 0 then + if curr >= len then alreadyFinished() + else arr.[curr] + else + notStarted() + interface IEnumerator<'T> with + member x.Current = x.Get() + interface System.Collections.IEnumerator with + member x.MoveNext() = + if curr >= len then false + else + curr <- curr + 1 + (curr < len) + member x.Current = box(x.Get()) + member x.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = () + + let ofArray arr = (new ArrayEnumerator<'T>(arr) :> IEnumerator<'T>) + + [] + type Singleton<'T>(v:'T) = + let mutable started = false + interface IEnumerator<'T> with + member x.Current = v + interface IEnumerator with + member x.Current = box v + member x.MoveNext() = if started then false else (started <- true; true) + member x.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = () + + let Singleton x = (new Singleton<'T>(x) :> IEnumerator<'T>) + + let EnumerateThenFinally f (e : IEnumerator<'T>) = + { new IEnumerator<'T> with + member x.Current = e.Current + interface IEnumerator with + member x.Current = (e :> IEnumerator).Current + member x.MoveNext() = e.MoveNext() + member x.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = + try + e.Dispose() + finally + f() + } + + +namespace Microsoft.FSharp.Core.CompilerServices + + open System + open System.Diagnostics + open Microsoft.FSharp.Core + open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators + open Microsoft.FSharp.Core.Operators + open Microsoft.FSharp.Control + open Microsoft.FSharp.Collections + open Microsoft.FSharp.Primitives.Basics + open System.Collections + open System.Collections.Generic + + 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 inline checkNonNull argName arg = + match box arg with + | null -> nullArg argName + | _ -> () + + let mkSeq f = + { new IEnumerable<'U> with + member x.GetEnumerator() = f() + interface IEnumerable with + member x.GetEnumerator() = (f() :> IEnumerator) } + + [] + type EmptyEnumerable<'T> = + | EmptyEnumerable + interface IEnumerable<'T> with + member x.GetEnumerator() = IEnumerator.Empty<'T>() + interface IEnumerable with + member x.GetEnumerator() = (IEnumerator.Empty<'T>() :> IEnumerator) + + let Generate openf compute closef = + mkSeq (fun () -> IEnumerator.generateWhileSome openf compute closef) + + let GenerateUsing (openf : unit -> ('U :> System.IDisposable)) compute = + Generate openf compute (fun (s:'U) -> s.Dispose()) + + let EnumerateFromFunctions opener moveNext current = + Generate + opener + (fun x -> if moveNext x then Some(current x) else None) + (fun x -> match box(x) with :? System.IDisposable as id -> id.Dispose() | _ -> ()) + + // A family of enumerators that can have additional 'finally' actions added to the enumerator through + // the use of mutation. This is used to 'push' the disposal action for a 'use' into the next enumerator. + // For example, + // seq { use x = ... + // while ... } + // results in the 'while' loop giving an adjustable enumerator. This is then adjusted by adding the disposal action + // from the 'use' into the enumerator. This means that we avoid constructing a two-deep enumerator chain in this + // common case. + type IFinallyEnumerator = + abstract AppendFinallyAction : (unit -> unit) -> unit + + /// A concrete implementation of IEnumerable that adds the given compensation to the "Dispose" chain of any + /// enumerators returned by the enumerable. + [] + type FinallyEnumerable<'T>(compensation: unit -> unit, restf: unit -> seq<'T>) = + interface IEnumerable<'T> with + member x.GetEnumerator() = + try + let ie = restf().GetEnumerator() + match ie with + | :? IFinallyEnumerator as a -> + a.AppendFinallyAction(compensation) + ie + | _ -> + IEnumerator.EnumerateThenFinally compensation ie + with e -> + compensation() + reraise() + interface IEnumerable with + member x.GetEnumerator() = ((x :> IEnumerable<'T>).GetEnumerator() :> IEnumerator) + + /// An optimized object for concatenating a sequence of enumerables + [] + type ConcatEnumerator<'T,'U when 'U :> seq<'T>>(sources: seq<'U>) = + let mutable outerEnum = sources.GetEnumerator() + let mutable currInnerEnum = IEnumerator.Empty() + + let mutable started = false + let mutable finished = false + let mutable compensations = [] + + [] // false = unchecked + val mutable private currElement : 'T + + member x.Finish() = + finished <- true + try + match currInnerEnum with + | null -> () + | _ -> + try + currInnerEnum.Dispose() + finally + currInnerEnum <- null + finally + try + match outerEnum with + | null -> () + | _ -> + try + outerEnum.Dispose() + finally + outerEnum <- null + finally + let rec iter comps = + match comps with + | [] -> () + | h::t -> + try h() finally iter t + try + compensations |> List.rev |> iter + finally + compensations <- [] + + member x.GetCurrent() = + IEnumerator.check started + if finished then IEnumerator.alreadyFinished() else x.currElement + + interface IFinallyEnumerator with + member x.AppendFinallyAction(f) = + compensations <- f :: compensations + + interface IEnumerator<'T> with + member x.Current = x.GetCurrent() + + interface IEnumerator with + member x.Current = box (x.GetCurrent()) + + member x.MoveNext() = + if not started then (started <- true) + if finished then false + else + let rec takeInner () = + // check the inner list + if currInnerEnum.MoveNext() then + x.currElement <- currInnerEnum.Current + true + else + // check the outer list + let rec takeOuter() = + if outerEnum.MoveNext() then + let ie = outerEnum.Current + // Optimization to detect the statically-allocated empty IEnumerables + match box ie with + | :? EmptyEnumerable<'T> -> + // This one is empty, just skip, don't call GetEnumerator, try again + takeOuter() + | _ -> + // OK, this one may not be empty. + // Don't forget to dispose of the enumerator for the inner list now we're done with it + currInnerEnum.Dispose() + currInnerEnum <- ie.GetEnumerator() + takeInner () + else + // We're done + x.Finish() + false + takeOuter() + takeInner () + + member x.Reset() = IEnumerator.noReset() + + interface System.IDisposable with + member x.Dispose() = + if not finished then + x.Finish() + + let EnumerateUsing (resource : 'T :> System.IDisposable) (rest: 'T -> #seq<'U>) = + (FinallyEnumerable((fun () -> match box resource with null -> () | _ -> resource.Dispose()), + (fun () -> rest resource :> seq<_>)) :> seq<_>) + + let mkConcatSeq (sources: seq<'U :> seq<'T>>) = + mkSeq (fun () -> new ConcatEnumerator<_,_>(sources) :> IEnumerator<'T>) + + let EnumerateWhile (g : unit -> bool) (b: seq<'T>) : seq<'T> = + let started = ref false + let curr = ref None + let getCurr() = + IEnumerator.check !started + match !curr with None -> IEnumerator.alreadyFinished() | Some x -> x + let start() = if not !started then (started := true) + + let finish() = (curr := None) + mkConcatSeq + (mkSeq (fun () -> + { new IEnumerator<_> with + member x.Current = getCurr() + interface IEnumerator with + member x.Current = box (getCurr()) + member x.MoveNext() = + start() + let keepGoing = (try g() with e -> finish (); reraise ()) in + if keepGoing then + curr := Some(b); true + else + finish(); false + member x.Reset() = IEnumerator.noReset() + interface System.IDisposable with + member x.Dispose() = () })) + + let EnumerateThenFinally (rest : seq<'T>) (compensation : unit -> unit) = + (FinallyEnumerable(compensation, (fun () -> rest)) :> seq<_>) + + let CreateEvent (add : 'Delegate -> unit) (remove : 'Delegate -> unit) (create : (obj -> 'Args -> unit) -> 'Delegate ) :IEvent<'Delegate,'Args> = + // Note, we implement each interface explicitly: this works around a bug in the CLR + // implementation on CompactFramework 3.7, used on Windows Phone 7 + { new obj() with + member x.ToString() = "" + interface IEvent<'Delegate,'Args> + interface IDelegateEvent<'Delegate> with + member x.AddHandler(h) = add h + member x.RemoveHandler(h) = remove h + interface System.IObservable<'Args> with + member x.Subscribe(r:IObserver<'Args>) = + let h = create (fun _ args -> r.OnNext(args)) + add h + { new System.IDisposable with + member x.Dispose() = remove h } } + + + [] + type GeneratedSequenceBase<'T>() = + let mutable redirectTo : GeneratedSequenceBase<'T> = Unchecked.defaultof<_> + let mutable redirect : bool = false + + abstract GetFreshEnumerator : unit -> IEnumerator<'T> + abstract GenerateNext : next:byref> -> int // 0 = Stop, 1 = Yield, 2 = Goto + abstract Close: unit -> unit + abstract CheckClose: bool + abstract LastGenerated : 'T + + //[] + member x.MoveNextImpl() = + let active = + if redirect then redirectTo + else x + let mutable target = null + match active.GenerateNext(&target) with + | 1 -> + true + | 2 -> + match target.GetEnumerator() with + | :? GeneratedSequenceBase<'T> as g when not active.CheckClose -> + redirectTo <- g + | e -> + redirectTo <- + { new GeneratedSequenceBase<'T>() with + member x.GetFreshEnumerator() = e + member x.GenerateNext(_) = if e.MoveNext() then 1 else 0 + member x.Close() = try e.Dispose() finally active.Close() + member x.CheckClose = true + member x.LastGenerated = e.Current } + redirect <- true + x.MoveNextImpl() + | _ (* 0 *) -> + false + + interface IEnumerable<'T> with + member x.GetEnumerator() = x.GetFreshEnumerator() + interface IEnumerable with + member x.GetEnumerator() = (x.GetFreshEnumerator() :> IEnumerator) + interface IEnumerator<'T> with + member x.Current = if redirect then redirectTo.LastGenerated else x.LastGenerated + member x.Dispose() = if redirect then redirectTo.Close() else x.Close() + interface IEnumerator with + member x.Current = box (if redirect then redirectTo.LastGenerated else x.LastGenerated) + + //[] + member x.MoveNext() = x.MoveNextImpl() + + member x.Reset() = raise <| new System.NotSupportedException() + + namespace Microsoft.FSharp.Collections open System From dced01055ed22981e29f8b5d72550e352efd33fd Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:46:05 +1100 Subject: [PATCH 131/286] localizing upto This is retained for compatibility --- src/fsharp/FSharp.Core/seq.fs | 830 ++++++++++++++++++++++++++++++++-- 1 file changed, 781 insertions(+), 49 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 1ec7eac7a90..d56a8304d7a 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -164,55 +164,6 @@ namespace Microsoft.FSharp.Collections member this.Dispose() = () } - let upto lastOption f = - match lastOption with - | Some b when b<0 -> Empty() // a request for -ve length returns empty sequence - | _ -> - let unstarted = -1 // index value means unstarted (and no valid index) - let completed = -2 // index value means completed (and no valid index) - let unreachable = -3 // index is unreachable from 0,1,2,3,... - let finalIndex = match lastOption with - | Some b -> b // here b>=0, a valid end value. - | None -> unreachable // run "forever", well as far as Int32.MaxValue since indexing with a bounded type. - // The Current value for a valid index is "f i". - // Lazy<_> values are used as caches, to store either the result or an exception if thrown. - // These "Lazy<_>" caches are created only on the first call to current and forced immediately. - // The lazy creation of the cache nodes means enumerations that skip many Current values are not delayed by GC. - // For example, the full enumeration of Seq.initInfinite in the tests. - // state - let index = ref unstarted - // a Lazy node to cache the result/exception - let current = ref (Unchecked.defaultof<_>) - let setIndex i = index := i; current := (Unchecked.defaultof<_>) // cache node unprimed, initialised on demand. - let getCurrent() = - if !index = unstarted then notStarted() - if !index = completed then alreadyFinished() - match box !current with - | null -> current := Lazy<_>.Create(fun () -> f !index) - | _ -> () - // forced or re-forced immediately. - (!current).Force() - { new IEnumerator<'U> with - member x.Current = getCurrent() - interface IEnumerator with - member x.Current = box (getCurrent()) - member x.MoveNext() = - if !index = completed then - false - elif !index = unstarted then - setIndex 0 - true - else ( - if !index = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) - if !index = finalIndex then - false - else - setIndex (!index + 1) - true - ) - member self.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = () } let readAndClear r = lock r (fun () -> match !r with None -> None | Some _ as res -> r := None; res) @@ -623,6 +574,787 @@ namespace Microsoft.FSharp.Collections [] [] module Seq = +// type ISeqEnumerable<'T> = +// abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State + + module SeqComposer = + open IEnumerator + + type ISeqComponent = + abstract OnComplete : unit -> unit + abstract OnDispose : unit -> unit + + module Helpers = + // used for performance reasons; these are not recursive calls, so should be safe + let inline avoidTailCall x = + match x with + | true -> true + | false -> false + + let inline ComposeFilter f g x = f x && g x + + let inline UpcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) + let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) + let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) + let inline UpcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) + + type SeqProcessNextStates = + | InProcess = 0 + | NotStarted = 1 + | Finished = 2 + + type Result<'T>() = + let mutable halted = false + + member val SeqState = SeqProcessNextStates.NotStarted with get, set + + member __.StopFurtherProcessing () = halted <- true + member __.Halted = halted + + member val Current = Unchecked.defaultof<'T> with get, set + + let seqComponentTail = + { new ISeqComponent with + member __.OnComplete() = () + member __.OnDispose() = () } + + type [] SeqComponentFactory<'T,'U> () = + abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V> + + and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = + inherit SeqComponentFactory<'T,'V> () + override __.Create<'W> (result:Result<'W>) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create result (second.Create result next) + + and ChooseFactory<'T,'U> (filter:'T->option<'U>) = + inherit SeqComponentFactory<'T,'U> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next) + + and DistinctFactory<'T when 'T: equality> () = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Distinct (next) + + and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast DistinctBy (keyFunction, next) + + and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Except (itemsToExclude, next) + + and FilterFactory<'T> (filter:'T->bool) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter + + and MapFactory<'T,'U> (map:'T->'U) = + inherit SeqComponentFactory<'T,'U> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map + + and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = + inherit SeqComponentFactory<'First,'U> () + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map2First (map, input2, result, next) + + and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = + inherit SeqComponentFactory<'Second,'U> () + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'Second,'V> = upcast Map2Second (map, input1, result, next) + + and MapiFactory<'T,'U> (mapi:int->'T->'U) = + inherit SeqComponentFactory<'T,'U> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next) + + and PairwiseFactory<'T> () = + inherit SeqComponentFactory<'T,'T*'T> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next + + and SkipFactory<'T> (count:int) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next) + + and SkipWhileFactory<'T> (predicate:'T->bool) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (predicate, next) + + and TakeWhileFactory<'T> (predicate:'T->bool) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (predicate, result, next) + + and TakeFactory<'T> (count:int) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next) + + and TruncateFactory<'T> (count:int) = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Truncate (count, result, next) + + and [] SeqComponent<'T,'U> (next:ISeqComponent) = + abstract ProcessNext : input:'T -> bool + + // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip + // and it can only do it at the start of a sequence + abstract Skipping : unit -> bool + + abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> + abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> + + interface ISeqComponent with + member __.OnComplete () = next.OnComplete () + member __.OnDispose () = next.OnDispose () + + default __.Skipping () = false + + default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) + default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) + + and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'T,'V>(next) + + override __.ProcessNext (input:'T) : bool = + match choose input with + | Some value -> Helpers.avoidTailCall (next.ProcessNext value) + | None -> false + + and Distinct<'T,'V when 'T: equality> (next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) + + override __.ProcessNext (input:'T) : bool = + if hashSet.Add input then + Helpers.avoidTailCall (next.ProcessNext input) + else + false + + and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) + + override __.ProcessNext (input:'T) : bool = + if hashSet.Add(keyFunction input) then + Helpers.avoidTailCall (next.ProcessNext input) + else + false + + and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) + + override __.ProcessNext (input:'T) : bool = + if cached.Value.Add input then + Helpers.avoidTailCall (next.ProcessNext input) + else + false + + and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) + + override __.ProcessNext (input:'T) : bool = + if filter input then + Helpers.avoidTailCall (next.ProcessNext input) + else + false + + and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'T,'V>(next) + + override __.ProcessNext (input:'T) : bool = + if filter input then + Helpers.avoidTailCall (next.ProcessNext (map input)) + else + false + + and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'T,'V>(next) + + override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) + + override __.ProcessNext (input:'T) : bool = + Helpers.avoidTailCall (next.ProcessNext (map input)) + + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'First,'V>(next) + + let input2 = enumerable2.GetEnumerator () + let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map + + override __.ProcessNext (input:'First) : bool = + if input2.MoveNext () then + Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) + else + result.StopFurtherProcessing () + false + + interface ISeqComponent with + override __.OnDispose () = + try + input2.Dispose () + finally + (Helpers.UpcastISeqComponent next).OnDispose () + + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'Second,'V>(next) + + let input1 = enumerable1.GetEnumerator () + let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map + + override __.ProcessNext (input:'Second) : bool = + if input1.MoveNext () then + Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) + else + result.StopFurtherProcessing () + false + + interface ISeqComponent with + override __.OnDispose () = + try + input1.Dispose () + finally + (Helpers.UpcastISeqComponent next).OnDispose () + + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'T,'V>(next) + + override __.ProcessNext (input:'T) : bool = + let u = map input + if filter u then + Helpers.avoidTailCall (next.ProcessNext u) + else + false + + and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'T,'V>(next) + + let mutable idx = 0 + let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi + + override __.ProcessNext (input:'T) : bool = + idx <- idx + 1 + Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) + + and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let mutable isFirst = true + let mutable lastValue = Unchecked.defaultof<'T> + + override __.ProcessNext (input:'T) : bool = + if isFirst then + lastValue <- input + isFirst <- false + false + else + let currentPair = lastValue, input + lastValue <- input + Helpers.avoidTailCall (next.ProcessNext currentPair) + + and Skip<'T,'V> (skipCount:int, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let mutable count = 0 + + override __.Skipping () = + if count < skipCount then + count <- count + 1 + true + else + false + + override __.ProcessNext (input:'T) : bool = + if count < skipCount then + count <- count + 1 + false + else + Helpers.avoidTailCall (next.ProcessNext input) + + interface ISeqComponent with + override __.OnComplete () = + if count < skipCount then + let x = skipCount - count + invalidOpFmt "tried to skip {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + (Helpers.UpcastISeqComponent next).OnComplete () + + and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let mutable skip = true + + override __.ProcessNext (input:'T) : bool = + if skip then + skip <- predicate input + if skip then + false + else + Helpers.avoidTailCall (next.ProcessNext input) + else + Helpers.avoidTailCall (next.ProcessNext input) + + and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = + inherit Truncate<'T, 'V>(takeCount, result, next) + + interface ISeqComponent with + override this.OnComplete () = + if this.Count < takeCount then + let x = takeCount - this.Count + invalidOpFmt "tried to take {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + (Helpers.UpcastISeqComponent next).OnComplete () + + and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + override __.ProcessNext (input:'T) : bool = + if predicate input then + next.ProcessNext input + else + result.StopFurtherProcessing () + false + + and Tail<'T> (result:Result<'T>) = + inherit SeqComponent<'T,'T>(seqComponentTail) + + override __.ProcessNext (input:'T) : bool = + result.Current <- input + true + + and Truncate<'T,'V> (truncateCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let mutable count = 0 + + member __.Count = count + + override __.ProcessNext (input:'T) : bool = + if count < truncateCount then + count <- count + 1 + if count = truncateCount then + result.StopFurtherProcessing () + next.ProcessNext input + else + result.StopFurtherProcessing () + false + + module Enumerable = + [] + type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) = + interface IDisposable with + member __.Dispose() : unit = + seqComponent.OnDispose () + + interface IEnumerator with + member this.Current : obj = box ((Helpers.UpcastEnumerator 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.Current + else + match result.SeqState with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> failwith "library implementation error: all states should have been handled" + + and [] EnumerableBase<'T> () = + abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> + abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> + abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State + + default this.Append source = Helpers.UpcastEnumerable (AppendEnumerable [this; source]) + + interface IEnumerable with + member this.GetEnumerator () : IEnumerator = + let genericEnumerable = Helpers.UpcastEnumerable this + let genericEnumerator = genericEnumerable.GetEnumerator () + Helpers.UpcastEnumeratorNonGeneric genericEnumerator + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" + + and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, seqComponent) + + let rec moveNext () = + if (not result.Halted) && source.MoveNext () then + if seqComponent.ProcessNext source.Current then + true + else + moveNext () + else + result.SeqState <- SeqProcessNextStates.Finished + (Helpers.UpcastISeqComponent seqComponent).OnComplete () + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + interface IDisposable with + member __.Dispose() = + try + source.Dispose () + finally + (Helpers.UpcastISeqComponent seqComponent).OnDispose () + + and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = + inherit EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Helpers.UpcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) + + override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory (current, next))) + + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let enumerator = enumerable.GetEnumerator () + let result = Result<'U> () + + let components = current.Create result (Tail result) + + let mutable state = initialState + while (not result.Halted) && (enumerator.MoveNext ()) do + if components.ProcessNext (enumerator.Current) then + state <- folder'.Invoke (state, result.Current) + + state + + and AppendEnumerator<'T> (sources:list>) = + let sources = sources |> List.rev + + let mutable state = SeqProcessNextStates.NotStarted + let mutable remaining = sources.Tail + let mutable active = sources.Head.GetEnumerator () + + let rec moveNext () = + if active.MoveNext () then true + else + match remaining with + | [] -> false + | hd :: tl -> + active.Dispose () + active <- hd.GetEnumerator () + remaining <- tl + + moveNext () + + 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 ((Helpers.UpcastEnumerator this)).Current + member __.MoveNext () = + state <- SeqProcessNextStates.InProcess + moveNext () + member __.Reset () = noReset () + + interface IDisposable with + member __.Dispose() = + active.Dispose () + + and AppendEnumerable<'T> (sources:list>) = + inherit EnumerableBase<'T>() + + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = + Helpers.UpcastEnumerator (new AppendEnumerator<_> (sources)) + + override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = + Helpers.UpcastEnumerable (Enumerable<'T,'V>(this, next)) + + override this.Append source = + Helpers.UpcastEnumerable (AppendEnumerable (source :: sources)) + + override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let enumerable = Helpers.UpcastEnumerable (AppendEnumerable sources) + let enumerator = enumerable.GetEnumerator () + + let mutable state = initialState + while enumerator.MoveNext () do + state <- folder'.Invoke (state, enumerator.Current) + + state + + module Array = + type Enumerator<'T,'U>(array:array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) + + let mutable idx = 0 + + let rec moveNext () = + if (not result.Halted) && idx < array.Length then + idx <- idx+1 + if seqComponent.ProcessNext array.[idx-1] then + true + else + moveNext () + else + result.SeqState <- SeqProcessNextStates.Finished + (Helpers.UpcastISeqComponent seqComponent).OnComplete () + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type Enumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) = + inherit Enumerable.EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Helpers.UpcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail result), result)) + + override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory (current, next))) + + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let mutable idx = 0 + let result = Result<'U> () + let components = current.Create result (Tail result) + + let mutable state = initialState + while (not result.Halted) && (idx < array.Length) do + if components.ProcessNext array.[idx] then + state <- folder'.Invoke (state, result.Current) + idx <- idx + 1 + + state + + module List = + type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) + + let mutable list = alist + + let rec moveNext current = + match result.Halted, current with + | false, head::tail -> + if seqComponent.ProcessNext head then + list <- tail + true + else + moveNext tail + | _ -> + result.SeqState <- SeqProcessNextStates.Finished + (Helpers.UpcastISeqComponent seqComponent).OnComplete () + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext list + + type Enumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) = + inherit Enumerable.EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Helpers.UpcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail result), result)) + + override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory (current, next))) + + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let result = Result<'U> () + let components = current.Create result (Tail result) + + let rec fold state lst = + match result.Halted, lst with + | true, _ + | false, [] -> state + | false, hd :: tl -> + if components.ProcessNext hd then + fold (folder'.Invoke (state, result.Current)) tl + else + fold state tl + + fold initialState alist + + 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, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) + + let terminatingIdx = + getTerminatingIdx count + + let mutable maybeSkipping = true + let mutable idx = -1 + + let rec moveNext () = + if (not signal.Halted) && 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 <- seqComponent.Skipping () + + if maybeSkipping then + moveNext () + elif seqComponent.ProcessNext (f idx) then + true + else + moveNext () + elif (not signal.Halted) && idx = System.Int32.MaxValue then + raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + else + signal.SeqState <- SeqProcessNextStates.Finished + (Helpers.UpcastISeqComponent seqComponent).OnComplete () + false + + interface IEnumerator with + member __.MoveNext () = + signal.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) = + inherit Enumerable.EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Helpers.UpcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail result), result)) + + override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.UpcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next))) + + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let result = Result<'U> () + let components = current.Create result (Tail result) + + let mutable idx = -1 + let terminatingIdx = getTerminatingIdx count + + let mutable maybeSkipping = true + + let mutable state = initialState + while (not result.Halted) && (idx < terminatingIdx) do + if maybeSkipping then + maybeSkipping <- components.Skipping () + + if (not maybeSkipping) && (components.ProcessNext (f (idx+1))) then + state <- folder'.Invoke (state, result.Current) + + idx <- idx + 1 + + state + + let upto lastOption f = + match lastOption with + | Some b when b<0 -> Empty() // a request for -ve length returns empty sequence + | _ -> + let unstarted = -1 // index value means unstarted (and no valid index) + let completed = -2 // index value means completed (and no valid index) + let unreachable = -3 // index is unreachable from 0,1,2,3,... + let finalIndex = match lastOption with + | Some b -> b // here b>=0, a valid end value. + | None -> unreachable // run "forever", well as far as Int32.MaxValue since indexing with a bounded type. + // The Current value for a valid index is "f i". + // Lazy<_> values are used as caches, to store either the result or an exception if thrown. + // These "Lazy<_>" caches are created only on the first call to current and forced immediately. + // The lazy creation of the cache nodes means enumerations that skip many Current values are not delayed by GC. + // For example, the full enumeration of Seq.initInfinite in the tests. + // state + let index = ref unstarted + // a Lazy node to cache the result/exception + let current = ref (Unchecked.defaultof<_>) + let setIndex i = index := i; current := (Unchecked.defaultof<_>) // cache node unprimed, initialised on demand. + let getCurrent() = + if !index = unstarted then notStarted() + if !index = completed then alreadyFinished() + match box !current with + | null -> current := Lazy<_>.Create(fun () -> f !index) + | _ -> () + // forced or re-forced immediately. + (!current).Force() + { new IEnumerator<'U> with + member x.Current = getCurrent() + interface IEnumerator with + member x.Current = box (getCurrent()) + member x.MoveNext() = + if !index = completed then + false + elif !index = unstarted then + setIndex 0 + true + else ( + if !index = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + if !index = finalIndex then + false + else + setIndex (!index + 1) + true + ) + member self.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = () } + + type EnumerableDecider<'T>(count:Nullable, f:int->'T) = + 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 + + override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = + Helpers.UpcastEnumerable (Enumerable<'T,'V>(count, f, next)) + + override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let enumerator = (Helpers.UpcastEnumerable this).GetEnumerator () + + let mutable state = initialState + while enumerator.MoveNext () do + state <- folder'.Invoke (state, enumerator.Current) + + state + #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions #else From 7d95187c1f6820289c158eefed4ef5ab41ece5a3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:52:39 +1100 Subject: [PATCH 132/286] cleaning up SeqComposer.Helpers - better comments - consistent casing --- src/fsharp/FSharp.Core/seq.fs | 95 +++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 44 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index d56a8304d7a..f19940af7f7 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -586,17 +586,16 @@ namespace Microsoft.FSharp.Collections module Helpers = // used for performance reasons; these are not recursive calls, so should be safe - let inline avoidTailCall x = - match x with - | true -> true - | false -> false + // ** it should be noted that potential changes to the f# compiler may render this function + // ineffictive ** + let inline avoidTailCall boolean = match boolean with true -> true | false -> false - let inline ComposeFilter f g x = f x && g x - - let inline UpcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) - let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) - let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline UpcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) + // 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 upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) + let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) + let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) + let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) type SeqProcessNextStates = | InProcess = 0 @@ -791,7 +790,7 @@ namespace Microsoft.FSharp.Collections try input2.Dispose () finally - (Helpers.UpcastISeqComponent next).OnDispose () + (Helpers.upcastISeqComponent next).OnDispose () and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) = inherit SeqComponent<'Second,'V>(next) @@ -811,7 +810,7 @@ namespace Microsoft.FSharp.Collections try input1.Dispose () finally - (Helpers.UpcastISeqComponent next).OnDispose () + (Helpers.upcastISeqComponent next).OnDispose () and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) = inherit SeqComponent<'T,'V>(next) @@ -874,7 +873,7 @@ namespace Microsoft.FSharp.Collections let x = skipCount - count invalidOpFmt "tried to skip {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.UpcastISeqComponent next).OnComplete () + (Helpers.upcastISeqComponent next).OnComplete () and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -900,7 +899,7 @@ namespace Microsoft.FSharp.Collections let x = takeCount - this.Count invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.UpcastISeqComponent next).OnComplete () + (Helpers.upcastISeqComponent next).OnComplete () and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -944,7 +943,7 @@ namespace Microsoft.FSharp.Collections seqComponent.OnDispose () interface IEnumerator with - member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current + member this.Current : obj = box ((Helpers.upcastEnumerator this)).Current member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)" member __.Reset () : unit = noReset () @@ -962,13 +961,13 @@ namespace Microsoft.FSharp.Collections abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State - default this.Append source = Helpers.UpcastEnumerable (AppendEnumerable [this; source]) + default this.Append source = Helpers.upcastEnumerable (AppendEnumerable [this; source]) interface IEnumerable with member this.GetEnumerator () : IEnumerator = - let genericEnumerable = Helpers.UpcastEnumerable this + let genericEnumerable = Helpers.upcastEnumerable this let genericEnumerator = genericEnumerable.GetEnumerator () - Helpers.UpcastEnumeratorNonGeneric genericEnumerator + Helpers.upcastEnumeratorNonGeneric genericEnumerator interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" @@ -984,7 +983,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.UpcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -997,7 +996,7 @@ namespace Microsoft.FSharp.Collections try source.Dispose () finally - (Helpers.UpcastISeqComponent seqComponent).OnDispose () + (Helpers.upcastISeqComponent seqComponent).OnDispose () and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = inherit EnumerableBase<'U>() @@ -1005,10 +1004,10 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.UpcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory (current, next))) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1054,7 +1053,7 @@ namespace Microsoft.FSharp.Collections | _ -> failwith "library implementation error: all states should have been handled" interface IEnumerator with - member this.Current = box ((Helpers.UpcastEnumerator this)).Current + member this.Current = box ((Helpers.upcastEnumerator this)).Current member __.MoveNext () = state <- SeqProcessNextStates.InProcess moveNext () @@ -1069,18 +1068,18 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - Helpers.UpcastEnumerator (new AppendEnumerator<_> (sources)) + Helpers.upcastEnumerator (new AppendEnumerator<_> (sources)) override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = - Helpers.UpcastEnumerable (Enumerable<'T,'V>(this, next)) + Helpers.upcastEnumerable (Enumerable<'T,'V>(this, next)) override this.Append source = - Helpers.UpcastEnumerable (AppendEnumerable (source :: sources)) + Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - let enumerable = Helpers.UpcastEnumerable (AppendEnumerable sources) + let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) let enumerator = enumerable.GetEnumerator () let mutable state = initialState @@ -1104,7 +1103,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.UpcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -1118,10 +1117,10 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.UpcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory (current, next))) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1154,7 +1153,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (Helpers.UpcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -1168,10 +1167,10 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.UpcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory (current, next))) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1239,7 +1238,7 @@ namespace Microsoft.FSharp.Collections raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else signal.SeqState <- SeqProcessNextStates.Finished - (Helpers.UpcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -1253,10 +1252,10 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.UpcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.UpcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next))) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1342,12 +1341,12 @@ namespace Microsoft.FSharp.Collections upto (if count.HasValue then Some (count.Value-1) else None) f override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = - Helpers.UpcastEnumerable (Enumerable<'T,'V>(count, f, next)) + Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - let enumerator = (Helpers.UpcastEnumerable this).GetEnumerator () + let enumerator = (Helpers.upcastEnumerable this).GetEnumerator () let mutable state = initialState while enumerator.MoveNext () do @@ -1390,13 +1389,13 @@ namespace Microsoft.FSharp.Collections [] let initInfinite<'T> (f:int->'T) : IEnumerable<'T> = - Composer.Seq.initInfinite f - |> Upcast.enumerable + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable (), f)) [] let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> = - Composer.Seq.init count f - |> Upcast.enumerable + if count < 0 then invalidArgInputMustBeNonNegative "count" count + elif count = 0 then empty else + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable count, f)) [] let iter f (source : seq<'T>) = @@ -1489,6 +1488,14 @@ namespace Microsoft.FSharp.Collections let revamp3 f (ie1 : seq<_>) (source2 : seq<_>) (source3 : seq<_>) = mkSeq (fun () -> f (ie1.GetEnumerator()) (source2.GetEnumerator()) (source3.GetEnumerator())) + let private seqFactory createSeqComponent (source:seq<'T>) = + checkNonNull "source" source + match source with + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose createSeqComponent + | :? array<'T> as a -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<_,_>(a, createSeqComponent)) + | :? list<'T> as a -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.List.Enumerable<_,_>(a, createSeqComponent)) + | _ -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Enumerable.Enumerable<_,_>(source, createSeqComponent)) + [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = Composer.Seq.filter f (toComposer source) @@ -1666,8 +1673,8 @@ namespace Microsoft.FSharp.Collections checkNonNull "source1" source1 checkNonNull "source2" source2 match source1 with - | :? Composer.Seq.Enumerable.EnumerableBase<'T> as s -> s.Append source2 - | _ -> Upcast.enumerable (new Composer.Seq.Enumerable.AppendEnumerable<_>([source2; source1])) + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Append source2 + | _ -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Enumerable.AppendEnumerable<_>([source2; source1])) [] From 595567e63da4b789abe578357f78a2518e7713f7 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:59:00 +1100 Subject: [PATCH 133/286] Seq.map3 --- src/fsharp/FSharp.Core/seq.fs | 54 +++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index f19940af7f7..59b0d736e4f 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -126,30 +126,6 @@ namespace Microsoft.FSharp.Collections e2.Dispose() } - let map3 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) (e3 : IEnumerator<_>) : IEnumerator<_> = - let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) - upcast - { new MapEnumerator<_>() with - member this.DoMoveNext curr = - let n1 = e1.MoveNext() - let n2 = e2.MoveNext() - let n3 = e3.MoveNext() - - if n1 && n2 && n3 then - curr <- f.Invoke(e1.Current, e2.Current, e3.Current) - true - else - false - member this.Dispose() = - try - e1.Dispose() - finally - try - e2.Dispose() - finally - e3.Dispose() - } - let unfold f x : IEnumerator<_> = let state = ref x upcast @@ -656,6 +632,10 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'Second,'U> () override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'Second,'V> = upcast Map2Second (map, input1, result, next) + and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = + inherit SeqComponentFactory<'First,'U> () + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map3 (map, input2, input3, result, next) + and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next) @@ -812,6 +792,30 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:Result<'V>, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'First,'V>(next) + + let input2 = enumerable2.GetEnumerator () + let input3 = enumerable3.GetEnumerator () + let map' = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt map + + override __.ProcessNext (input:'First) : bool = + if input2.MoveNext () && input3.MoveNext () then + Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) + else + result.StopFurtherProcessing () + false + + interface ISeqComponent with + override __.OnDispose () = + try + input2.Dispose () + finally + try + input3.Dispose () + finally + (Helpers.upcastISeqComponent next).OnDispose () + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) = inherit SeqComponent<'T,'V>(next) @@ -1531,7 +1535,7 @@ namespace Microsoft.FSharp.Collections let map3 f source1 source2 source3 = checkNonNull "source2" source2 checkNonNull "source3" source3 - source1 |> seqFactory (Composer.Seq.Map3Factory (f, source2, source3)) + source1 |> seqFactory (SeqComposer.Map3Factory (f, source2, source3)) [] let choose f source = From 3ee8914a043eff0ddfbdebfd4067f9ee94871af4 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 06:06:25 +1100 Subject: [PATCH 134/286] Seq.mapi2 --- src/fsharp/FSharp.Core/seq.fs | 47 ++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 59b0d736e4f..fa0a8348829 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -107,25 +107,6 @@ namespace Microsoft.FSharp.Collections interface System.IDisposable with member this.Dispose() = this.Dispose() - let mapi2 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) : IEnumerator<_> = - let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) - let i = ref (-1) - upcast - { new MapEnumerator<_>() with - member this.DoMoveNext curr = - i := !i + 1 - if (e1.MoveNext() && e2.MoveNext()) then - curr <- f.Invoke(!i, e1.Current, e2.Current) - true - else - false - member this.Dispose() = - try - e1.Dispose() - finally - e2.Dispose() - } - let unfold f x : IEnumerator<_> = let state = ref x upcast @@ -640,6 +621,10 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next) + and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = + inherit SeqComponentFactory<'First,'U> () + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Mapi2 (map, input2, result, next) + and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next @@ -836,6 +821,28 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'First,'V>(next) + + let mutable idx = 0 + let input2 = enumerable2.GetEnumerator () + let mapi2' = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt map + + override __.ProcessNext (input:'First) : bool = + if input2.MoveNext () then + idx <- idx + 1 + Helpers.avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) + else + result.StopFurtherProcessing () + false + + interface ISeqComponent with + override __.OnDispose () = + try + input2.Dispose () + finally + (Helpers.upcastISeqComponent next).OnDispose () + and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -1522,7 +1529,7 @@ namespace Microsoft.FSharp.Collections [] let mapi2 f source1 source2 = checkNonNull "source2" source2 - source1 |> seqFactory (Composer.Seq.Mapi2Factory (f, source2)) + source1 |> seqFactory (SeqComposer.Mapi2Factory (f, source2)) [] let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = From 239d36f657beb722e9987615468df693163fbdcc Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 06:09:39 +1100 Subject: [PATCH 135/286] Simplified map2 - removing the check of both types --- src/fsharp/FSharp.Core/seq.fs | 34 ++++------------------------------ 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index fa0a8348829..79059f022e5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -605,13 +605,9 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map - and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = + and Map2Factory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map2First (map, input2, result, next) - - and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = - inherit SeqComponentFactory<'Second,'U> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'Second,'V> = upcast Map2Second (map, input1, result, next) + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map2 (map, input2, result, next) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () @@ -737,7 +733,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = + and Map2<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -757,26 +753,6 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) = - inherit SeqComponent<'Second,'V>(next) - - let input1 = enumerable1.GetEnumerator () - let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map - - override __.ProcessNext (input:'Second) : bool = - if input1.MoveNext () then - Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) - else - result.StopFurtherProcessing () - false - - interface ISeqComponent with - override __.OnDispose () = - try - input1.Dispose () - finally - (Helpers.upcastISeqComponent next).OnDispose () - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:Result<'V>, next:SeqComponent<'U,'V>) = inherit SeqComponent<'First,'V>(next) @@ -1534,9 +1510,7 @@ namespace Microsoft.FSharp.Collections [] let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = checkNonNull "source1" source1 - match source1 with - | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose (Composer.Seq.Map2FirstFactory (f, source2))) - | _ -> source2 |> seqFactory (Composer.Seq.Map2SecondFactory (f, source1)) + source1 |> seqFactory (SeqComposer.Map2Factory (f, source2)) [] let map3 f source1 source2 source3 = From be5b83ba67e3b547c761686309c07516c055c9cf Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 10:15:33 +1100 Subject: [PATCH 136/286] Seq.unfold --- src/fsharp/FSharp.Core/seq.fs | 108 ++++++++++++++++------------------ 1 file changed, 52 insertions(+), 56 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 79059f022e5..573974b26e3 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -69,59 +69,6 @@ namespace Microsoft.FSharp.Collections if index = 0 then e.Current else nth (index-1) e - [] - type MapEnumeratorState = - | NotStarted - | InProcess - | Finished - - [] - type MapEnumerator<'T> () = - let mutable state = NotStarted - [] - val mutable private curr : 'T - - member this.GetCurrent () = - match state with - | NotStarted -> notStarted() - | Finished -> alreadyFinished() - | InProcess -> () - this.curr - - abstract DoMoveNext : byref<'T> -> bool - abstract Dispose : unit -> unit - - interface IEnumerator<'T> with - member this.Current = this.GetCurrent() - - interface IEnumerator with - member this.Current = box(this.GetCurrent()) - member this.MoveNext () = - state <- InProcess - if this.DoMoveNext(&this.curr) then - true - else - state <- Finished - false - member this.Reset() = noReset() - interface System.IDisposable with - member this.Dispose() = this.Dispose() - - let unfold f x : IEnumerator<_> = - let state = ref x - upcast - { new MapEnumerator<_>() with - member this.DoMoveNext curr = - match f !state with - | None -> false - | Some(r,s) -> - curr <- r - state := s - true - member this.Dispose() = () - } - - let readAndClear r = lock r (fun () -> match !r with None -> None | Some _ as res -> r := None; res) @@ -1177,6 +1124,56 @@ namespace Microsoft.FSharp.Collections fold initialState alist + module Unfold = + type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) + + let mutable current = state + + let rec moveNext () = + match generator current with + | None -> false + | Some (item, nextState) -> + current <- nextState + if seqComponent.ProcessNext item then + true + else + moveNext () + + interface IEnumerator with + member __.MoveNext () = + signal.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:SeqComponentFactory<'T,'U>) = + inherit Enumerable.EnumerableBase<'U>() + + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (Tail result), result)) + + override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = + Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory (current, next))) + + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = + let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + + let result = Result<'U> () + let components = current.Create result (Tail result) + + let rec fold state current = + match result.Halted, generator current with + | true, _ + | false, None -> state + | false, Some (item, next) -> + if components.ProcessNext item then + fold (folder'.Invoke (state, result.Current)) next + else + fold state next + + fold initialState 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. @@ -1269,7 +1266,7 @@ namespace Microsoft.FSharp.Collections let upto lastOption f = match lastOption with - | Some b when b<0 -> Empty() // a request for -ve length returns empty sequence + | 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) @@ -1368,8 +1365,7 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : seq<'T> = - Composer.Seq.unfold generator state - |> Upcast.enumerable + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Unfold.Enumerable<'T,'T,'State>(generator, state, SeqComposer.MapFactory id)) [] let empty<'T> = (EmptyEnumerable :> seq<'T>) From 69169394b552d28952925e058c9a4aa6043e7552 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 10:35:24 +1100 Subject: [PATCH 137/286] Added an IdentityFactory Identity can be used to wrap basic containers into SeqComposer compatible types, but can safely be removed when composing the components. --- src/fsharp/FSharp.Core/seq.fs | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 573974b26e3..9e8611ff507 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -523,11 +523,24 @@ namespace Microsoft.FSharp.Collections type [] SeqComponentFactory<'T,'U> () = abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V> + abstract IsIdentity : bool - and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = + default __.IsIdentity = false + + and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = inherit SeqComponentFactory<'T,'V> () override __.Create<'W> (result:Result<'W>) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create result (second.Create result next) + static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = + let castToTV (factory:obj) = + match factory with + | :? SeqComponentFactory<'T,'V> as result -> result + | _ -> failwith "library implementation error: they types must match when paired with identity" + + if first.IsIdentity then castToTV second + elif second.IsIdentity then castToTV first + else upcast ComposedFactory(first, second) + and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next) @@ -548,6 +561,11 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'T> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter + and IdentityFactory<'T> () = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateMap id + override __.IsIdentity = true + and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map @@ -941,7 +959,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1054,7 +1072,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory.Combine current next)) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1104,7 +1122,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1154,7 +1172,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (Tail result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1239,7 +1257,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next))) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1365,7 +1383,7 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : seq<'T> = - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Unfold.Enumerable<'T,'T,'State>(generator, state, SeqComposer.MapFactory id)) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Unfold.Enumerable<'T,'T,'State>(generator, state, SeqComposer.IdentityFactory ())) [] let empty<'T> = (EmptyEnumerable :> seq<'T>) From dd0937216495bad95eea72c60f0a6acf9361e17a Mon Sep 17 00:00:00 2001 From: liboz Date: Fri, 14 Oct 2016 20:13:25 -0400 Subject: [PATCH 138/286] Made map2 more complex (reverted from commit ceaed6cd7cb9f842fb9b47440bff7cedeed74629) Also removed some extra null checks --- src/fsharp/FSharp.Core/seq.fs | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 9e8611ff507..d4fdc4e506d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -570,9 +570,13 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map - and Map2Factory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = + and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map2 (map, input2, result, next) + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map2First (map, input2, result, next) + + and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = + inherit SeqComponentFactory<'Second,'U> () + override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'Second,'V> = upcast Map2Second (map, input1, result, next) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () @@ -698,7 +702,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -718,6 +722,26 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) = + inherit SeqComponent<'Second,'V>(next) + + let input1 = enumerable1.GetEnumerator () + let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map + + override __.ProcessNext (input:'Second) : bool = + if input1.MoveNext () then + Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) + else + result.StopFurtherProcessing () + false + + interface ISeqComponent with + override __.OnDispose () = + try + input1.Dispose () + finally + (Helpers.upcastISeqComponent next).OnDispose () + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:Result<'V>, next:SeqComponent<'U,'V>) = inherit SeqComponent<'First,'V>(next) @@ -1523,8 +1547,9 @@ namespace Microsoft.FSharp.Collections [] let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = - checkNonNull "source1" source1 - source1 |> seqFactory (SeqComposer.Map2Factory (f, source2)) + match source1 with + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2)) + | _ -> source2 |> seqFactory (SeqComposer.Map2SecondFactory (f, source1)) [] let map3 f source1 source2 source3 = From 892e4f437d95a578414361fc422055aa67040ac3 Mon Sep 17 00:00:00 2001 From: liboz Date: Fri, 14 Oct 2016 20:31:55 -0400 Subject: [PATCH 139/286] fixed to removing the right null check --- src/fsharp/FSharp.Core/seq.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index d4fdc4e506d..9ca59a96907 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1547,6 +1547,7 @@ namespace Microsoft.FSharp.Collections [] let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = + checkNonNull "source1" source1 match source1 with | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2)) | _ -> source2 |> seqFactory (SeqComposer.Map2SecondFactory (f, source1)) From a155d1b6b08dcfd11dfd4b07ccfe036b5905e550 Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 15 Oct 2016 00:06:36 -0400 Subject: [PATCH 140/286] seq.tail and a fix to takewhile to use avoidtailcall --- src/fsharp/FSharp.Core/seq.fs | 62 +++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 9ca59a96907..0056bf96263 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -610,6 +610,10 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'T> () override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next) + and TailFactory<'T> () = + inherit SeqComponentFactory<'T,'T> () + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Tail<'T,'V> (next) + and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Truncate (count, result, next) @@ -882,7 +886,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if predicate input then - next.ProcessNext input + Helpers.avoidTailCall (next.ProcessNext input) else result.StopFurtherProcessing () false @@ -894,6 +898,24 @@ namespace Microsoft.FSharp.Collections result.Current <- input true + and Tail<'T, 'V> (next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + let mutable first = true + + override __.ProcessNext (input:'T) : bool = + if first then + first <- false + false + else + Helpers.avoidTailCall (next.ProcessNext input) + + interface ISeqComponent with + override this.OnComplete () = + if first then + invalidArg "source" (SR.GetString(SR.notEnoughElements)) + (Helpers.upcastISeqComponent next).OnComplete () + and Truncate<'T,'V> (truncateCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -980,7 +1002,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) @@ -991,7 +1013,7 @@ namespace Microsoft.FSharp.Collections let enumerator = enumerable.GetEnumerator () let result = Result<'U> () - let components = current.Create result (Tail result) + let components = current.Create result (Tail<'U> result) let mutable state = initialState while (not result.Halted) && (enumerator.MoveNext ()) do @@ -1093,7 +1115,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory.Combine current next)) @@ -1103,7 +1125,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = 0 let result = Result<'U> () - let components = current.Create result (Tail result) + let components = current.Create result (Tail<'U> result) let mutable state = initialState while (not result.Halted) && (idx < array.Length) do @@ -1143,7 +1165,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) @@ -1152,7 +1174,7 @@ namespace Microsoft.FSharp.Collections let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let result = Result<'U> () - let components = current.Create result (Tail result) + let components = current.Create result (Tail<'U> result) let rec fold state lst = match result.Halted, lst with @@ -1193,7 +1215,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (Tail<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) @@ -1202,7 +1224,7 @@ namespace Microsoft.FSharp.Collections let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let result = Result<'U> () - let components = current.Create result (Tail result) + let components = current.Create result (Tail<'U> result) let rec fold state current = match result.Halted, generator current with @@ -1278,7 +1300,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) @@ -1287,7 +1309,7 @@ namespace Microsoft.FSharp.Collections let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let result = Result<'U> () - let components = current.Create result (Tail result) + let components = current.Create result (Tail<'U> result) let mutable idx = -1 let terminatingIdx = getTerminatingIdx count @@ -2281,23 +2303,7 @@ namespace Microsoft.FSharp.Collections [] let tail (source: seq<'T>) = - source |> seqFactory (Composer.Seq.TailFactory ()) - - [] - let tryLast (source : seq<_>) = - source - |> foreach (fun _ -> - { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values(true, Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun tried -> - if tried.Value._1 then - None - else - Some tried.Value._2 + source |> seqFactory (SeqComposer.TailFactory ()) [] let last (source : seq<_>) = From 172abef501c81994a8647c674a1ba9f9de159466 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 16:57:55 +1100 Subject: [PATCH 141/286] Seq.ofArray --- src/fsharp/FSharp.Core/seq.fs | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 0056bf96263..1c7e2394062 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -100,31 +100,6 @@ namespace Microsoft.FSharp.Collections interface System.IDisposable with member x.Dispose() = dispose() } - [] - type ArrayEnumerator<'T>(arr: 'T array) = - let mutable curr = -1 - let mutable len = arr.Length - member x.Get() = - if curr >= 0 then - if curr >= len then alreadyFinished() - else arr.[curr] - else - notStarted() - interface IEnumerator<'T> with - member x.Current = x.Get() - interface System.Collections.IEnumerator with - member x.MoveNext() = - if curr >= len then false - else - curr <- curr + 1 - (curr < len) - member x.Current = box(x.Get()) - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = () - - let ofArray arr = (new ArrayEnumerator<'T>(arr) :> IEnumerator<'T>) - [] type Singleton<'T>(v:'T) = let mutable started = false @@ -1765,7 +1740,7 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source : 'T array) = checkNonNull "source" source - Upcast.enumerable (Composer.Seq.Array.createId source) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory ())) [] let toArray (source : seq<'T>) = From c407040dd9c4a90c65c0dbbc302ebe951656aee5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 18:25:43 +1100 Subject: [PATCH 142/286] Seq.rev --- src/fsharp/FSharp.Core/seq.fs | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 1c7e2394062..770e1b67b84 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1062,10 +1062,19 @@ namespace Microsoft.FSharp.Collections state module Array = - type Enumerator<'T,'U>(array:array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U>(lazyArray:Lazy>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable idx = 0 + let mutable array = Unchecked.defaultof<_> + + let mutable initMoveNext = Unchecked.defaultof<_> + do + initMoveNext <- + fun () -> + result.SeqState <- SeqProcessNextStates.InProcess + array <- lazyArray.Value + initMoveNext <- ignore let rec moveNext () = if (not result.Halted) && idx < array.Length then @@ -1081,19 +1090,22 @@ namespace Microsoft.FSharp.Collections interface IEnumerator with member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess + initMoveNext () moveNext () - type Enumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) = + type Enumerable<'T,'U>(lazyArray:Lazy>, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() + new(array:array<'T>, current:SeqComponentFactory<'T,'U>) = + Enumerable<'T,'U>((Lazy.CreateFromValue array), current) + interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(lazyArray, current.Create result (Tail<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory.Combine current next)) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(lazyArray, ComposedFactory.Combine current next)) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1102,6 +1114,7 @@ namespace Microsoft.FSharp.Collections let result = Result<'U> () let components = current.Create result (Tail<'U> result) + let array = lazyArray.Value let mutable state = initialState while (not result.Halted) && (idx < array.Length) do if components.ProcessNext array.[idx] then @@ -2310,11 +2323,12 @@ namespace Microsoft.FSharp.Collections [] let rev source = checkNonNull "source" source - let delayedReverse () = - let array = source |> toArray + let reverseViaArray = lazy ( + let array = source |> toArray Array.Reverse array - array - Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedReverse) + array + ) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(reverseViaArray, SeqComposer.IdentityFactory ())) [] let permute f (source:seq<_>) = From b302e24bddf398bee65ae3d0265fb37aede68fff Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 18:48:47 +1100 Subject: [PATCH 143/286] Added brackets to disambiguate Lazy --- src/fsharp/FSharp.Core/seq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 770e1b67b84..ccbd2faac45 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1097,7 +1097,7 @@ namespace Microsoft.FSharp.Collections inherit Enumerable.EnumerableBase<'U>() new(array:array<'T>, current:SeqComponentFactory<'T,'U>) = - Enumerable<'T,'U>((Lazy.CreateFromValue array), current) + Enumerable<'T,'U>((Lazy<_>.CreateFromValue array), current) interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = From bee4f5643bf2198bc7bb7693bf213f3688157313 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 19:02:09 +1100 Subject: [PATCH 144/286] Seq.permute --- src/fsharp/FSharp.Core/seq.fs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ccbd2faac45..df547ed9c6b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2323,21 +2323,14 @@ namespace Microsoft.FSharp.Collections [] let rev source = checkNonNull "source" source - let reverseViaArray = lazy ( - let array = source |> toArray - Array.Reverse array - array - ) - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(reverseViaArray, SeqComposer.IdentityFactory ())) + let lazyReverseViaArray = lazy (let array = source |> toArray in Array.Reverse array; array) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazyReverseViaArray, SeqComposer.IdentityFactory ())) [] let permute f (source:seq<_>) = checkNonNull "source" source - let delayedPermute () = - source - |> toArray - |> Array.permute f - Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedPermute) + let lazyPermuteViaArray = lazy (source |> toArray |> Array.permute f) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazyPermuteViaArray, SeqComposer.IdentityFactory ())) [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = From e4591c31007a5a12ee9a2acca8d96d52452b71f8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 19:07:03 +1100 Subject: [PATCH 145/286] Seq.sort(By|With|ByDescending|Descending)? --- src/fsharp/FSharp.Core/seq.fs | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index df547ed9c6b..8136db9d992 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1999,29 +1999,20 @@ namespace Microsoft.FSharp.Collections [] let sortBy keyf source = checkNonNull "source" source - let delayedSort () = - let array = source |> toArray - Array.stableSortInPlaceBy keyf array - array - Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedSort) + let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlaceBy keyf array; array) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazySortViaArray, SeqComposer.IdentityFactory ())) [] let sort source = checkNonNull "source" source - let delayedSort () = - let array = source |> toArray - Array.stableSortInPlace array - array - Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedSort) + let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlace array; array) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazySortViaArray, SeqComposer.IdentityFactory ())) [] let sortWith f source = checkNonNull "source" source - let delayedSort () = - let array = source |> toArray - Array.stableSortInPlaceWith f array - array - Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedSort) + let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlaceWith f array; array) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazySortViaArray, SeqComposer.IdentityFactory ())) [] let inline sortByDescending keyf source = From adb01d8142359872b401b3c01a5587bc1823c07f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 19:24:50 +1100 Subject: [PATCH 146/286] Factory helper create methods for less clutter --- src/fsharp/FSharp.Core/seq.fs | 39 ++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 8136db9d992..ee7cb639c90 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1061,6 +1061,9 @@ namespace Microsoft.FSharp.Collections state + let create enumerable current = + Helpers.upcastEnumerable (Enumerable(enumerable, current)) + module Array = type Enumerator<'T,'U>(lazyArray:Lazy>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) @@ -1096,9 +1099,6 @@ namespace Microsoft.FSharp.Collections type Enumerable<'T,'U>(lazyArray:Lazy>, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() - new(array:array<'T>, current:SeqComponentFactory<'T,'U>) = - Enumerable<'T,'U>((Lazy<_>.CreateFromValue array), current) - interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1123,6 +1123,18 @@ namespace Microsoft.FSharp.Collections state + let createLazy (lazyArray:Lazy>) (current:SeqComponentFactory<'T,'U>) = + Helpers.upcastEnumerable (Enumerable(lazyArray, current)) + + let create (array:array<'T>) (current:SeqComponentFactory<'T,'U>) = + createLazy (Lazy<_>.CreateFromValue array) current + + let createLazyId (lazyArray:Lazy>) = + createLazy lazyArray (IdentityFactory ()) + + let createId (array:array<'T>) = + create array (IdentityFactory ()) + module List = type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) @@ -1176,6 +1188,9 @@ namespace Microsoft.FSharp.Collections fold initialState alist + let create alist current = + Helpers.upcastEnumerable (Enumerable(alist, current)) + module Unfold = type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) @@ -1527,9 +1542,9 @@ namespace Microsoft.FSharp.Collections checkNonNull "source" source match source with | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose createSeqComponent - | :? array<'T> as a -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<_,_>(a, createSeqComponent)) - | :? list<'T> as a -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.List.Enumerable<_,_>(a, createSeqComponent)) - | _ -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Enumerable.Enumerable<_,_>(source, createSeqComponent)) + | :? array<'T> as a -> SeqComposer.Array.create a createSeqComponent + | :? list<'T> as a -> SeqComposer.List.create a createSeqComponent + | _ -> SeqComposer.Enumerable.create source createSeqComponent [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = @@ -1753,7 +1768,7 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source : 'T array) = checkNonNull "source" source - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory ())) + SeqComposer.Array.createId source [] let toArray (source : seq<'T>) = @@ -2000,19 +2015,19 @@ namespace Microsoft.FSharp.Collections let sortBy keyf source = checkNonNull "source" source let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlaceBy keyf array; array) - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazySortViaArray, SeqComposer.IdentityFactory ())) + SeqComposer.Array.createLazyId lazySortViaArray [] let sort source = checkNonNull "source" source let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlace array; array) - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazySortViaArray, SeqComposer.IdentityFactory ())) + SeqComposer.Array.createLazyId lazySortViaArray [] let sortWith f source = checkNonNull "source" source let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlaceWith f array; array) - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazySortViaArray, SeqComposer.IdentityFactory ())) + SeqComposer.Array.createLazyId lazySortViaArray [] let inline sortByDescending keyf source = @@ -2315,13 +2330,13 @@ namespace Microsoft.FSharp.Collections let rev source = checkNonNull "source" source let lazyReverseViaArray = lazy (let array = source |> toArray in Array.Reverse array; array) - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazyReverseViaArray, SeqComposer.IdentityFactory ())) + SeqComposer.Array.createLazyId lazyReverseViaArray [] let permute f (source:seq<_>) = checkNonNull "source" source let lazyPermuteViaArray = lazy (source |> toArray |> Array.permute f) - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Array.Enumerable<'T,'T>(lazyPermuteViaArray, SeqComposer.IdentityFactory ())) + SeqComposer.Array.createLazyId lazyPermuteViaArray [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = From 22e10203874687544683b866a315d09c795d92c5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 05:10:24 +1100 Subject: [PATCH 147/286] Replaced Lazy<'T> with (unit->'T) The use of lazy changed the seq's funcitonality, as it would have only been calculated once, even if the sequence was iterated again. --- src/fsharp/FSharp.Core/seq.fs | 57 ++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ee7cb639c90..f7be46a50fa 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1065,7 +1065,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (Enumerable(enumerable, current)) module Array = - type Enumerator<'T,'U>(lazyArray:Lazy>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable idx = 0 @@ -1076,7 +1076,7 @@ namespace Microsoft.FSharp.Collections initMoveNext <- fun () -> result.SeqState <- SeqProcessNextStates.InProcess - array <- lazyArray.Value + array <- delayedArray () initMoveNext <- ignore let rec moveNext () = @@ -1096,16 +1096,16 @@ namespace Microsoft.FSharp.Collections initMoveNext () moveNext () - type Enumerable<'T,'U>(lazyArray:Lazy>, current:SeqComponentFactory<'T,'U>) = + type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(lazyArray, current.Create result (Tail<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (Tail<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(lazyArray, ComposedFactory.Combine current next)) + Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1114,7 +1114,7 @@ namespace Microsoft.FSharp.Collections let result = Result<'U> () let components = current.Create result (Tail<'U> result) - let array = lazyArray.Value + let array = delayedArray () let mutable state = initialState while (not result.Halted) && (idx < array.Length) do if components.ProcessNext array.[idx] then @@ -1123,14 +1123,14 @@ namespace Microsoft.FSharp.Collections state - let createLazy (lazyArray:Lazy>) (current:SeqComponentFactory<'T,'U>) = - Helpers.upcastEnumerable (Enumerable(lazyArray, current)) + let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = + Helpers.upcastEnumerable (Enumerable(delayedArray, current)) let create (array:array<'T>) (current:SeqComponentFactory<'T,'U>) = - createLazy (Lazy<_>.CreateFromValue array) current + createDelayed (fun () -> array) current - let createLazyId (lazyArray:Lazy>) = - createLazy lazyArray (IdentityFactory ()) + let createDelayedId (delayedArray:unit -> array<'T>) = + createDelayed delayedArray (IdentityFactory ()) let createId (array:array<'T>) = create array (IdentityFactory ()) @@ -2014,20 +2014,29 @@ namespace Microsoft.FSharp.Collections [] let sortBy keyf source = checkNonNull "source" source - let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlaceBy keyf array; array) - SeqComposer.Array.createLazyId lazySortViaArray + let delayedSort () = + let array = source |> toArray + Array.stableSortInPlaceBy keyf array + array + SeqComposer.Array.createDelayedId delayedSort [] let sort source = checkNonNull "source" source - let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlace array; array) - SeqComposer.Array.createLazyId lazySortViaArray + let delayedSort () = + let array = source |> toArray + Array.stableSortInPlace array + array + SeqComposer.Array.createDelayedId delayedSort [] let sortWith f source = checkNonNull "source" source - let lazySortViaArray = lazy (let array = source |> toArray in Array.stableSortInPlaceWith f array; array) - SeqComposer.Array.createLazyId lazySortViaArray + let delayedSort () = + let array = source |> toArray + Array.stableSortInPlaceWith f array + array + SeqComposer.Array.createDelayedId delayedSort [] let inline sortByDescending keyf source = @@ -2329,14 +2338,20 @@ namespace Microsoft.FSharp.Collections [] let rev source = checkNonNull "source" source - let lazyReverseViaArray = lazy (let array = source |> toArray in Array.Reverse array; array) - SeqComposer.Array.createLazyId lazyReverseViaArray + let delayedReverse () = + let array = source |> toArray + Array.Reverse array + array + SeqComposer.Array.createDelayedId delayedReverse [] let permute f (source:seq<_>) = checkNonNull "source" source - let lazyPermuteViaArray = lazy (source |> toArray |> Array.permute f) - SeqComposer.Array.createLazyId lazyPermuteViaArray + let delayedPermute () = + source + |> toArray + |> Array.permute f + SeqComposer.Array.createDelayedId delayedPermute [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = From e3bc57dddb217ba14edb06c0c91a68f02473098a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 05:15:23 +1100 Subject: [PATCH 148/286] Renamed Tail to SetResult to disambiguate --- src/fsharp/FSharp.Core/seq.fs | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index f7be46a50fa..2c8d74d33ca 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -866,13 +866,6 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing () false - and Tail<'T> (result:Result<'T>) = - inherit SeqComponent<'T,'T>(seqComponentTail) - - override __.ProcessNext (input:'T) : bool = - result.Current <- input - true - and Tail<'T, 'V> (next:SeqComponent<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -908,6 +901,14 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing () false + // SetResult<> is used at the end of the chain of SeqComponents to assign the final value + type SetResult<'T> (result:Result<'T>) = + inherit SeqComponent<'T,'T>(seqComponentTail) + + override __.ProcessNext (input:'T) : bool = + result.Current <- input + true + module Enumerable = [] type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) = @@ -977,7 +978,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) @@ -988,7 +989,7 @@ namespace Microsoft.FSharp.Collections let enumerator = enumerable.GetEnumerator () let result = Result<'U> () - let components = current.Create result (Tail<'U> result) + let components = current.Create result (SetResult<'U> result) let mutable state = initialState while (not result.Halted) && (enumerator.MoveNext ()) do @@ -1102,7 +1103,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (Tail<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) @@ -1112,7 +1113,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = 0 let result = Result<'U> () - let components = current.Create result (Tail<'U> result) + let components = current.Create result (SetResult<'U> result) let array = delayedArray () let mutable state = initialState @@ -1165,7 +1166,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) @@ -1174,7 +1175,7 @@ namespace Microsoft.FSharp.Collections let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let result = Result<'U> () - let components = current.Create result (Tail<'U> result) + let components = current.Create result (SetResult<'U> result) let rec fold state lst = match result.Halted, lst with @@ -1218,7 +1219,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (Tail<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (SetResult<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) @@ -1227,7 +1228,7 @@ namespace Microsoft.FSharp.Collections let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let result = Result<'U> () - let components = current.Create result (Tail<'U> result) + let components = current.Create result (SetResult<'U> result) let rec fold state current = match result.Halted, generator current with @@ -1303,7 +1304,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (SetResult<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) @@ -1312,7 +1313,7 @@ namespace Microsoft.FSharp.Collections let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let result = Result<'U> () - let components = current.Create result (Tail<'U> result) + let components = current.Create result (SetResult<'U> result) let mutable idx = -1 let terminatingIdx = getTerminatingIdx count From 30e61960bb8389fc87a7d0cce81ad33e0b646e88 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 06:11:37 +1100 Subject: [PATCH 149/286] Added Iter --- src/fsharp/FSharp.Core/seq.fs | 91 ++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 2c8d74d33ca..70daab6dc28 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -931,9 +931,10 @@ namespace Microsoft.FSharp.Collections | _ -> failwith "library implementation error: all states should have been handled" and [] EnumerableBase<'T> () = - abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> - abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> + abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> + abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State + abstract member Iter : f:('T->unit) -> unit default this.Append source = Helpers.upcastEnumerable (AppendEnumerable [this; source]) @@ -983,6 +984,16 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) + override this.Iter (f:'U->unit) : unit = + let enumerator = enumerable.GetEnumerator () + let result = Result<'U> () + + let components = current.Create result (SetResult<'U> result) + + while (not result.Halted) && (enumerator.MoveNext ()) do + if components.ProcessNext (enumerator.Current) then + f result.Current + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1050,6 +1061,13 @@ namespace Microsoft.FSharp.Collections override this.Append source = Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) + override this.Iter (f:'T->unit) : unit = + let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) + let enumerator = enumerable.GetEnumerator () + + while enumerator.MoveNext () do + f enumerator.Current + override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1108,6 +1126,17 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) + override this.Iter (f:'U->unit) : unit = + let mutable idx = 0 + let result = Result<'U> () + let components = current.Create result (SetResult<'U> result) + + let array = delayedArray () + while (not result.Halted) && (idx < array.Length) do + if components.ProcessNext array.[idx] then + f result.Current + idx <- idx + 1 + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1171,6 +1200,23 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) + override this.Iter (f:'U->unit) : unit = + let result = Result<'U> () + let components = current.Create result (SetResult<'U> result) + + let rec fold lst = + match result.Halted, lst with + | true, _ + | false, [] -> () + | false, hd :: tl -> + if components.ProcessNext hd then + f result.Current + fold tl + else + fold tl + + fold alist + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1224,6 +1270,23 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) + override this.Iter (f:'U->unit) : unit = + let result = Result<'U> () + let components = current.Create result (SetResult<'U> result) + + let rec fold current = + match result.Halted, generator current with + | true, _ + | false, None -> () + | false, Some (item, next) -> + if components.ProcessNext item then + f result.Current + fold next + else + fold next + + fold state + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1309,6 +1372,24 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) + override this.Iter (iter:'U->unit) : unit = + let result = Result<'U> () + let components = current.Create result (SetResult<'U> result) + + let mutable idx = -1 + let terminatingIdx = getTerminatingIdx count + + let mutable maybeSkipping = true + + while (not result.Halted) && (idx < terminatingIdx) do + if maybeSkipping then + maybeSkipping <- components.Skipping () + + if (not maybeSkipping) && (components.ProcessNext (f (idx+1))) then + iter result.Current + + idx <- idx + 1 + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1395,6 +1476,12 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) + override this.Iter (f:'T->unit): unit = + let enumerator = (Helpers.upcastEnumerable this).GetEnumerator () + + while enumerator.MoveNext () do + f enumerator.Current + override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder From abff61f185dae0f4c396f094fa0e507d2d7329a8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 06:16:48 +1100 Subject: [PATCH 150/286] Seq.iter & Seq.average --- src/fsharp/FSharp.Core/seq.fs | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 70daab6dc28..0fa79a25317 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1537,7 +1537,14 @@ namespace Microsoft.FSharp.Collections [] let iter f (source : seq<'T>) = - Composer.Seq.iter f (toComposer source) + checkNonNull "source" source + checkNonNull "source" source + match source with + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Iter f + | _ -> + use e = source.GetEnumerator() + while e.MoveNext() do + f e.Current [] let tryHead (source : seq<_>) = @@ -2193,13 +2200,15 @@ namespace Microsoft.FSharp.Collections [] let inline average (source: seq< ^a>) : ^a = - source - |> foreach (fun _ -> - { new Composer.Core.Folder<'a, Composer.Core.Values<'a, int>> (Composer.Core.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with - override this.ProcessNext value = - this.Value._1 <- Checked.(+) this.Value._1 value - this.Value._2 <- this.Value._2 + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + checkNonNull "source" source + let mutable acc = LanguagePrimitives.GenericZero< ^a> + let mutable count = 0 + source |> iter (fun current -> + acc <- Checked.(+) acc current + count <- count + 1) + if count = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + LanguagePrimitives.DivideByInt< ^a> acc count member this.OnComplete _ = if this.Value._2 = 0 then From 130d04f1f6a5e56787d83a513c0a1b40ae20d4aa Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 15 Oct 2016 11:34:13 -0400 Subject: [PATCH 151/286] making identity more efficient --- src/fsharp/FSharp.Core/seq.fs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 0fa79a25317..4e1648fae9f 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -538,7 +538,7 @@ namespace Microsoft.FSharp.Collections and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateMap id + override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Identity (next) override __.IsIdentity = true and MapFactory<'T,'U> (map:'T->'U) = @@ -673,6 +673,12 @@ namespace Microsoft.FSharp.Collections else false + and Identity<'T,'V> (next:SeqComponent<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + override __.ProcessNext (input:'T) : bool = + Helpers.avoidTailCall (next.ProcessNext input) + and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) = inherit SeqComponent<'T,'V>(next) From 81611476f782292778b00f5d7b518c48f8a327e8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 10:09:42 +1100 Subject: [PATCH 152/286] Updated NoNeedToTailcall for Seq.iter changes --- .../analyses/tailcalls.NoNeedToTailcall.output.test.bsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl index 5f4e677efc6..0f49d38a8dc 100644 --- a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl +++ b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl @@ -41,7 +41,7 @@ value simpleLibraryCall9 at line 63 does not make a critical tailcall value simpleLibraryCall10 at line 65 does not make a critical tailcall value simpleLibraryCall11 at line 66 does not make a critical tailcall value simpleLibraryCall12 at line 67 does not make a critical tailcall -value simpleLibraryCall13 at line 68 does not make a critical tailcall +value simpleLibraryCall13 at line 68 may make a critical tailcall value simpleLibraryUse14 at line 69 does not make a critical tailcall value simpleLibraryUse15 at line 70 does not make a critical tailcall value simpleLibraryUse16 at line 71 does not make a critical tailcall From 4fbcb513495d1dc63711ac8b7b270855c81f7e3c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 18:11:25 +1100 Subject: [PATCH 153/286] Added OnComplete calls to Iter and Folds --- src/fsharp/FSharp.Core/seq.fs | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 4e1648fae9f..4016b2dc4fc 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1000,6 +1000,9 @@ namespace Microsoft.FSharp.Collections if components.ProcessNext (enumerator.Current) then f result.Current + (Helpers.upcastISeqComponent components).OnComplete () + + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1012,6 +1015,8 @@ namespace Microsoft.FSharp.Collections while (not result.Halted) && (enumerator.MoveNext ()) do if components.ProcessNext (enumerator.Current) then state <- folder'.Invoke (state, result.Current) + + (Helpers.upcastISeqComponent components).OnComplete () state @@ -1143,6 +1148,9 @@ namespace Microsoft.FSharp.Collections f result.Current idx <- idx + 1 + (Helpers.upcastISeqComponent components).OnComplete () + + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1157,6 +1165,8 @@ namespace Microsoft.FSharp.Collections state <- folder'.Invoke (state, result.Current) idx <- idx + 1 + (Helpers.upcastISeqComponent components).OnComplete () + state let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = @@ -1213,7 +1223,7 @@ namespace Microsoft.FSharp.Collections let rec fold lst = match result.Halted, lst with | true, _ - | false, [] -> () + | false, [] -> (Helpers.upcastISeqComponent components).OnComplete () | false, hd :: tl -> if components.ProcessNext hd then f result.Current @@ -1232,7 +1242,9 @@ namespace Microsoft.FSharp.Collections let rec fold state lst = match result.Halted, lst with | true, _ - | false, [] -> state + | false, [] -> + (Helpers.upcastISeqComponent components).OnComplete () + state | false, hd :: tl -> if components.ProcessNext hd then fold (folder'.Invoke (state, result.Current)) tl @@ -1283,7 +1295,7 @@ namespace Microsoft.FSharp.Collections let rec fold current = match result.Halted, generator current with | true, _ - | false, None -> () + | false, None -> (Helpers.upcastISeqComponent components).OnComplete () | false, Some (item, next) -> if components.ProcessNext item then f result.Current @@ -1302,7 +1314,9 @@ namespace Microsoft.FSharp.Collections let rec fold state current = match result.Halted, generator current with | true, _ - | false, None -> state + | false, None -> + (Helpers.upcastISeqComponent components).OnComplete () + state | false, Some (item, next) -> if components.ProcessNext item then fold (folder'.Invoke (state, result.Current)) next @@ -1396,6 +1410,8 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 + (Helpers.upcastISeqComponent components).OnComplete () + override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -1416,6 +1432,8 @@ namespace Microsoft.FSharp.Collections state <- folder'.Invoke (state, result.Current) idx <- idx + 1 + + (Helpers.upcastISeqComponent components).OnComplete () state From 455b871102f531684b9893a51d5250168f17592a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 17 Oct 2016 20:17:23 +1100 Subject: [PATCH 154/286] Experimental ForEach Currently this is only implemented on Array. This adds some public surface to the SeqComposer which may be removed. --- src/fsharp/FSharp.Core/seq.fs | 237 ++++++++++++++++++++++----------- src/fsharp/FSharp.Core/seq.fsi | 22 +++ 2 files changed, 182 insertions(+), 77 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 4016b2dc4fc..d78dc1fd40e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -453,9 +453,6 @@ namespace Microsoft.FSharp.Collections [] [] module Seq = -// type ISeqEnumerable<'T> = -// abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State - module SeqComposer = open IEnumerator @@ -463,6 +460,32 @@ namespace Microsoft.FSharp.Collections abstract OnComplete : unit -> unit abstract OnDispose : unit -> unit + type ISeqPipeline = + abstract StopFurtherProcessing : unit -> unit + + [] + type SeqConsumer<'T,'U> () = + abstract ProcessNext : input:'T -> bool + + interface ISeqComponent with + member __.OnComplete() = () + member __.OnDispose() = () + + type Fold<'T> (folder:'T->'T->'T, initialState:'T) = + inherit SeqConsumer<'T,'T>() + + let folder = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(folder) + + let mutable folded = initialState + override __.ProcessNext input = + folded <- folder.Invoke (folded, input) + true + member __.Folded = folded + + [] + type SeqEnumerable<'T>() = + abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:(ISeqPipeline->'a) -> 'a + module Helpers = // 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 @@ -476,20 +499,6 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) - type SeqProcessNextStates = - | InProcess = 0 - | NotStarted = 1 - | Finished = 2 - - type Result<'T>() = - let mutable halted = false - - member val SeqState = SeqProcessNextStates.NotStarted with get, set - - member __.StopFurtherProcessing () = halted <- true - member __.Halted = halted - - member val Current = Unchecked.defaultof<'T> with get, set let seqComponentTail = { new ISeqComponent with @@ -497,14 +506,15 @@ namespace Microsoft.FSharp.Collections member __.OnDispose() = () } type [] SeqComponentFactory<'T,'U> () = - abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V> + abstract Create<'V> : ISeqPipeline -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> abstract IsIdentity : bool default __.IsIdentity = false and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = inherit SeqComponentFactory<'T,'V> () - override __.Create<'W> (result:Result<'W>) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create result (second.Create result next) + override __.Create<'W> (result:ISeqPipeline) (next:SeqConsumer<'V,'W>) : SeqConsumer<'T,'W> = + first.Create result (second.Create result next) static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = let castToTV (factory:obj) = @@ -518,83 +528,89 @@ namespace Microsoft.FSharp.Collections and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Choose (filter, next) and DistinctFactory<'T when 'T: equality> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Distinct (next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast DistinctBy (keyFunction, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Except (itemsToExclude, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = + match next with + | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter + | _ -> upcast Filter (filter, next) and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Identity (next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Identity (next) override __.IsIdentity = true and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = + match next with + | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map + | _ -> upcast Map<_,_,_> (map, next) and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map2First (map, input2, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = inherit SeqComponentFactory<'Second,'U> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'Second,'V> = upcast Map2Second (map, input1, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map3 (map, input2, input3, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next) and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Mapi2 (map, input2, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T*'T,'V>) : SeqConsumer<'T,'V> = upcast Pairwise next and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (predicate, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (predicate, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Take (count, result, next) and TailFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Tail<'T,'V> (next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Truncate (count, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next) and [] SeqComponent<'T,'U> (next:ISeqComponent) = - abstract ProcessNext : input:'T -> bool + inherit SeqConsumer<'T,'U>() // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip // and it can only do it at the start of a sequence @@ -612,7 +628,7 @@ namespace Microsoft.FSharp.Collections default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) - and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqComponent<'U,'V>) = + and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -620,7 +636,7 @@ namespace Microsoft.FSharp.Collections | Some value -> Helpers.avoidTailCall (next.ProcessNext value) | None -> false - and Distinct<'T,'V when 'T: equality> (next:SeqComponent<'T,'V>) = + and Distinct<'T,'V when 'T: equality> (next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) @@ -631,7 +647,7 @@ namespace Microsoft.FSharp.Collections else false - and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqComponent<'T,'V>) = + and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) @@ -642,7 +658,7 @@ namespace Microsoft.FSharp.Collections else false - and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqComponent<'T,'V>) = + and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) @@ -653,7 +669,7 @@ namespace Microsoft.FSharp.Collections else false - and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) = + and Filter<'T,'V> (filter:'T->bool, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) @@ -664,7 +680,7 @@ namespace Microsoft.FSharp.Collections else false - and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqComponent<'U,'V>) = + and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -673,13 +689,13 @@ namespace Microsoft.FSharp.Collections else false - and Identity<'T,'V> (next:SeqComponent<'T,'V>) = + and Identity<'T,'V> (next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext input) - and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) = + and Map<'T,'U,'V> (map:'T->'U, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) @@ -687,7 +703,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -707,7 +723,7 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) = + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'Second,'V>(next) let input1 = enumerable1.GetEnumerator () @@ -727,7 +743,7 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:Result<'V>, next:SeqComponent<'U,'V>) = + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -751,7 +767,7 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) = + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -761,7 +777,7 @@ namespace Microsoft.FSharp.Collections else false - and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqComponent<'U,'V>) = + and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) let mutable idx = 0 @@ -771,7 +787,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) = + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'First,'V>(next) let mutable idx = 0 @@ -793,7 +809,7 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) = + and Pairwise<'T,'V> (next:SeqConsumer<'T*'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable isFirst = true @@ -809,7 +825,7 @@ namespace Microsoft.FSharp.Collections lastValue <- input Helpers.avoidTailCall (next.ProcessNext currentPair) - and Skip<'T,'V> (skipCount:int, next:SeqComponent<'T,'V>) = + and Skip<'T,'V> (skipCount:int, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -836,7 +852,7 @@ namespace Microsoft.FSharp.Collections [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] (Helpers.upcastISeqComponent next).OnComplete () - and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) = + and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable skip = true @@ -851,7 +867,7 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = + and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>) = inherit Truncate<'T, 'V>(takeCount, result, next) interface ISeqComponent with @@ -862,7 +878,7 @@ namespace Microsoft.FSharp.Collections [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] (Helpers.upcastISeqComponent next).OnComplete () - and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) = + and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -872,7 +888,7 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing () false - and Tail<'T, 'V> (next:SeqComponent<'T,'V>) = + and Tail<'T, 'V> (next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable first = true @@ -890,7 +906,7 @@ namespace Microsoft.FSharp.Collections invalidArg "source" (SR.GetString(SR.notEnoughElements)) (Helpers.upcastISeqComponent next).OnComplete () - and Truncate<'T,'V> (truncateCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) = + and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -907,9 +923,24 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing () false + type SeqProcessNextStates = + | InProcess = 0 + | NotStarted = 1 + | Finished = 2 + + type Result<'T>() = + let mutable halted = false + + member val Current = Unchecked.defaultof<'T> with get, set + member val SeqState = SeqProcessNextStates.NotStarted with get, set + member __.Halted = halted + + interface ISeqPipeline with + member __.StopFurtherProcessing () = halted <- true + // SetResult<> is used at the end of the chain of SeqComponents to assign the final value type SetResult<'T> (result:Result<'T>) = - inherit SeqComponent<'T,'T>(seqComponentTail) + inherit SeqConsumer<'T,'T>() override __.ProcessNext (input:'T) : bool = result.Current <- input @@ -937,6 +968,8 @@ namespace Microsoft.FSharp.Collections | _ -> failwith "library implementation error: all states should have been handled" and [] EnumerableBase<'T> () = + inherit SeqEnumerable<'T>() + abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State @@ -953,7 +986,8 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" - and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + + and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqConsumer<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, seqComponent) let rec moveNext () = @@ -990,6 +1024,8 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.Iter (f:'U->unit) : unit = let enumerator = enumerable.GetEnumerator () let result = Result<'U> () @@ -1072,6 +1108,8 @@ namespace Microsoft.FSharp.Collections override this.Append source = Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = ignore f; failwith "TBD" + override this.Iter (f:'T->unit) : unit = let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) let enumerator = enumerable.GetEnumerator () @@ -1095,7 +1133,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (Enumerable(enumerable, current)) module Array = - type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:SeqConsumer<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable idx = 0 @@ -1137,6 +1175,25 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + let mutable idx = 0 + let mutable halted = false + + let pipeline = + { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + + let result = f pipeline + let consumer = current.Create pipeline result + + let array = delayedArray () + while (not halted) && (idx < array.Length) do + consumer.ProcessNext array.[idx] |> ignore + idx <- idx + 1 + + (Helpers.upcastISeqComponent consumer).OnComplete () + + result + override this.Iter (f:'U->unit) : unit = let mutable idx = 0 let result = Result<'U> () @@ -1182,7 +1239,7 @@ namespace Microsoft.FSharp.Collections create array (IdentityFactory ()) module List = - type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqConsumer<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable list = alist @@ -1216,6 +1273,8 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.Iter (f:'U->unit) : unit = let result = Result<'U> () let components = current.Create result (SetResult<'U> result) @@ -1257,7 +1316,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (Enumerable(alist, current)) module Unfold = - type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) = + type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:SeqConsumer<'T,'U>, signal:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) let mutable current = state @@ -1288,6 +1347,8 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.Iter (f:'U->unit) : unit = let result = Result<'U> () let components = current.Create result (SetResult<'U> result) @@ -1345,9 +1406,17 @@ namespace Microsoft.FSharp.Collections else System.Int32.MaxValue - type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) = + let makeIsSkipping (consumer:SeqConsumer<'T,'U>) = + match consumer with + | :? SeqComponent<'T,'U> as c -> c.Skipping + | _ -> fun () -> false + + type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqConsumer<'T,'U>, signal:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) + let isSkipping = + makeIsSkipping seqComponent + let terminatingIdx = getTerminatingIdx count @@ -1361,7 +1430,7 @@ namespace Microsoft.FSharp.Collections if maybeSkipping then // Skip can only is only checked at the start of the sequence, so once // triggered, we stay triggered. - maybeSkipping <- seqComponent.Skipping () + maybeSkipping <- isSkipping () if maybeSkipping then moveNext () @@ -1392,18 +1461,23 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.Iter (iter:'U->unit) : unit = let result = Result<'U> () let components = current.Create result (SetResult<'U> result) let mutable idx = -1 let terminatingIdx = getTerminatingIdx count - + + let isSkipping = + makeIsSkipping components + let mutable maybeSkipping = true while (not result.Halted) && (idx < terminatingIdx) do if maybeSkipping then - maybeSkipping <- components.Skipping () + maybeSkipping <- isSkipping () if (not maybeSkipping) && (components.ProcessNext (f (idx+1))) then iter result.Current @@ -1421,12 +1495,15 @@ namespace Microsoft.FSharp.Collections let mutable idx = -1 let terminatingIdx = getTerminatingIdx count + let isSkipping = + makeIsSkipping components + let mutable maybeSkipping = true let mutable state = initialState while (not result.Halted) && (idx < terminatingIdx) do if maybeSkipping then - maybeSkipping <- components.Skipping () + maybeSkipping <- isSkipping () if (not maybeSkipping) && (components.ProcessNext (f (idx+1))) then state <- folder'.Invoke (state, result.Current) @@ -1500,6 +1577,8 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = ignore f; failwith "TBD" + override this.Iter (f:'T->unit): unit = let enumerator = (Helpers.upcastEnumerable this).GetEnumerator () @@ -2204,13 +2283,17 @@ namespace Microsoft.FSharp.Collections [] let inline sum (source:seq<'a>) : 'a = - source - |> foreach (fun _ -> - { new Composer.Core.Folder<'a,'a> (LanguagePrimitives.GenericZero) with - override this.ProcessNext value = - this.Value <- Checked.(+) this.Value value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun sum -> sum.Value + match source with + | :? SeqComposer.SeqEnumerable<'a> as s -> + let summer = SeqComposer.Fold (Checked.(+), LanguagePrimitives.GenericZero) + s.ForEach (fun _ -> summer) |> ignore + summer.Folded + | _ -> + use e = source.GetEnumerator() + let mutable acc = LanguagePrimitives.GenericZero< ^a> + while e.MoveNext() do + acc <- Checked.(+) acc e.Current + acc [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index f06c676e4de..98389ae02a7 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -13,6 +13,28 @@ namespace Microsoft.FSharp.Collections [] [] module Seq = + module SeqComposer = + type ISeqComponent = + abstract OnComplete : unit -> unit + abstract OnDispose : unit -> unit + + type ISeqPipeline = + abstract StopFurtherProcessing : unit -> unit + + [] + type SeqConsumer<'T,'U> = + abstract ProcessNext : input:'T -> bool + interface ISeqComponent + + type Fold<'T> = + inherit SeqConsumer<'T,'T> + new : folder:('T->'T->'T) * initialState:'T -> Fold<'T> + member Folded : 'T + + [] + type SeqEnumerable<'T> = + abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:(ISeqPipeline->'a) -> 'a + /// Returns a new sequence that contains the cartesian product of the two input sequences. /// The first sequence. /// The second sequence. From b15bfeb8108d2c140f8d207c340b6cf4d74ee850 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 18:25:12 +1100 Subject: [PATCH 155/286] Fixed signature file, so can now use object expression --- src/fsharp/FSharp.Core/seq.fs | 21 ++++++++++----------- src/fsharp/FSharp.Core/seq.fsi | 11 +++++++---- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index d78dc1fd40e..0f6fce06cbe 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -471,16 +471,11 @@ namespace Microsoft.FSharp.Collections member __.OnComplete() = () member __.OnDispose() = () - type Fold<'T> (folder:'T->'T->'T, initialState:'T) = + [] + type AccumulatingConsumer<'T, 'U>(initialState:'U) = inherit SeqConsumer<'T,'T>() - let folder = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(folder) - - let mutable folded = initialState - override __.ProcessNext input = - folded <- folder.Invoke (folded, input) - true - member __.Folded = folded + member val Accumulator = initialState with get, set [] type SeqEnumerable<'T>() = @@ -2285,9 +2280,13 @@ namespace Microsoft.FSharp.Collections let inline sum (source:seq<'a>) : 'a = match source with | :? SeqComposer.SeqEnumerable<'a> as s -> - let summer = SeqComposer.Fold (Checked.(+), LanguagePrimitives.GenericZero) - s.ForEach (fun _ -> summer) |> ignore - summer.Folded + let total = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with + override this.ProcessNext value = + this.Accumulator <- Checked.(+) this.Accumulator value + true }) + total.Accumulator | _ -> use e = source.GetEnumerator() let mutable acc = LanguagePrimitives.GenericZero< ^a> diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 98389ae02a7..e3ce82eb234 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -23,13 +23,16 @@ namespace Microsoft.FSharp.Collections [] type SeqConsumer<'T,'U> = + new : unit -> SeqConsumer<'T,'U> abstract ProcessNext : input:'T -> bool interface ISeqComponent - type Fold<'T> = + [] + type AccumulatingConsumer<'T,'U> = inherit SeqConsumer<'T,'T> - new : folder:('T->'T->'T) * initialState:'T -> Fold<'T> - member Folded : 'T + new : initialState:'U -> AccumulatingConsumer<'T,'U> + member Accumulator : 'U + member Accumulator : 'U with set [] type SeqEnumerable<'T> = @@ -1372,4 +1375,4 @@ namespace Microsoft.FSharp.Collections /// /// Thrown when any of the input sequences is null. [] - val zip3: source1:seq<'T1> -> source2:seq<'T2> -> source3:seq<'T3> -> seq<'T1 * 'T2 * 'T3> \ No newline at end of file + val zip3: source1:seq<'T1> -> source2:seq<'T2> -> source3:seq<'T3> -> seq<'T1 * 'T2 * 'T3> From bb90f47a4a9168777763d537f70c89a344974ec8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 19:50:47 +1100 Subject: [PATCH 156/286] Provided all ForEach implementations --- src/fsharp/FSharp.Core/seq.fs | 121 ++++++++++++++++++++++++++++++++-- 1 file changed, 115 insertions(+), 6 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 0f6fce06cbe..ee3c7a1658a 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -493,6 +493,7 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) + let inline upcastSeqConsumer (t:#SeqConsumer<'a,'b>) : SeqConsumer<'a,'b> = (# "" t : SeqConsumer<'a,'b> #) let seqComponentTail = @@ -1019,7 +1020,21 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + let mutable halted = false + let pipeline = + { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + + let result = f pipeline + let consumer = current.Create pipeline result + + use enumerator = enumerable.GetEnumerator () + while (not halted) && (enumerator.MoveNext ()) do + consumer.ProcessNext enumerator.Current |> ignore + + (Helpers.upcastISeqComponent consumer).OnComplete () + + result override this.Iter (f:'U->unit) : unit = let enumerator = enumerable.GetEnumerator () @@ -1103,7 +1118,23 @@ namespace Microsoft.FSharp.Collections override this.Append source = Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = ignore f; failwith "TBD" + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = + let mutable halted = false + let pipeline = + { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + + let result = f pipeline + let consumer = Helpers.upcastSeqConsumer result + + let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) + use enumerator = enumerable.GetEnumerator () + + while enumerator.MoveNext () do + consumer.ProcessNext enumerator.Current |> ignore + + (Helpers.upcastISeqComponent consumer).OnComplete () + + result override this.Iter (f:'T->unit) : unit = let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) @@ -1268,7 +1299,25 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + let mutable halted = false + let pipeline = + { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + + let result = f pipeline + let consumer = current.Create pipeline result + + let rec iterate lst = + match halted, lst with + | true, _ + | false, [] -> (Helpers.upcastISeqComponent consumer).OnComplete () + | false, hd :: tl -> + consumer.ProcessNext hd |> ignore + iterate tl + + iterate alist + + result override this.Iter (f:'U->unit) : unit = let result = Result<'U> () @@ -1342,7 +1391,25 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + let mutable halted = false + let pipeline = + { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + + let result = f pipeline + let consumer = current.Create pipeline result + + let rec iterate current = + match halted, generator current with + | true, _ + | false, None -> (Helpers.upcastISeqComponent consumer).OnComplete () + | false, Some (item, next) -> + consumer.ProcessNext item |> ignore + iterate next + + iterate state + + result override this.Iter (f:'U->unit) : unit = let result = Result<'U> () @@ -1456,7 +1523,34 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ignore f; failwith "TBD" + override this.ForEach (createResult:ISeqPipeline->#SeqConsumer<'U,'U>) = + let mutable halted = false + let pipeline = + { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + + let result = createResult pipeline + let consumer = current.Create pipeline result + + let mutable idx = -1 + let terminatingIdx = getTerminatingIdx count + + let isSkipping = + makeIsSkipping consumer + + let mutable maybeSkipping = true + + while (not halted) && (idx < terminatingIdx) do + if maybeSkipping then + maybeSkipping <- isSkipping () + + if (not maybeSkipping) then + consumer.ProcessNext (f (idx+1)) |> ignore + + idx <- idx + 1 + + (Helpers.upcastISeqComponent consumer).OnComplete () + + result override this.Iter (iter:'U->unit) : unit = let result = Result<'U> () @@ -1572,7 +1666,22 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = ignore f; failwith "TBD" + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = + let mutable halted = false + let pipeline = + { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + + let result = f pipeline + let consumer = Helpers.upcastSeqConsumer result + + use enumerator = (Helpers.upcastEnumerable this).GetEnumerator () + + while enumerator.MoveNext () do + consumer.ProcessNext enumerator.Current |> ignore + + (Helpers.upcastISeqComponent consumer).OnComplete () + + result override this.Iter (f:'T->unit): unit = let enumerator = (Helpers.upcastEnumerable this).GetEnumerator () From 26ad2aa8afe5f923b37c6743254d190efd69e916 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 19:56:59 +1100 Subject: [PATCH 157/286] Removed Fold --- src/fsharp/FSharp.Core/seq.fs | 148 +++++----------------------------- 1 file changed, 18 insertions(+), 130 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ee3c7a1658a..c3fd52a5ec0 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -968,7 +968,6 @@ namespace Microsoft.FSharp.Collections abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> - abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State abstract member Iter : f:('T->unit) -> unit default this.Append source = Helpers.upcastEnumerable (AppendEnumerable [this; source]) @@ -1048,24 +1047,6 @@ namespace Microsoft.FSharp.Collections (Helpers.upcastISeqComponent components).OnComplete () - - override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let enumerator = enumerable.GetEnumerator () - let result = Result<'U> () - - let components = current.Create result (SetResult<'U> result) - - let mutable state = initialState - while (not result.Halted) && (enumerator.MoveNext ()) do - if components.ProcessNext (enumerator.Current) then - state <- folder'.Invoke (state, result.Current) - - (Helpers.upcastISeqComponent components).OnComplete () - - state - and AppendEnumerator<'T> (sources:list>) = let sources = sources |> List.rev @@ -1143,18 +1124,6 @@ namespace Microsoft.FSharp.Collections while enumerator.MoveNext () do f enumerator.Current - override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) - let enumerator = enumerable.GetEnumerator () - - let mutable state = initialState - while enumerator.MoveNext () do - state <- folder'.Invoke (state, enumerator.Current) - - state - let create enumerable current = Helpers.upcastEnumerable (Enumerable(enumerable, current)) @@ -1233,25 +1202,6 @@ namespace Microsoft.FSharp.Collections (Helpers.upcastISeqComponent components).OnComplete () - - override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let mutable idx = 0 - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let array = delayedArray () - let mutable state = initialState - while (not result.Halted) && (idx < array.Length) do - if components.ProcessNext array.[idx] then - state <- folder'.Invoke (state, result.Current) - idx <- idx + 1 - - (Helpers.upcastISeqComponent components).OnComplete () - - state - let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = Helpers.upcastEnumerable (Enumerable(delayedArray, current)) @@ -1336,26 +1286,6 @@ namespace Microsoft.FSharp.Collections fold alist - override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let rec fold state lst = - match result.Halted, lst with - | true, _ - | false, [] -> - (Helpers.upcastISeqComponent components).OnComplete () - state - | false, hd :: tl -> - if components.ProcessNext hd then - fold (folder'.Invoke (state, result.Current)) tl - else - fold state tl - - fold initialState alist - let create alist current = Helpers.upcastEnumerable (Enumerable(alist, current)) @@ -1428,26 +1358,6 @@ namespace Microsoft.FSharp.Collections fold state - override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let rec fold state current = - match result.Halted, generator current with - | true, _ - | false, None -> - (Helpers.upcastISeqComponent components).OnComplete () - state - | false, Some (item, next) -> - if components.ProcessNext item then - fold (folder'.Invoke (state, result.Current)) next - else - fold state next - - fold initialState 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. @@ -1575,34 +1485,6 @@ namespace Microsoft.FSharp.Collections (Helpers.upcastISeqComponent components).OnComplete () - override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let mutable idx = -1 - let terminatingIdx = getTerminatingIdx count - - let isSkipping = - makeIsSkipping components - - let mutable maybeSkipping = true - - let mutable state = initialState - while (not result.Halted) && (idx < terminatingIdx) do - if maybeSkipping then - maybeSkipping <- isSkipping () - - if (not maybeSkipping) && (components.ProcessNext (f (idx+1))) then - state <- folder'.Invoke (state, result.Current) - - idx <- idx + 1 - - (Helpers.upcastISeqComponent components).OnComplete () - - state - 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" @@ -1689,17 +1571,6 @@ namespace Microsoft.FSharp.Collections while enumerator.MoveNext () do f enumerator.Current - override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State = - let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - - let enumerator = (Helpers.upcastEnumerable this).GetEnumerator () - - let mutable state = initialState - while enumerator.MoveNext () do - state <- folder'.Invoke (state, enumerator.Current) - - state - #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions #else @@ -1967,7 +1838,24 @@ namespace Microsoft.FSharp.Collections [] let fold<'T,'State> f (x:'State) (source:seq<'T>) = - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) + checkNonNull "source" source + match source with + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) + let total = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'State> (x) with + override this.ProcessNext value = + this.Accumulator <- f.Invoke (this.Accumulator, value) + true }) + total.Accumulator + | _ -> + use e = source.GetEnumerator() + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) + let mutable state = x + while e.MoveNext() do + state <- f.Invoke(state, e.Current) + state source |> foreach (fun _ -> From bc034c6426f6ae78f9b4698de5d065dbcfbff1e3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 20:01:20 +1100 Subject: [PATCH 158/286] Remove Iter --- src/fsharp/FSharp.Core/seq.fs | 103 ++-------------------------------- 1 file changed, 5 insertions(+), 98 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index c3fd52a5ec0..e718d73879c 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -968,7 +968,6 @@ namespace Microsoft.FSharp.Collections abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> - abstract member Iter : f:('T->unit) -> unit default this.Append source = Helpers.upcastEnumerable (AppendEnumerable [this; source]) @@ -1035,18 +1034,6 @@ namespace Microsoft.FSharp.Collections result - override this.Iter (f:'U->unit) : unit = - let enumerator = enumerable.GetEnumerator () - let result = Result<'U> () - - let components = current.Create result (SetResult<'U> result) - - while (not result.Halted) && (enumerator.MoveNext ()) do - if components.ProcessNext (enumerator.Current) then - f result.Current - - (Helpers.upcastISeqComponent components).OnComplete () - and AppendEnumerator<'T> (sources:list>) = let sources = sources |> List.rev @@ -1117,13 +1104,6 @@ namespace Microsoft.FSharp.Collections result - override this.Iter (f:'T->unit) : unit = - let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) - let enumerator = enumerable.GetEnumerator () - - while enumerator.MoveNext () do - f enumerator.Current - let create enumerable current = Helpers.upcastEnumerable (Enumerable(enumerable, current)) @@ -1189,19 +1169,6 @@ namespace Microsoft.FSharp.Collections result - override this.Iter (f:'U->unit) : unit = - let mutable idx = 0 - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let array = delayedArray () - while (not result.Halted) && (idx < array.Length) do - if components.ProcessNext array.[idx] then - f result.Current - idx <- idx + 1 - - (Helpers.upcastISeqComponent components).OnComplete () - let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = Helpers.upcastEnumerable (Enumerable(delayedArray, current)) @@ -1269,23 +1236,6 @@ namespace Microsoft.FSharp.Collections result - override this.Iter (f:'U->unit) : unit = - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let rec fold lst = - match result.Halted, lst with - | true, _ - | false, [] -> (Helpers.upcastISeqComponent components).OnComplete () - | false, hd :: tl -> - if components.ProcessNext hd then - f result.Current - fold tl - else - fold tl - - fold alist - let create alist current = Helpers.upcastEnumerable (Enumerable(alist, current)) @@ -1341,23 +1291,6 @@ namespace Microsoft.FSharp.Collections result - override this.Iter (f:'U->unit) : unit = - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let rec fold current = - match result.Halted, generator current with - | true, _ - | false, None -> (Helpers.upcastISeqComponent components).OnComplete () - | false, Some (item, next) -> - if components.ProcessNext item then - f result.Current - fold next - else - fold next - - fold 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. @@ -1462,29 +1395,6 @@ namespace Microsoft.FSharp.Collections result - override this.Iter (iter:'U->unit) : unit = - let result = Result<'U> () - let components = current.Create result (SetResult<'U> result) - - let mutable idx = -1 - let terminatingIdx = getTerminatingIdx count - - let isSkipping = - makeIsSkipping components - - let mutable maybeSkipping = true - - while (not result.Halted) && (idx < terminatingIdx) do - if maybeSkipping then - maybeSkipping <- isSkipping () - - if (not maybeSkipping) && (components.ProcessNext (f (idx+1))) then - iter result.Current - - idx <- idx + 1 - - (Helpers.upcastISeqComponent components).OnComplete () - 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" @@ -1565,12 +1475,6 @@ namespace Microsoft.FSharp.Collections result - override this.Iter (f:'T->unit): unit = - let enumerator = (Helpers.upcastEnumerable this).GetEnumerator () - - while enumerator.MoveNext () do - f enumerator.Current - #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions #else @@ -1615,10 +1519,13 @@ namespace Microsoft.FSharp.Collections [] let iter f (source : seq<'T>) = - checkNonNull "source" source checkNonNull "source" source match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Iter f + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> + s.ForEach (fun _ -> + { new SeqComposer.SeqConsumer<'T,'T> () with + override this.ProcessNext value = + f value; true }) |> ignore | _ -> use e = source.GetEnumerator() while e.MoveNext() do From d685d71d98d0028e557888455ebec32ba675bd9d Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 18 Oct 2016 20:18:13 -0400 Subject: [PATCH 159/286] sumby, average, averageby, max, maxby, min, minby --- src/fsharp/FSharp.Core/seq.fs | 267 +++++++++++++++++++++++++--------- 1 file changed, 196 insertions(+), 71 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index e718d73879c..4f5e35720c2 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2200,25 +2200,50 @@ namespace Microsoft.FSharp.Collections [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = - source - |> foreach (fun _ -> - { new Composer.Core.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with - override this.ProcessNext value = - this.Value <- Checked.(+) this.Value (f value) - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun sum -> sum.Value + match source with + | :? SeqComposer.SeqEnumerable<'T> as s -> + let total = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + override this.ProcessNext value = + this.Accumulator <- Checked.(+) this.Accumulator (f value) + true }) + total.Accumulator + | _ -> + use e = source.GetEnumerator() + let mutable acc = LanguagePrimitives.GenericZero< ^U> + while e.MoveNext() do + acc <- Checked.(+) acc (f e.Current) + acc [] let inline average (source: seq< ^a>) : ^a = - checkNonNull "source" source - let mutable acc = LanguagePrimitives.GenericZero< ^a> - let mutable count = 0 - source |> iter (fun current -> - acc <- Checked.(+) acc current - count <- count + 1) - if count = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - LanguagePrimitives.DivideByInt< ^a> acc count + match source with + | :? SeqComposer.SeqEnumerable<'a> as s -> + let mutable count = 0 + let total = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with + override this.ProcessNext value = + this.Accumulator <- Checked.(+) this.Accumulator value + count <- count + 1 + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if count = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + LanguagePrimitives.DivideByInt< ^a> total.Accumulator count + | _ -> + checkNonNull "source" source + let mutable acc = LanguagePrimitives.GenericZero< ^a> + let mutable count = 0 + source |> iter (fun current -> + acc <- Checked.(+) acc current + count <- count + 1) + if count = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + LanguagePrimitives.DivideByInt< ^a> acc count member this.OnComplete _ = if this.Value._2 = 0 then @@ -2227,13 +2252,33 @@ namespace Microsoft.FSharp.Collections [] let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = - source - |> foreach (fun _ -> - { new Composer.Core.Folder<'T,Composer.Core.Values<'U, int>> (Composer.Core.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with - override this.ProcessNext value = - this.Value._1 <- Checked.(+) this.Value._1 (f value) - this.Value._2 <- this.Value._2 + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + match source with + | :? SeqComposer.SeqEnumerable<'T> as s -> + let mutable count = 0 + let total = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + override this.ProcessNext value = + this.Accumulator <- Checked.(+) this.Accumulator (f value) + count <- count + 1 + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if count = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + LanguagePrimitives.DivideByInt< ^U> total.Accumulator count + | _ -> + checkNonNull "source" source + use e = source.GetEnumerator() + let mutable acc = LanguagePrimitives.GenericZero< ^U> + let mutable count = 0 + while e.MoveNext() do + acc <- Checked.(+) acc (f e.Current) + count <- count + 1 + if count = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + LanguagePrimitives.DivideByInt< ^U> acc count member this.OnComplete _ = if this.Value._2 = 0 then @@ -2242,16 +2287,34 @@ namespace Microsoft.FSharp.Collections [] let inline min (source: seq<_>) = - source - |> foreach (fun _ -> - { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - elif value < this.Value._2 then - this.Value._2 <- value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + match source with + | :? SeqComposer.SeqEnumerable<'T> as s -> + let mutable first = false + let min = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + if value < this.Accumulator then + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + min.Accumulator + | _ -> + checkNonNull "source" source + use e = source.GetEnumerator() + if not (e.MoveNext()) then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + let mutable acc = e.Current + while e.MoveNext() do + let curr = e.Current + if curr < acc then + acc <- curr + acc member this.OnComplete _ = if this.Value._1 then @@ -2261,20 +2324,42 @@ namespace Microsoft.FSharp.Collections [] let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = - source - |> foreach (fun _ -> - { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - match this.Value._1, f value with - | true, valueU -> - this.Value._1 <- false - this.Value._2 <- valueU - this.Value._3 <- value - | false, valueU when valueU < this.Value._2 -> - this.Value._2 <- valueU - this.Value._3 <- value - | _ -> () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + match source with + | :? SeqComposer.SeqEnumerable<'T> as s -> + let mutable first = false + let mutable acc = Unchecked.defaultof<'U> + let min = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + let currValue = value + let curr = f currValue + if curr < acc then + acc <- curr + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + min.Accumulator + | _ -> + checkNonNull "source" source + use e = source.GetEnumerator() + if not (e.MoveNext()) then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + let first = e.Current + let mutable acc = f first + let mutable accv = first + while e.MoveNext() do + let currv = e.Current + let curr = f currv + if curr < acc then + acc <- curr + accv <- currv + accv member this.OnComplete _ = if this.Value._1 then @@ -2300,16 +2385,34 @@ namespace Microsoft.FSharp.Collections *) [] let inline max (source: seq<_>) = - source - |> foreach (fun _ -> - { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - elif value > this.Value._2 then - this.Value._2 <- value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + match source with + | :? SeqComposer.SeqEnumerable<'T> as s -> + let mutable first = false + let max = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + if value > this.Accumulator then + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + max.Accumulator + | _ -> + checkNonNull "source" source + use e = source.GetEnumerator() + if not (e.MoveNext()) then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + let mutable acc = e.Current + while e.MoveNext() do + let curr = e.Current + if curr > acc then + acc <- curr + acc member this.OnComplete _ = if this.Value._1 then @@ -2319,20 +2422,42 @@ namespace Microsoft.FSharp.Collections [] let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = - source - |> foreach (fun _ -> - { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - match this.Value._1, f value with - | true, valueU -> - this.Value._1 <- false - this.Value._2 <- valueU - this.Value._3 <- value - | false, valueU when valueU > this.Value._2 -> - this.Value._2 <- valueU - this.Value._3 <- value - | _ -> () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + match source with + | :? SeqComposer.SeqEnumerable<'T> as s -> + let mutable first = false + let mutable acc = Unchecked.defaultof<'U> + let min = + s.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + let currValue = value + let curr = f currValue + if curr > acc then + acc <- curr + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + min.Accumulator + | _ -> + checkNonNull "source" source + use e = source.GetEnumerator() + if not (e.MoveNext()) then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + let first = e.Current + let mutable acc = f first + let mutable accv = first + while e.MoveNext() do + let currv = e.Current + let curr = f currv + if curr > acc then + acc <- curr + accv <- currv + accv member this.OnComplete _ = if this.Value._1 then From 8c86a15b7870ae619aa23ed5d30cb517461ac737 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 19 Oct 2016 18:20:55 +1100 Subject: [PATCH 160/286] Removed overzelous upcastSeqConsumer PE verify says no. --- src/fsharp/FSharp.Core/seq.fs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 4f5e35720c2..8aad815b50e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -493,8 +493,6 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) - let inline upcastSeqConsumer (t:#SeqConsumer<'a,'b>) : SeqConsumer<'a,'b> = (# "" t : SeqConsumer<'a,'b> #) - let seqComponentTail = { new ISeqComponent with @@ -1092,7 +1090,7 @@ namespace Microsoft.FSharp.Collections { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } let result = f pipeline - let consumer = Helpers.upcastSeqConsumer result + let consumer : SeqConsumer<'T,'T> = upcast result let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) use enumerator = enumerable.GetEnumerator () @@ -1464,7 +1462,7 @@ namespace Microsoft.FSharp.Collections { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } let result = f pipeline - let consumer = Helpers.upcastSeqConsumer result + let consumer : SeqConsumer<'T,'T> = upcast result use enumerator = (Helpers.upcastEnumerable this).GetEnumerator () From 1481aa0a5b80ff4d666863db4e35d63e404ed289 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 19 Oct 2016 21:39:49 +1100 Subject: [PATCH 161/286] Appease the NoNeedToTailcall file --- .../analyses/tailcalls.NoNeedToTailcall.output.test.bsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl index 0f49d38a8dc..5f4e677efc6 100644 --- a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl +++ b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl @@ -41,7 +41,7 @@ value simpleLibraryCall9 at line 63 does not make a critical tailcall value simpleLibraryCall10 at line 65 does not make a critical tailcall value simpleLibraryCall11 at line 66 does not make a critical tailcall value simpleLibraryCall12 at line 67 does not make a critical tailcall -value simpleLibraryCall13 at line 68 may make a critical tailcall +value simpleLibraryCall13 at line 68 does not make a critical tailcall value simpleLibraryUse14 at line 69 does not make a critical tailcall value simpleLibraryUse15 at line 70 does not make a critical tailcall value simpleLibraryUse16 at line 71 does not make a critical tailcall From 860c051f491ecf5b3c5aaa9fc61749dda182261a Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 18:27:37 -0400 Subject: [PATCH 162/286] toComposer and implementing sum --- src/fsharp/FSharp.Core/seq.fs | 24 +++++++++++++----------- src/fsharp/FSharp.Core/seq.fsi | 10 ++++++++++ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 8aad815b50e..3b5bae6dfd1 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2178,23 +2178,25 @@ namespace Microsoft.FSharp.Collections then mkDelayedSeq (fun () -> countByValueType keyf source) else mkDelayedSeq (fun () -> countByRefType keyf source) + [] + let toComposer (source:seq<'T>): SeqComposer.SeqEnumerable<'T> = + checkNonNull "source" source + match source with + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(s, (SeqComposer.IdentityFactory())) + | :? array<'T> as a -> upcast SeqComposer.Array.Enumerable((fun () -> a), (SeqComposer.IdentityFactory())) + | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, (SeqComposer.IdentityFactory())) + | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, (SeqComposer.IdentityFactory())) + [] let inline sum (source:seq<'a>) : 'a = - match source with - | :? SeqComposer.SeqEnumerable<'a> as s -> - let total = - s.ForEach (fun _ -> + let newSource = toComposer source + let total = + newSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Accumulator <- Checked.(+) this.Accumulator value true }) - total.Accumulator - | _ -> - use e = source.GetEnumerator() - let mutable acc = LanguagePrimitives.GenericZero< ^a> - while e.MoveNext() do - acc <- Checked.(+) acc e.Current - acc + total.Accumulator [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index e3ce82eb234..87df902c3b8 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -1146,6 +1146,16 @@ namespace Microsoft.FSharp.Collections [] val inline sortByDescending : projection:('T -> 'Key) -> source:seq<'T> -> seq<'T> when 'Key : comparison + /// Builds an SeqEnumerable from the given collection. + /// + /// The input sequence. + /// + /// The result SeqEnumerable. + /// + /// Thrown when the input sequence is null. + [] + val toComposer : source:seq<'T> -> SeqComposer.SeqEnumerable<'T> + /// Returns the sum of the elements in the sequence. /// /// The elements are summed using the + operator and Zero property associated with the generated type. From c395f2f719c355ce3d144518a8de37836328c503 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 18:48:31 -0400 Subject: [PATCH 163/286] singleton identityfactory --- src/fsharp/FSharp.Core/seq.fs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 3b5bae6dfd1..f98f630f51f 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -548,6 +548,8 @@ namespace Microsoft.FSharp.Collections override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Identity (next) override __.IsIdentity = true + static member IdentityFactory = IdentityFactory<'T>() + and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = @@ -1174,10 +1176,10 @@ namespace Microsoft.FSharp.Collections createDelayed (fun () -> array) current let createDelayedId (delayedArray:unit -> array<'T>) = - createDelayed delayedArray (IdentityFactory ()) + createDelayed delayedArray IdentityFactory.IdentityFactory let createId (array:array<'T>) = - create array (IdentityFactory ()) + create array IdentityFactory.IdentityFactory module List = type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqConsumer<'T,'U>, result:Result<'U>) = @@ -1500,7 +1502,7 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : seq<'T> = - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Unfold.Enumerable<'T,'T,'State>(generator, state, SeqComposer.IdentityFactory ())) + SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Unfold.Enumerable<'T,'T,'State>(generator, state, SeqComposer.IdentityFactory.IdentityFactory)) [] let empty<'T> = (EmptyEnumerable :> seq<'T>) @@ -2182,10 +2184,10 @@ namespace Microsoft.FSharp.Collections let toComposer (source:seq<'T>): SeqComposer.SeqEnumerable<'T> = checkNonNull "source" source match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(s, (SeqComposer.IdentityFactory())) - | :? array<'T> as a -> upcast SeqComposer.Array.Enumerable((fun () -> a), (SeqComposer.IdentityFactory())) - | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, (SeqComposer.IdentityFactory())) - | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, (SeqComposer.IdentityFactory())) + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(s, SeqComposer.IdentityFactory.IdentityFactory) + | :? array<'T> as a -> upcast SeqComposer.Array.Enumerable((fun () -> a), SeqComposer.IdentityFactory.IdentityFactory) + | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, SeqComposer.IdentityFactory.IdentityFactory) + | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory.IdentityFactory) [] let inline sum (source:seq<'a>) : 'a = From 41cc0e30fe28077918efc639cf0b131b72bccdcb Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 18:54:59 -0400 Subject: [PATCH 164/286] using tocomposer --- src/fsharp/FSharp.Core/seq.fs | 334 ++++++++++++---------------------- 1 file changed, 112 insertions(+), 222 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index f98f630f51f..6f02c90f6bc 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2191,9 +2191,9 @@ namespace Microsoft.FSharp.Collections [] let inline sum (source:seq<'a>) : 'a = - let newSource = toComposer source + let composedSource = toComposer source let total = - newSource.ForEach (fun _ -> + composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Accumulator <- Checked.(+) this.Accumulator value @@ -2202,85 +2202,51 @@ namespace Microsoft.FSharp.Collections [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = - match source with - | :? SeqComposer.SeqEnumerable<'T> as s -> - let total = - s.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with - override this.ProcessNext value = - this.Accumulator <- Checked.(+) this.Accumulator (f value) - true }) - total.Accumulator - | _ -> - use e = source.GetEnumerator() - let mutable acc = LanguagePrimitives.GenericZero< ^U> - while e.MoveNext() do - acc <- Checked.(+) acc (f e.Current) - acc + let composedSource = toComposer source + let total = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + override this.ProcessNext value = + this.Accumulator <- Checked.(+) this.Accumulator (f value) + true }) + total.Accumulator [] let inline average (source: seq< ^a>) : ^a = - match source with - | :? SeqComposer.SeqEnumerable<'a> as s -> - let mutable count = 0 - let total = - s.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with - override this.ProcessNext value = - this.Accumulator <- Checked.(+) this.Accumulator value - count <- count + 1 - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if count = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - LanguagePrimitives.DivideByInt< ^a> total.Accumulator count - | _ -> - checkNonNull "source" source - let mutable acc = LanguagePrimitives.GenericZero< ^a> - let mutable count = 0 - source |> iter (fun current -> - acc <- Checked.(+) acc current - count <- count + 1) - if count = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - LanguagePrimitives.DivideByInt< ^a> acc count + let composedSource = toComposer source - member this.OnComplete _ = - if this.Value._2 = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - |> fun total -> LanguagePrimitives.DivideByInt< ^a> total.Value._1 total.Value._2 + let mutable count = 0 + let total = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with + override this.ProcessNext value = + this.Accumulator <- Checked.(+) this.Accumulator value + count <- count + 1 + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if count = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + LanguagePrimitives.DivideByInt< ^a> total.Accumulator count [] let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = - match source with - | :? SeqComposer.SeqEnumerable<'T> as s -> - let mutable count = 0 - let total = - s.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with - override this.ProcessNext value = - this.Accumulator <- Checked.(+) this.Accumulator (f value) - count <- count + 1 - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if count = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - LanguagePrimitives.DivideByInt< ^U> total.Accumulator count - | _ -> - checkNonNull "source" source - use e = source.GetEnumerator() - let mutable acc = LanguagePrimitives.GenericZero< ^U> - let mutable count = 0 - while e.MoveNext() do - acc <- Checked.(+) acc (f e.Current) - count <- count + 1 - if count = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - LanguagePrimitives.DivideByInt< ^U> acc count + let composedSource = toComposer source + let mutable count = 0 + let total = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + override this.ProcessNext value = + this.Accumulator <- Checked.(+) this.Accumulator (f value) + count <- count + 1 + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if count = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + LanguagePrimitives.DivideByInt< ^U> total.Accumulator count member this.OnComplete _ = if this.Value._2 = 0 then @@ -2289,85 +2255,47 @@ namespace Microsoft.FSharp.Collections [] let inline min (source: seq<_>) = - match source with - | :? SeqComposer.SeqEnumerable<'T> as s -> - let mutable first = false - let min = - s.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - first <- false - if value < this.Accumulator then - this.Accumulator <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - min.Accumulator - | _ -> - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let mutable acc = e.Current - while e.MoveNext() do - let curr = e.Current - if curr < acc then - acc <- curr - acc + let composedSource = toComposer source - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun min -> min.Value._2 + let mutable first = false + let min = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + if value < this.Accumulator then + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + min.Accumulator [] let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = - match source with - | :? SeqComposer.SeqEnumerable<'T> as s -> - let mutable first = false - let mutable acc = Unchecked.defaultof<'U> - let min = - s.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - first <- false - let currValue = value - let curr = f currValue - if curr < acc then - acc <- curr - this.Accumulator <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - min.Accumulator - | _ -> - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let first = e.Current - let mutable acc = f first - let mutable accv = first - while e.MoveNext() do - let currv = e.Current - let curr = f currv - if curr < acc then - acc <- curr - accv <- currv - accv + let composedSource = toComposer source - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun min -> min.Value._3 + let mutable first = false + let mutable acc = Unchecked.defaultof<'U> + let min = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + let currValue = value + let curr = f currValue + if curr < acc then + acc <- curr + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + min.Accumulator (* [] let inline minValBy (f : 'T -> 'U) (source: seq<'T>) : 'U = @@ -2387,85 +2315,47 @@ namespace Microsoft.FSharp.Collections *) [] let inline max (source: seq<_>) = - match source with - | :? SeqComposer.SeqEnumerable<'T> as s -> - let mutable first = false - let max = - s.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - first <- false - if value > this.Accumulator then - this.Accumulator <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - max.Accumulator - | _ -> - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let mutable acc = e.Current - while e.MoveNext() do - let curr = e.Current - if curr > acc then - acc <- curr - acc + let composedSource = toComposer source - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun max -> max.Value._2 + let mutable first = false + let max = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + if value > this.Accumulator then + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + max.Accumulator [] let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = - match source with - | :? SeqComposer.SeqEnumerable<'T> as s -> - let mutable first = false - let mutable acc = Unchecked.defaultof<'U> - let min = - s.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - first <- false - let currValue = value - let curr = f currValue - if curr > acc then - acc <- curr - this.Accumulator <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - min.Accumulator - | _ -> - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - let first = e.Current - let mutable acc = f first - let mutable accv = first - while e.MoveNext() do - let currv = e.Current - let curr = f currv - if curr > acc then - acc <- curr - accv <- currv - accv + let composedSource = toComposer source - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun min -> min.Value._3 + let mutable first = false + let mutable acc = Unchecked.defaultof<'U> + let min = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + first <- false + let currValue = value + let curr = f currValue + if curr > acc then + acc <- curr + this.Accumulator <- value + true + interface SeqComposer.ISeqComponent with + member __.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + min.Accumulator (* [] From 3f06c3be5bb969156ce68ab1e9234fec870a9378 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 19:58:41 -0400 Subject: [PATCH 165/286] implementing previously implementing seq functions using toComposer. Also fixes a bug with the boolean checking first --- src/fsharp/FSharp.Core/seq.fs | 50 ++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 6f02c90f6bc..89d9cb171eb 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2257,13 +2257,15 @@ namespace Microsoft.FSharp.Collections let inline min (source: seq<_>) = let composedSource = toComposer source - let mutable first = false + let mutable first = true let min = composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = - first <- false - if value < this.Accumulator then + if first then + first <- false + this.Accumulator <- value + elif value < this.Accumulator then this.Accumulator <- value true interface SeqComposer.ISeqComponent with @@ -2277,18 +2279,22 @@ namespace Microsoft.FSharp.Collections let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = let composedSource = toComposer source - let mutable first = false + let mutable first = true let mutable acc = Unchecked.defaultof<'U> let min = composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = - first <- false - let currValue = value - let curr = f currValue - if curr < acc then - acc <- curr + if first then + first <- false this.Accumulator <- value + else + first <- false + let currValue = value + let curr = f currValue + if curr < acc then + acc <- curr + this.Accumulator <- value true interface SeqComposer.ISeqComponent with member __.OnComplete() = @@ -2317,14 +2323,17 @@ namespace Microsoft.FSharp.Collections let inline max (source: seq<_>) = let composedSource = toComposer source - let mutable first = false + let mutable first = true let max = composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = - first <- false - if value > this.Accumulator then - this.Accumulator <- value + if first then + first <- false + this.Accumulator <- value + else + if value > this.Accumulator then + this.Accumulator <- value true interface SeqComposer.ISeqComponent with member __.OnComplete() = @@ -2337,18 +2346,21 @@ namespace Microsoft.FSharp.Collections let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = let composedSource = toComposer source - let mutable first = false + let mutable first = true let mutable acc = Unchecked.defaultof<'U> let min = composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = - first <- false - let currValue = value - let curr = f currValue - if curr > acc then - acc <- curr + if first then + first <- false this.Accumulator <- value + else + let currValue = value + let curr = f currValue + if curr > acc then + acc <- curr + this.Accumulator <- value true interface SeqComposer.ISeqComponent with member __.OnComplete() = From 18bf9dfb24be5e1c840b8fa43189c287a83d06a5 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 21:32:50 -0400 Subject: [PATCH 166/286] fix bug with bool --- src/fsharp/FSharp.Core/seq.fs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 89d9cb171eb..cf895b42eb0 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2285,13 +2285,13 @@ namespace Microsoft.FSharp.Collections composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = + let currValue = value + let curr = f currValue if first then first <- false + acc <- curr this.Accumulator <- value else - first <- false - let currValue = value - let curr = f currValue if curr < acc then acc <- curr this.Accumulator <- value @@ -2329,8 +2329,8 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = if first then - first <- false - this.Accumulator <- value + first <- false + this.Accumulator <- value else if value > this.Accumulator then this.Accumulator <- value @@ -2352,12 +2352,13 @@ namespace Microsoft.FSharp.Collections composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = + let currValue = value + let curr = f currValue if first then first <- false + acc <- curr this.Accumulator <- value else - let currValue = value - let curr = f currValue if curr > acc then acc <- curr this.Accumulator <- value From 769bf354c9fea162ce3633985f4e482ace510d45 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 16:55:58 +1100 Subject: [PATCH 167/286] Remove duplicated ISeqPipeline --- src/fsharp/FSharp.Core/seq.fs | 48 ++++++++++++++--------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index cf895b42eb0..27ab7d0d58c 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -942,6 +942,11 @@ namespace Microsoft.FSharp.Collections result.Current <- input true + type Pipeline() = + let mutable halted = false + interface ISeqPipeline with member x.StopFurtherProcessing() = halted <- true + member __.Halted = halted + module Enumerable = [] type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) = @@ -1019,15 +1024,13 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let mutable halted = false - let pipeline = - { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + let pipeline = Pipeline() let result = f pipeline let consumer = current.Create pipeline result use enumerator = enumerable.GetEnumerator () - while (not halted) && (enumerator.MoveNext ()) do + while (not pipeline.Halted) && (enumerator.MoveNext ()) do consumer.ProcessNext enumerator.Current |> ignore (Helpers.upcastISeqComponent consumer).OnComplete () @@ -1087,9 +1090,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = - let mutable halted = false - let pipeline = - { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + let pipeline = Pipeline() let result = f pipeline let consumer : SeqConsumer<'T,'T> = upcast result @@ -1097,7 +1098,7 @@ namespace Microsoft.FSharp.Collections let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) use enumerator = enumerable.GetEnumerator () - while enumerator.MoveNext () do + while (not pipeline.Halted) && (enumerator.MoveNext ()) do consumer.ProcessNext enumerator.Current |> ignore (Helpers.upcastISeqComponent consumer).OnComplete () @@ -1152,16 +1153,13 @@ namespace Microsoft.FSharp.Collections override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = let mutable idx = 0 - let mutable halted = false - - let pipeline = - { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + let pipeline = Pipeline () let result = f pipeline let consumer = current.Create pipeline result let array = delayedArray () - while (not halted) && (idx < array.Length) do + while (not pipeline.Halted) && (idx < array.Length) do consumer.ProcessNext array.[idx] |> ignore idx <- idx + 1 @@ -1217,15 +1215,13 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let mutable halted = false - let pipeline = - { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + let pipeline = Pipeline () let result = f pipeline let consumer = current.Create pipeline result let rec iterate lst = - match halted, lst with + match pipeline.Halted, lst with | true, _ | false, [] -> (Helpers.upcastISeqComponent consumer).OnComplete () | false, hd :: tl -> @@ -1272,15 +1268,13 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let mutable halted = false - let pipeline = - { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + let pipeline = Pipeline () let result = f pipeline let consumer = current.Create pipeline result let rec iterate current = - match halted, generator current with + match pipeline.Halted, generator current with | true, _ | false, None -> (Helpers.upcastISeqComponent consumer).OnComplete () | false, Some (item, next) -> @@ -1367,9 +1361,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) override this.ForEach (createResult:ISeqPipeline->#SeqConsumer<'U,'U>) = - let mutable halted = false - let pipeline = - { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + let pipeline = Pipeline () let result = createResult pipeline let consumer = current.Create pipeline result @@ -1382,7 +1374,7 @@ namespace Microsoft.FSharp.Collections let mutable maybeSkipping = true - while (not halted) && (idx < terminatingIdx) do + while (not pipeline.Halted) && (idx < terminatingIdx) do if maybeSkipping then maybeSkipping <- isSkipping () @@ -1459,16 +1451,14 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = - let mutable halted = false - let pipeline = - { new ISeqPipeline with member x.StopFurtherProcessing() = halted <- true } + let pipeline = Pipeline () let result = f pipeline let consumer : SeqConsumer<'T,'T> = upcast result use enumerator = (Helpers.upcastEnumerable this).GetEnumerator () - while enumerator.MoveNext () do + while (not pipeline.Halted) && (enumerator.MoveNext ()) do consumer.ProcessNext enumerator.Current |> ignore (Helpers.upcastISeqComponent consumer).OnComplete () From 1879a1c833ca4a4414df297e42bf30ce79c56649 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 17:56:26 +1100 Subject: [PATCH 168/286] Just a straight cast when EnumerableBase --- src/fsharp/FSharp.Core/seq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 27ab7d0d58c..552ddc13727 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2174,7 +2174,7 @@ namespace Microsoft.FSharp.Collections let toComposer (source:seq<'T>): SeqComposer.SeqEnumerable<'T> = checkNonNull "source" source match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(s, SeqComposer.IdentityFactory.IdentityFactory) + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast s | :? array<'T> as a -> upcast SeqComposer.Array.Enumerable((fun () -> a), SeqComposer.IdentityFactory.IdentityFactory) | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, SeqComposer.IdentityFactory.IdentityFactory) | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory.IdentityFactory) From 8201d570a69f110433f768b53471efa247fd3ae3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 18:24:25 +1100 Subject: [PATCH 169/286] Simplified Identity --- src/fsharp/FSharp.Core/seq.fs | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 552ddc13727..d5b6d57c29b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -501,9 +501,6 @@ namespace Microsoft.FSharp.Collections type [] SeqComponentFactory<'T,'U> () = abstract Create<'V> : ISeqPipeline -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> - abstract IsIdentity : bool - - default __.IsIdentity = false and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = inherit SeqComponentFactory<'T,'V> () @@ -511,14 +508,7 @@ namespace Microsoft.FSharp.Collections first.Create result (second.Create result next) static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = - let castToTV (factory:obj) = - match factory with - | :? SeqComponentFactory<'T,'V> as result -> result - | _ -> failwith "library implementation error: they types must match when paired with identity" - - if first.IsIdentity then castToTV second - elif second.IsIdentity then castToTV first - else upcast ComposedFactory(first, second) + upcast ComposedFactory(first, second) and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () @@ -545,10 +535,9 @@ namespace Microsoft.FSharp.Collections and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Identity (next) - override __.IsIdentity = true - - static member IdentityFactory = IdentityFactory<'T>() + static let singleton = IdentityFactory<'T>() + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = next + static member IdentityFactory = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () @@ -685,12 +674,6 @@ namespace Microsoft.FSharp.Collections else false - and Identity<'T,'V> (next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - override __.ProcessNext (input:'T) : bool = - Helpers.avoidTailCall (next.ProcessNext input) - and Map<'T,'U,'V> (map:'T->'U, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) From 790b0cd633ceba30ab42489bbce0e80325589ace Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 19:25:47 +1100 Subject: [PATCH 170/286] Avoid creating extra ref objects Using average as an example of using a tuple-like, but mutable, value type to tie the data closer together and avoid allocation. --- src/fsharp/FSharp.Core/seq.fs | 43 ++++++++++++++++++++++++---------- src/fsharp/FSharp.Core/seq.fsi | 13 ++++++++-- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index d5b6d57c29b..9ce41c04f08 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -471,11 +471,26 @@ namespace Microsoft.FSharp.Collections member __.OnComplete() = () member __.OnDispose() = () + [] + type MutableData<'a,'b> = + val mutable _1 : 'a + val mutable _2 : 'b + + new (a:'a, b: 'b) = { + _1 = a + _2 = b + } + [] - type AccumulatingConsumer<'T, 'U>(initialState:'U) = - inherit SeqConsumer<'T,'T>() + type AccumulatingConsumer<'T, 'U> = + inherit SeqConsumer<'T,'T> + + val mutable Accumulator : 'U - member val Accumulator = initialState with get, set + new (initialState) = { + inherit SeqConsumer<'T,'T>() + Accumulator = initialState + } [] type SeqEnumerable<'T>() = @@ -2162,6 +2177,8 @@ namespace Microsoft.FSharp.Collections | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, SeqComposer.IdentityFactory.IdentityFactory) | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory.IdentityFactory) + let inline foreach f (source:SeqComposer.SeqEnumerable<_>) = source.ForEach f + [] let inline sum (source:seq<'a>) : 'a = let composedSource = toComposer source @@ -2186,22 +2203,22 @@ namespace Microsoft.FSharp.Collections [] let inline average (source: seq< ^a>) : ^a = - let composedSource = toComposer source - - let mutable count = 0 let total = - composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'a, SeqComposer.MutableData<'a, int>> (SeqComposer.MutableData(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = - this.Accumulator <- Checked.(+) this.Accumulator value - count <- count + 1 + this.Accumulator._1 <- Checked.(+) this.Accumulator._1 value + this.Accumulator._2 <- this.Accumulator._2 + 1 true + interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if count = 0 then + member this.OnComplete() = + if (this:?>SeqComposer.AccumulatingConsumer<'a, SeqComposer.MutableData<'a, int>>).Accumulator._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - LanguagePrimitives.DivideByInt< ^a> total.Accumulator count + LanguagePrimitives.DivideByInt< ^a> total.Accumulator._1 total.Accumulator._2 [] let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 87df902c3b8..443286c3fa0 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -27,12 +27,21 @@ namespace Microsoft.FSharp.Collections abstract ProcessNext : input:'T -> bool interface ISeqComponent + [] + type MutableData<'a,'b> = + struct + new : a:'a * b:'b -> MutableData<'a,'b> + val mutable _1: 'a + val mutable _2: 'b + end + [] type AccumulatingConsumer<'T,'U> = + class inherit SeqConsumer<'T,'T> new : initialState:'U -> AccumulatingConsumer<'T,'U> - member Accumulator : 'U - member Accumulator : 'U with set + val mutable Accumulator: 'U + end [] type SeqEnumerable<'T> = From 3b4585b7ee1024f201748c283319bcf42d1eee9e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 20:08:10 +1100 Subject: [PATCH 171/286] Ensuring that OnDispose is called from ForEach --- src/fsharp/FSharp.Core/seq.fs | 178 ++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 84 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 9ce41c04f08..7581f7d3669 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1013,6 +1013,10 @@ namespace Microsoft.FSharp.Collections and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = inherit EnumerableBase<'U>() + static let iterate (enumerator:IEnumerator<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + while (not pipeline.Halted) && (enumerator.MoveNext ()) do + consumer.ProcessNext enumerator.Current |> ignore + interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1023,17 +1027,15 @@ namespace Microsoft.FSharp.Collections override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = let pipeline = Pipeline() - let result = f pipeline let consumer = current.Create pipeline result - use enumerator = enumerable.GetEnumerator () - while (not pipeline.Halted) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - - (Helpers.upcastISeqComponent consumer).OnComplete () - - result + try + iterate enumerator pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () and AppendEnumerator<'T> (sources:list>) = let sources = sources |> List.rev @@ -1077,6 +1079,10 @@ namespace Microsoft.FSharp.Collections and AppendEnumerable<'T> (sources:list>) = inherit EnumerableBase<'T>() + static let iterate (enumerator:IEnumerator<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + while (not pipeline.Halted) && (enumerator.MoveNext ()) do + consumer.ProcessNext enumerator.Current |> ignore + interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = Helpers.upcastEnumerator (new AppendEnumerator<_> (sources)) @@ -1089,19 +1095,16 @@ namespace Microsoft.FSharp.Collections override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = let pipeline = Pipeline() - let result = f pipeline let consumer : SeqConsumer<'T,'T> = upcast result - let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) use enumerator = enumerable.GetEnumerator () - - while (not pipeline.Halted) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - - (Helpers.upcastISeqComponent consumer).OnComplete () - - result + try + iterate enumerator pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () let create enumerable current = Helpers.upcastEnumerable (Enumerable(enumerable, current)) @@ -1141,6 +1144,12 @@ namespace Microsoft.FSharp.Collections type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() + static let iterate (array:array<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let mutable idx = 0 + while (not pipeline.Halted) && (idx < array.Length) do + consumer.ProcessNext array.[idx] |> ignore + idx <- idx + 1 + interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1150,20 +1159,15 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let mutable idx = 0 let pipeline = Pipeline () - let result = f pipeline let consumer = current.Create pipeline result - - let array = delayedArray () - while (not pipeline.Halted) && (idx < array.Length) do - consumer.ProcessNext array.[idx] |> ignore - idx <- idx + 1 - - (Helpers.upcastISeqComponent consumer).OnComplete () - - result + try + iterate (delayedArray ()) pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = Helpers.upcastEnumerable (Enumerable(delayedArray, current)) @@ -1201,6 +1205,16 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext list + let iterate (alist:list<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let rec iterate lst = + match pipeline.Halted, lst with + | true, _ + | false, [] -> () + | false, hd :: tl -> + consumer.ProcessNext hd |> ignore + iterate tl + iterate alist + type Enumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() @@ -1214,21 +1228,14 @@ namespace Microsoft.FSharp.Collections override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = let pipeline = Pipeline () - let result = f pipeline let consumer = current.Create pipeline result - - let rec iterate lst = - match pipeline.Halted, lst with - | true, _ - | false, [] -> (Helpers.upcastISeqComponent consumer).OnComplete () - | false, hd :: tl -> - consumer.ProcessNext hd |> ignore - iterate tl - - iterate alist - - result + try + iterate alist pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () let create alist current = Helpers.upcastEnumerable (Enumerable(alist, current)) @@ -1257,6 +1264,17 @@ namespace Microsoft.FSharp.Collections type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() + static let iterate (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let rec iterate current = + match pipeline.Halted, generator current with + | true, _ + | false, None -> () + | false, Some (item, next) -> + consumer.ProcessNext item |> ignore + iterate next + + iterate state + interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1267,21 +1285,14 @@ namespace Microsoft.FSharp.Collections override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = let pipeline = Pipeline () - let result = f pipeline let consumer = current.Create pipeline result - - let rec iterate current = - match pipeline.Halted, generator current with - | true, _ - | false, None -> (Helpers.upcastISeqComponent consumer).OnComplete () - | false, Some (item, next) -> - consumer.ProcessNext item |> ignore - iterate next - - iterate state - - result + try + iterate generator state pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () module Init = // The original implementation of "init" delayed the calculation of Current, and so it was possible @@ -1350,6 +1361,18 @@ namespace Microsoft.FSharp.Collections type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() + static let iterate f (terminatingIdx:int) (isSkipping) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let mutable idx = -1 + let mutable maybeSkipping = true + while (not pipeline.Halted) && (idx < terminatingIdx) do + if maybeSkipping then + maybeSkipping <- isSkipping () + + if (not maybeSkipping) then + consumer.ProcessNext (f (idx+1)) |> ignore + + idx <- idx + 1 + interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1360,30 +1383,16 @@ namespace Microsoft.FSharp.Collections override this.ForEach (createResult:ISeqPipeline->#SeqConsumer<'U,'U>) = let pipeline = Pipeline () - let result = createResult pipeline let consumer = current.Create pipeline result - - let mutable idx = -1 let terminatingIdx = getTerminatingIdx count - - let isSkipping = - makeIsSkipping consumer - - let mutable maybeSkipping = true - - while (not pipeline.Halted) && (idx < terminatingIdx) do - if maybeSkipping then - maybeSkipping <- isSkipping () - - if (not maybeSkipping) then - consumer.ProcessNext (f (idx+1)) |> ignore - - idx <- idx + 1 - - (Helpers.upcastISeqComponent consumer).OnComplete () - - result + let isSkipping = makeIsSkipping consumer + try + iterate f terminatingIdx isSkipping pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () let upto lastOption f = match lastOption with @@ -1438,6 +1447,10 @@ namespace Microsoft.FSharp.Collections type EnumerableDecider<'T>(count:Nullable, f:int->'T) = inherit Enumerable.EnumerableBase<'T>() + static let iterate (enumerator:IEnumerator<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'T>) = + while (not pipeline.Halted) && (enumerator.MoveNext ()) do + consumer.ProcessNext enumerator.Current |> ignore + 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 @@ -1450,18 +1463,15 @@ namespace Microsoft.FSharp.Collections override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = let pipeline = Pipeline () - let result = f pipeline let consumer : SeqConsumer<'T,'T> = upcast result - use enumerator = (Helpers.upcastEnumerable this).GetEnumerator () - - while (not pipeline.Halted) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - - (Helpers.upcastISeqComponent consumer).OnComplete () - - result + try + iterate enumerator pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions From 3b4e50f7461d959a5a5f0b4293ef97b44bd8ca29 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 20 Oct 2016 07:24:44 -0400 Subject: [PATCH 172/286] Seq.iteri, exists, contains, forall, trypick, pick, tryfind, find, reduce, last, trylast cleanup for Seq.iter, fold Also moves the functions in the seq.fsi file to be alphabetical --- src/fsharp/FSharp.Core/seq.fs | 198 ++++++++++++++++++++++----------- src/fsharp/FSharp.Core/seq.fsi | 12 +- 2 files changed, 137 insertions(+), 73 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 7581f7d3669..789303b8258 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1481,8 +1481,15 @@ namespace Microsoft.FSharp.Collections let inline indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) [] - let toComposer (source:seq<'T>): Composer.Core.ISeq<'T> = - Composer.Seq.toComposer source + let toComposer (source:seq<'T>): SeqComposer.SeqEnumerable<'T> = + checkNonNull "source" source + match source with + | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast s + | :? array<'T> as a -> upcast SeqComposer.Array.Enumerable((fun () -> a), SeqComposer.IdentityFactory.IdentityFactory) + | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, SeqComposer.IdentityFactory.IdentityFactory) + | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory.IdentityFactory) + + let inline foreach f (source:SeqComposer.SeqEnumerable<_>) = source.ForEach f let inline foreach f (source:seq<_>) = Composer.Seq.foreach f (toComposer source) @@ -1517,17 +1524,13 @@ namespace Microsoft.FSharp.Collections [] let iter f (source : seq<'T>) = - checkNonNull "source" source - match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> - s.ForEach (fun _ -> + source + |> toComposer + |> foreach (fun _ -> { new SeqComposer.SeqConsumer<'T,'T> () with override this.ProcessNext value = - f value; true }) |> ignore - | _ -> - use e = source.GetEnumerator() - while e.MoveNext() do - f e.Current + f value; true }) + |> ignore [] let tryHead (source : seq<_>) = @@ -1557,20 +1560,67 @@ namespace Microsoft.FSharp.Collections let nth i (source : seq<'T>) = item i source [] - let iteri f (source:seq<'T>) = - Composer.Seq.iteri f (toComposer source) + let iteri f (source : seq<'T>) = + let composedSource = toComposer source + + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) + let mutable i = 0 + + composedSource.ForEach (fun _ -> + { new SeqComposer.SeqConsumer<'T,'T> () with + override this.ProcessNext value = + f.Invoke(i, value) + i <- i + 1 + true }) + |> ignore [] - let exists f (source:seq<'T>) = - Composer.Seq.exists f (toComposer source) + let exists f (source : seq<'T>) = + let exists = + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.AccumulatingConsumer<'T, bool> (false) with + override this.ProcessNext value = + if this.Accumulator then + pipeline.StopFurtherProcessing() + else + this.Accumulator <- f value + true + }) + exists.Accumulator [] - let inline contains element (source:seq<'T>) = - Composer.Seq.contains element (toComposer source) + let inline contains element (source : seq<'T>) = + let contains = + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.AccumulatingConsumer<'T, bool> (false) with + override this.ProcessNext value = + if this.Accumulator then + pipeline.StopFurtherProcessing() + else + this.Accumulator <- element = value + true + }) + contains.Accumulator [] - let forall f (source:seq<'T>) = - Composer.Seq.forall f (toComposer source) + let forall f (source : seq<'T>) = + let forall = + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.AccumulatingConsumer<'T, bool> (true) with + override this.ProcessNext value = + if this.Accumulator then + this.Accumulator <- f value + else + pipeline.StopFurtherProcessing() + true + }) + forall.Accumulator [] let iter2 f (source1 : seq<_>) (source2 : seq<_>) = @@ -1686,7 +1736,19 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source : seq<'T>) = - Composer.Seq.tryPick f (toComposer source) + let pick = + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.AccumulatingConsumer<'T, Option<'U>> (None) with + override this.ProcessNext value = + if this.Accumulator.IsNone then + this.Accumulator <- f value + else + pipeline.StopFurtherProcessing() + true + }) + pick.Accumulator [] let pick f source = @@ -1696,7 +1758,20 @@ namespace Microsoft.FSharp.Collections [] let tryFind f (source : seq<'T>) = - Composer.Seq.tryFind f (toComposer source) + let find = + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.AccumulatingConsumer<'T, Option<'T>> (None) with + override this.ProcessNext value = + if this.Accumulator.IsNone then + if f value then + this.Accumulator <- Some(value) + else + pipeline.StopFurtherProcessing() + true + }) + find.Accumulator [] let find f source = @@ -1743,24 +1818,15 @@ namespace Microsoft.FSharp.Collections [] let fold<'T,'State> f (x:'State) (source:seq<'T>) = - checkNonNull "source" source - match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let total = - s.ForEach (fun _ -> + let composedSource = toComposer source + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) + + let total = composedSource.ForEach (fun _ -> { new SeqComposer.AccumulatingConsumer<'T,'State> (x) with override this.ProcessNext value = this.Accumulator <- f.Invoke (this.Accumulator, value) true }) - total.Accumulator - | _ -> - use e = source.GetEnumerator() - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let mutable state = x - while e.MoveNext() do - state <- f.Invoke(state, e.Current) - state + total.Accumulator source |> foreach (fun _ -> @@ -1790,24 +1856,25 @@ namespace Microsoft.FSharp.Collections [] let reduce f (source : seq<'T>) = + let composedSource = toComposer source let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) + let mutable first = true - source - |> foreach (fun _ -> - { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - else - this.Value._2 <- f.Invoke (this.Value._2, value) - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun reduced -> reduced.Value._2 + let total = composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + if first then + first <- false + this.Accumulator <- value + else + this.Accumulator <- f.Invoke (this.Accumulator, value) + true + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if first then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + total.Accumulator [] let replicate count x = @@ -2178,17 +2245,6 @@ namespace Microsoft.FSharp.Collections then mkDelayedSeq (fun () -> countByValueType keyf source) else mkDelayedSeq (fun () -> countByRefType keyf source) - [] - let toComposer (source:seq<'T>): SeqComposer.SeqEnumerable<'T> = - checkNonNull "source" source - match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast s - | :? array<'T> as a -> upcast SeqComposer.Array.Enumerable((fun () -> a), SeqComposer.IdentityFactory.IdentityFactory) - | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, SeqComposer.IdentityFactory.IdentityFactory) - | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory.IdentityFactory) - - let inline foreach f (source:SeqComposer.SeqEnumerable<_>) = source.ForEach f - [] let inline sum (source:seq<'a>) : 'a = let composedSource = toComposer source @@ -2444,6 +2500,24 @@ namespace Microsoft.FSharp.Collections [] let tail (source: seq<'T>) = source |> seqFactory (SeqComposer.TailFactory ()) + + [] + let tryLast (source : seq<_>) = + let composedSource = toComposer source + let mutable first = true + + let last = + composedSource.ForEach (fun _ -> + { new SeqComposer.AccumulatingConsumer<'T, 'T> (Unchecked.defaultof<'T>) with + override this.ProcessNext value = + if first then + first <- false + this.Accumulator <- value + true }) + if first then + None + else + Some(last.Accumulator) [] let last (source : seq<_>) = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 443286c3fa0..98e95484c77 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -1155,16 +1155,6 @@ namespace Microsoft.FSharp.Collections [] val inline sortByDescending : projection:('T -> 'Key) -> source:seq<'T> -> seq<'T> when 'Key : comparison - /// Builds an SeqEnumerable from the given collection. - /// - /// The input sequence. - /// - /// The result SeqEnumerable. - /// - /// Thrown when the input sequence is null. - [] - val toComposer : source:seq<'T> -> SeqComposer.SeqEnumerable<'T> - /// Returns the sum of the elements in the sequence. /// /// The elements are summed using the + operator and Zero property associated with the generated type. @@ -1248,7 +1238,7 @@ namespace Microsoft.FSharp.Collections /// /// Thrown when the input sequence is null. [] - val toComposer : source:seq<'T> -> Composer.Core.ISeq<'T> + val toComposer : source:seq<'T> -> SeqComposer.SeqEnumerable<'T> /// Builds a list from the given collection. /// From 58b0c79a8772be119a0807c8bd03889713a5c213 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 20 Oct 2016 14:03:04 -0400 Subject: [PATCH 173/286] passing false on process next when ending. --- src/fsharp/FSharp.Core/seq.fs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 789303b8258..2274da777bf 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1584,9 +1584,10 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if this.Accumulator then pipeline.StopFurtherProcessing() + false else this.Accumulator <- f value - true + true }) exists.Accumulator @@ -1600,9 +1601,10 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if this.Accumulator then pipeline.StopFurtherProcessing() + false else this.Accumulator <- element = value - true + true }) contains.Accumulator @@ -1616,9 +1618,10 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if this.Accumulator then this.Accumulator <- f value + false else pipeline.StopFurtherProcessing() - true + true }) forall.Accumulator @@ -1744,9 +1747,10 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if this.Accumulator.IsNone then this.Accumulator <- f value + true else pipeline.StopFurtherProcessing() - true + false }) pick.Accumulator @@ -1767,9 +1771,10 @@ namespace Microsoft.FSharp.Collections if this.Accumulator.IsNone then if f value then this.Accumulator <- Some(value) + true else pipeline.StopFurtherProcessing() - true + false }) find.Accumulator From 9fb6387c4f33fd62c5a540f1354689c1e622fd70 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 20 Oct 2016 16:29:50 -0400 Subject: [PATCH 174/286] fix bug where unfold did not respect the Halted state on Result --- src/fsharp/FSharp.Core/seq.fs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 2274da777bf..91f55e81e26 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1247,9 +1247,10 @@ namespace Microsoft.FSharp.Collections let mutable current = state let rec moveNext () = - match generator current with - | None -> false - | Some (item, nextState) -> + match signal.Halted, generator current with + | true, _ + | false, None -> false + | false, Some (item, nextState) -> current <- nextState if seqComponent.ProcessNext item then true From 022a499204e04203c352ec31249bd77c00aaaea5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 13:36:33 +1100 Subject: [PATCH 175/286] Made names a little less verbose --- src/fsharp/FSharp.Core/seq.fs | 134 ++++++++++++++++----------------- src/fsharp/FSharp.Core/seq.fsi | 10 +-- 2 files changed, 72 insertions(+), 72 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 91f55e81e26..09c4ab99bcc 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -472,7 +472,7 @@ namespace Microsoft.FSharp.Collections member __.OnDispose() = () [] - type MutableData<'a,'b> = + type Values<'a,'b> = val mutable _1 : 'a val mutable _2 : 'b @@ -482,14 +482,14 @@ namespace Microsoft.FSharp.Collections } [] - type AccumulatingConsumer<'T, 'U> = + type Folder<'T, 'U> = inherit SeqConsumer<'T,'T> - val mutable Accumulator : 'U + val mutable Value : 'U - new (initialState) = { + new (init) = { inherit SeqConsumer<'T,'T>() - Accumulator = initialState + Value = init } [] @@ -1581,16 +1581,16 @@ namespace Microsoft.FSharp.Collections source |> toComposer |> foreach (fun pipeline -> - { new SeqComposer.AccumulatingConsumer<'T, bool> (false) with + { new SeqComposer.Folder<'T, bool> (false) with override this.ProcessNext value = - if this.Accumulator then + if this.Value then pipeline.StopFurtherProcessing() false else - this.Accumulator <- f value + this.Value <- f value true }) - exists.Accumulator + exists.Value [] let inline contains element (source : seq<'T>) = @@ -1598,16 +1598,16 @@ namespace Microsoft.FSharp.Collections source |> toComposer |> foreach (fun pipeline -> - { new SeqComposer.AccumulatingConsumer<'T, bool> (false) with + { new SeqComposer.Folder<'T, bool> (false) with override this.ProcessNext value = - if this.Accumulator then + if this.Value then pipeline.StopFurtherProcessing() false else - this.Accumulator <- element = value + this.Value <- element = value true }) - contains.Accumulator + contains.Value [] let forall f (source : seq<'T>) = @@ -1615,16 +1615,16 @@ namespace Microsoft.FSharp.Collections source |> toComposer |> foreach (fun pipeline -> - { new SeqComposer.AccumulatingConsumer<'T, bool> (true) with + { new SeqComposer.Folder<'T, bool> (true) with override this.ProcessNext value = - if this.Accumulator then - this.Accumulator <- f value + if this.Value then + this.Value <- f value false else pipeline.StopFurtherProcessing() true }) - forall.Accumulator + forall.Value [] let iter2 f (source1 : seq<_>) (source2 : seq<_>) = @@ -1744,16 +1744,16 @@ namespace Microsoft.FSharp.Collections source |> toComposer |> foreach (fun pipeline -> - { new SeqComposer.AccumulatingConsumer<'T, Option<'U>> (None) with + { new SeqComposer.Folder<'T, Option<'U>> (None) with override this.ProcessNext value = - if this.Accumulator.IsNone then - this.Accumulator <- f value + if this.Value.IsNone then + this.Value <- f value true else pipeline.StopFurtherProcessing() false }) - pick.Accumulator + pick.Value [] let pick f source = @@ -1767,17 +1767,17 @@ namespace Microsoft.FSharp.Collections source |> toComposer |> foreach (fun pipeline -> - { new SeqComposer.AccumulatingConsumer<'T, Option<'T>> (None) with + { new SeqComposer.Folder<'T, Option<'T>> (None) with override this.ProcessNext value = - if this.Accumulator.IsNone then + if this.Value.IsNone then if f value then - this.Accumulator <- Some(value) + this.Value <- Some(value) true else pipeline.StopFurtherProcessing() false }) - find.Accumulator + find.Value [] let find f source = @@ -1828,11 +1828,11 @@ namespace Microsoft.FSharp.Collections let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) let total = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'State> (x) with + { new SeqComposer.Folder<'T,'State> (x) with override this.ProcessNext value = - this.Accumulator <- f.Invoke (this.Accumulator, value) + this.Value <- f.Invoke (this.Value, value) true }) - total.Accumulator + total.Value source |> foreach (fun _ -> @@ -1867,20 +1867,20 @@ namespace Microsoft.FSharp.Collections let mutable first = true let total = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = if first then first <- false - this.Accumulator <- value + this.Value <- value else - this.Accumulator <- f.Invoke (this.Accumulator, value) + this.Value <- f.Invoke (this.Value, value) true interface SeqComposer.ISeqComponent with member this.OnComplete() = if first then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - total.Accumulator + total.Value [] let replicate count x = @@ -2256,22 +2256,22 @@ namespace Microsoft.FSharp.Collections let composedSource = toComposer source let total = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'a,'a> (LanguagePrimitives.GenericZero) with + { new SeqComposer.Folder<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = - this.Accumulator <- Checked.(+) this.Accumulator value + this.Value <- Checked.(+) this.Value value true }) - total.Accumulator + total.Value [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = let composedSource = toComposer source let total = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = - this.Accumulator <- Checked.(+) this.Accumulator (f value) + this.Value <- Checked.(+) this.Value (f value) true }) - total.Accumulator + total.Value [] let inline average (source: seq< ^a>) : ^a = @@ -2279,18 +2279,18 @@ namespace Microsoft.FSharp.Collections source |> toComposer |> foreach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'a, SeqComposer.MutableData<'a, int>> (SeqComposer.MutableData(LanguagePrimitives.GenericZero, 0)) with + { new SeqComposer.Folder<'a, SeqComposer.Values<'a, int>> (SeqComposer.Values(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = - this.Accumulator._1 <- Checked.(+) this.Accumulator._1 value - this.Accumulator._2 <- this.Accumulator._2 + 1 + this.Value._1 <- Checked.(+) this.Value._1 value + this.Value._2 <- this.Value._2 + 1 true interface SeqComposer.ISeqComponent with member this.OnComplete() = - if (this:?>SeqComposer.AccumulatingConsumer<'a, SeqComposer.MutableData<'a, int>>).Accumulator._2 = 0 then + if (this:?>SeqComposer.Folder<'a, SeqComposer.Values<'a, int>>).Value._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - LanguagePrimitives.DivideByInt< ^a> total.Accumulator._1 total.Accumulator._2 + LanguagePrimitives.DivideByInt< ^a> total.Value._1 total.Value._2 [] let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = @@ -2298,9 +2298,9 @@ namespace Microsoft.FSharp.Collections let mutable count = 0 let total = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = - this.Accumulator <- Checked.(+) this.Accumulator (f value) + this.Value <- Checked.(+) this.Value (f value) count <- count + 1 true interface SeqComposer.ISeqComponent with @@ -2308,7 +2308,7 @@ namespace Microsoft.FSharp.Collections if count = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - LanguagePrimitives.DivideByInt< ^U> total.Accumulator count + LanguagePrimitives.DivideByInt< ^U> total.Value count member this.OnComplete _ = if this.Value._2 = 0 then @@ -2322,20 +2322,20 @@ namespace Microsoft.FSharp.Collections let mutable first = true let min = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = if first then first <- false - this.Accumulator <- value - elif value < this.Accumulator then - this.Accumulator <- value + this.Value <- value + elif value < this.Value then + this.Value <- value true interface SeqComposer.ISeqComponent with member __.OnComplete() = if first then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - min.Accumulator + min.Value [] let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = @@ -2345,25 +2345,25 @@ namespace Microsoft.FSharp.Collections let mutable acc = Unchecked.defaultof<'U> let min = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = let currValue = value let curr = f currValue if first then first <- false acc <- curr - this.Accumulator <- value + this.Value <- value else if curr < acc then acc <- curr - this.Accumulator <- value + this.Value <- value true interface SeqComposer.ISeqComponent with member __.OnComplete() = if first then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - min.Accumulator + min.Value (* [] let inline minValBy (f : 'T -> 'U) (source: seq<'T>) : 'U = @@ -2388,21 +2388,21 @@ namespace Microsoft.FSharp.Collections let mutable first = true let max = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = if first then first <- false - this.Accumulator <- value + this.Value <- value else - if value > this.Accumulator then - this.Accumulator <- value + if value > this.Value then + this.Value <- value true interface SeqComposer.ISeqComponent with member __.OnComplete() = if first then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - max.Accumulator + max.Value [] let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = @@ -2412,25 +2412,25 @@ namespace Microsoft.FSharp.Collections let mutable acc = Unchecked.defaultof<'U> let min = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T,'T> (Unchecked.defaultof<'T>) with + { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = let currValue = value let curr = f currValue if first then first <- false acc <- curr - this.Accumulator <- value + this.Value <- value else if curr > acc then acc <- curr - this.Accumulator <- value + this.Value <- value true interface SeqComposer.ISeqComponent with member __.OnComplete() = if first then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - min.Accumulator + min.Value (* [] @@ -2514,16 +2514,16 @@ namespace Microsoft.FSharp.Collections let last = composedSource.ForEach (fun _ -> - { new SeqComposer.AccumulatingConsumer<'T, 'T> (Unchecked.defaultof<'T>) with + { new SeqComposer.Folder<'T, 'T> (Unchecked.defaultof<'T>) with override this.ProcessNext value = if first then first <- false - this.Accumulator <- value + this.Value <- value true }) if first then None else - Some(last.Accumulator) + Some(last.Value) [] let last (source : seq<_>) = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 98e95484c77..4fed145f465 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -28,19 +28,19 @@ namespace Microsoft.FSharp.Collections interface ISeqComponent [] - type MutableData<'a,'b> = + type Values<'a,'b> = struct - new : a:'a * b:'b -> MutableData<'a,'b> + new : a:'a * b:'b -> Values<'a,'b> val mutable _1: 'a val mutable _2: 'b end [] - type AccumulatingConsumer<'T,'U> = + type Folder<'T,'U> = class inherit SeqConsumer<'T,'T> - new : initialState:'U -> AccumulatingConsumer<'T,'U> - val mutable Accumulator: 'U + new : init:'U -> Folder<'T,'U> + val mutable Value: 'U end [] From da742d3870287009506810bdd4bcf28423941442 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 13:53:33 +1100 Subject: [PATCH 176/286] Fixed tryPick Processed 1 past the end of the data, as demo'd here: seq { for i = 1 to 5 do yield i failwith "boom" } |> Seq.pick (fun x -> if x = 5 then Some true else None) |> fun result -> assert result --- src/fsharp/FSharp.Core/seq.fs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 09c4ab99bcc..91364c02e3d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1740,20 +1740,18 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source : seq<'T>) = - let pick = - source - |> toComposer - |> foreach (fun pipeline -> - { new SeqComposer.Folder<'T, Option<'U>> (None) with - override this.ProcessNext value = - if this.Value.IsNone then - this.Value <- f value - true - else - pipeline.StopFurtherProcessing() - false - }) - pick.Value + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, Option<'U>> (None) with + override this.ProcessNext value = + match f value with + | None -> false + | (Some _) as some -> + this.Value <- some + pipeline.StopFurtherProcessing() + true }) + |> fun pick -> pick.Value [] let pick f source = From d0786a02aee79450391ca434f064752989c83ca3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 14:02:20 +1100 Subject: [PATCH 177/286] Fixed tryFind, similar to tryPick Error seen with seq { for i = 1 to 5 do yield i failwith "boom" } |> Seq.find (fun x -> x = 5) |> fun result -> assert (result=5) --- src/fsharp/FSharp.Core/seq.fs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 91364c02e3d..f9597d31d55 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1761,21 +1761,18 @@ namespace Microsoft.FSharp.Collections [] let tryFind f (source : seq<'T>) = - let find = - source - |> toComposer - |> foreach (fun pipeline -> - { new SeqComposer.Folder<'T, Option<'T>> (None) with - override this.ProcessNext value = - if this.Value.IsNone then - if f value then - this.Value <- Some(value) - true - else - pipeline.StopFurtherProcessing() - false - }) - find.Value + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, Option<'T>> (None) with + override this.ProcessNext value = + if f value then + this.Value <- Some value + pipeline.StopFurtherProcessing() + true + else + false }) + |> fun find -> find.Value [] let find f source = From 9d7d8688b965bdb94c3a5d91bfe65d4dabd698f1 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:31:38 +1100 Subject: [PATCH 178/286] cleaned up math functions --- src/fsharp/FSharp.Core/seq.fs | 261 ++++++++++++++++----------------- src/fsharp/FSharp.Core/seq.fsi | 9 ++ 2 files changed, 139 insertions(+), 131 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index f9597d31d55..e2d839c6aa8 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -481,6 +481,18 @@ namespace Microsoft.FSharp.Collections _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 Folder<'T, 'U> = inherit SeqConsumer<'T,'T> @@ -2248,62 +2260,58 @@ namespace Microsoft.FSharp.Collections [] let inline sum (source:seq<'a>) : 'a = - let composedSource = toComposer source - let total = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'a,'a> (LanguagePrimitives.GenericZero) with - override this.ProcessNext value = - this.Value <- Checked.(+) this.Value value - true }) - total.Value + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'a,'a> (LanguagePrimitives.GenericZero) with + override this.ProcessNext value = + this.Value <- Checked.(+) this.Value value + true }) + |> fun sum -> sum.Value [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = - let composedSource = toComposer source - let total = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with - override this.ProcessNext value = - this.Value <- Checked.(+) this.Value (f value) - true }) - total.Value + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + override this.ProcessNext value = + this.Value <- Checked.(+) this.Value (f value) + true }) + |> fun sum -> sum.Value [] let inline average (source: seq< ^a>) : ^a = - let total = - source - |> toComposer - |> foreach (fun _ -> - { new SeqComposer.Folder<'a, SeqComposer.Values<'a, int>> (SeqComposer.Values(LanguagePrimitives.GenericZero, 0)) with - override this.ProcessNext value = - this.Value._1 <- Checked.(+) this.Value._1 value - this.Value._2 <- this.Value._2 + 1 - true + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'a, SeqComposer.Values<'a, int>> (SeqComposer.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + override this.ProcessNext value = + this.Value._1 <- Checked.(+) this.Value._1 value + this.Value._2 <- this.Value._2 + 1 + true - interface SeqComposer.ISeqComponent with - member this.OnComplete() = - if (this:?>SeqComposer.Folder<'a, SeqComposer.Values<'a, int>>).Value._2 = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - LanguagePrimitives.DivideByInt< ^a> total.Value._1 total.Value._2 + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if (this:?>SeqComposer.Folder<'a, SeqComposer.Values<'a, int>>).Value._2 = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) + |> fun total -> LanguagePrimitives.DivideByInt< ^a> total.Value._1 total.Value._2 [] let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = - let composedSource = toComposer source - let mutable count = 0 - let total = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with - override this.ProcessNext value = - this.Value <- Checked.(+) this.Value (f value) - count <- count + 1 - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if count = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - LanguagePrimitives.DivideByInt< ^U> total.Value count + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T,SeqComposer.Values<'U, int>> (SeqComposer.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + override this.ProcessNext value = + this.Value._1 <- Checked.(+) this.Value._1 (f value) + this.Value._2 <- this.Value._2 + 1 + true + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if (this:?>SeqComposer.Folder<'T,SeqComposer.Values<'U, int>>).Value._2 = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) + |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.Value._1 total.Value._2 member this.OnComplete _ = if this.Value._2 = 0 then @@ -2312,53 +2320,49 @@ namespace Microsoft.FSharp.Collections [] let inline min (source: seq<_>) = - let composedSource = toComposer source + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + elif value < this.Value._2 then + this.Value._2 <- value + true - let mutable first = true - let min = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - if first then - first <- false - this.Value <- value - elif value < this.Value then - this.Value <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - min.Value + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun min -> min.Value._2 [] let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = - let composedSource = toComposer source + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + match this.Value._1, f value with + | true, valueU -> + this.Value._1 <- false + this.Value._2 <- valueU + this.Value._3 <- value + | false, valueU when valueU < this.Value._2 -> + this.Value._2 <- valueU + this.Value._3 <- value + | _ -> () + true - let mutable first = true - let mutable acc = Unchecked.defaultof<'U> - let min = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - let currValue = value - let curr = f currValue - if first then - first <- false - acc <- curr - this.Value <- value - else - if curr < acc then - acc <- curr - this.Value <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - min.Value + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun min -> min.Value._3 (* [] let inline minValBy (f : 'T -> 'U) (source: seq<'T>) : 'U = @@ -2378,54 +2382,49 @@ namespace Microsoft.FSharp.Collections *) [] let inline max (source: seq<_>) = - let composedSource = toComposer source + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + elif value > this.Value._2 then + this.Value._2 <- value + true - let mutable first = true - let max = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - if first then - first <- false - this.Value <- value - else - if value > this.Value then - this.Value <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - max.Value + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun max -> max.Value._2 [] let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = - let composedSource = toComposer source + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + match this.Value._1, f value with + | true, valueU -> + this.Value._1 <- false + this.Value._2 <- valueU + this.Value._3 <- value + | false, valueU when valueU > this.Value._2 -> + this.Value._2 <- valueU + this.Value._3 <- value + | _ -> () + true - let mutable first = true - let mutable acc = Unchecked.defaultof<'U> - let min = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - let currValue = value - let curr = f currValue - if first then - first <- false - acc <- curr - this.Value <- value - else - if curr > acc then - acc <- curr - this.Value <- value - true - interface SeqComposer.ISeqComponent with - member __.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - min.Value + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun min -> min.Value._3 (* [] diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 4fed145f465..9c1c0413e19 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -35,6 +35,15 @@ namespace Microsoft.FSharp.Collections val mutable _2: 'b end + [] + type Values<'a,'b,'c> = + struct + new : a:'a * b:'b * c:'c -> Values<'a,'b,'c> + val mutable _1: 'a + val mutable _2: 'b + val mutable _3: 'c + end + [] type Folder<'T,'U> = class From 23f0aeec4336a755a230179fe89d8eb01965ff91 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:49:17 +1100 Subject: [PATCH 179/286] Just fixing some more one past the end --- src/fsharp/FSharp.Core/seq.fs | 81 +++++++++++++++++------------------ 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index e2d839c6aa8..bcfd46a5e25 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1589,54 +1589,51 @@ namespace Microsoft.FSharp.Collections [] let exists f (source : seq<'T>) = - let exists = - source - |> toComposer - |> foreach (fun pipeline -> - { new SeqComposer.Folder<'T, bool> (false) with - override this.ProcessNext value = - if this.Value then - pipeline.StopFurtherProcessing() - false - else - this.Value <- f value - true - }) - exists.Value + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, bool> (false) with + override this.ProcessNext value = + if f value then + this.Value <- true + pipeline.StopFurtherProcessing () + false + else + true + }) + |> fun exists -> exists.Value [] let inline contains element (source : seq<'T>) = - let contains = - source - |> toComposer - |> foreach (fun pipeline -> - { new SeqComposer.Folder<'T, bool> (false) with - override this.ProcessNext value = - if this.Value then - pipeline.StopFurtherProcessing() - false - else - this.Value <- element = value - true - }) - contains.Value + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, bool> (false) with + override this.ProcessNext value = + if element = value then + this.Value <- true + pipeline.StopFurtherProcessing() + false + else + true + }) + |> fun contains -> contains.Value [] let forall f (source : seq<'T>) = - let forall = - source - |> toComposer - |> foreach (fun pipeline -> - { new SeqComposer.Folder<'T, bool> (true) with - override this.ProcessNext value = - if this.Value then - this.Value <- f value - false - else - pipeline.StopFurtherProcessing() - true - }) - forall.Value + source + |> toComposer + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, bool> (true) with + override this.ProcessNext value = + if f value then + false + else + this.Value <- false + pipeline.StopFurtherProcessing() + true + }) + |> fun forall -> forall.Value [] let iter2 f (source1 : seq<_>) (source2 : seq<_>) = From 9478acb0b744f9054d19029e120ecbf46e21772a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:53:22 +1100 Subject: [PATCH 180/286] more consistency --- src/fsharp/FSharp.Core/seq.fs | 49 ++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index bcfd46a5e25..06ca80921ce 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1828,15 +1828,16 @@ namespace Microsoft.FSharp.Collections [] let fold<'T,'State> f (x:'State) (source:seq<'T>) = - let composedSource = toComposer source let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let total = composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'State> (x) with - override this.ProcessNext value = - this.Value <- f.Invoke (this.Value, value) - true }) - total.Value + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T,'State> (x) with + override this.ProcessNext value = + this.Value <- f.Invoke (this.Value, value) + true }) + |> fun folded -> folded.Value source |> foreach (fun _ -> @@ -1866,25 +1867,25 @@ namespace Microsoft.FSharp.Collections [] let reduce f (source : seq<'T>) = - let composedSource = toComposer source let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let mutable first = true - let total = composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T,'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - if first then - first <- false - this.Value <- value - else - this.Value <- f.Invoke (this.Value, value) - true - interface SeqComposer.ISeqComponent with - member this.OnComplete() = - if first then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - total.Value + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + else + this.Value._2 <- f.Invoke (this.Value._2, value) + true + interface SeqComposer.ISeqComponent with + member this.OnComplete() = + if (this:?>SeqComposer.Folder<'T, SeqComposer.Values>).Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun reduced -> reduced.Value._2 [] let replicate count x = From 6c5d6b0cc17f43d037bb7c90b50232f784322a4d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:57:34 +1100 Subject: [PATCH 181/286] more consistency --- src/fsharp/FSharp.Core/seq.fs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 06ca80921ce..45cef4d73bb 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1880,6 +1880,7 @@ namespace Microsoft.FSharp.Collections else this.Value._2 <- f.Invoke (this.Value._2, value) true + interface SeqComposer.ISeqComponent with member this.OnComplete() = if (this:?>SeqComposer.Folder<'T, SeqComposer.Values>).Value._1 then @@ -2501,21 +2502,20 @@ namespace Microsoft.FSharp.Collections [] let tryLast (source : seq<_>) = - let composedSource = toComposer source - let mutable first = true - - let last = - composedSource.ForEach (fun _ -> - { new SeqComposer.Folder<'T, 'T> (Unchecked.defaultof<'T>) with - override this.ProcessNext value = - if first then - first <- false - this.Value <- value - true }) - if first then - None - else - Some(last.Value) + source + |> toComposer + |> foreach (fun _ -> + { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + true }) + |> fun tried -> + if tried.Value._1 then + None + else + Some tried.Value._2 [] let last (source : seq<_>) = From d21770c51fa3f7e9598f73f57d845b354ba8ce32 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 16:44:03 +1100 Subject: [PATCH 182/286] foreach now takes seq and calls toComposer --- src/fsharp/FSharp.Core/seq.fs | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 45cef4d73bb..8f9769bf538 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1502,7 +1502,10 @@ namespace Microsoft.FSharp.Collections | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, SeqComposer.IdentityFactory.IdentityFactory) | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory.IdentityFactory) - let inline foreach f (source:SeqComposer.SeqEnumerable<_>) = source.ForEach f + let inline foreach f (source:seq<_>) = + source + |> toComposer + |> fun composer -> composer.ForEach f let inline foreach f (source:seq<_>) = Composer.Seq.foreach f (toComposer source) @@ -1538,7 +1541,6 @@ namespace Microsoft.FSharp.Collections [] let iter f (source : seq<'T>) = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.SeqConsumer<'T,'T> () with override this.ProcessNext value = @@ -1590,7 +1592,6 @@ namespace Microsoft.FSharp.Collections [] let exists f (source : seq<'T>) = source - |> toComposer |> foreach (fun pipeline -> { new SeqComposer.Folder<'T, bool> (false) with override this.ProcessNext value = @@ -1606,7 +1607,6 @@ namespace Microsoft.FSharp.Collections [] let inline contains element (source : seq<'T>) = source - |> toComposer |> foreach (fun pipeline -> { new SeqComposer.Folder<'T, bool> (false) with override this.ProcessNext value = @@ -1622,7 +1622,6 @@ namespace Microsoft.FSharp.Collections [] let forall f (source : seq<'T>) = source - |> toComposer |> foreach (fun pipeline -> { new SeqComposer.Folder<'T, bool> (true) with override this.ProcessNext value = @@ -1750,7 +1749,6 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source : seq<'T>) = source - |> toComposer |> foreach (fun pipeline -> { new SeqComposer.Folder<'T, Option<'U>> (None) with override this.ProcessNext value = @@ -1771,7 +1769,6 @@ namespace Microsoft.FSharp.Collections [] let tryFind f (source : seq<'T>) = source - |> toComposer |> foreach (fun pipeline -> { new SeqComposer.Folder<'T, Option<'T>> (None) with override this.ProcessNext value = @@ -1831,7 +1828,6 @@ namespace Microsoft.FSharp.Collections let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T,'State> (x) with override this.ProcessNext value = @@ -1870,7 +1866,6 @@ namespace Microsoft.FSharp.Collections let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = @@ -2260,7 +2255,6 @@ namespace Microsoft.FSharp.Collections [] let inline sum (source:seq<'a>) : 'a = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = @@ -2271,7 +2265,6 @@ namespace Microsoft.FSharp.Collections [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = @@ -2282,7 +2275,6 @@ namespace Microsoft.FSharp.Collections [] let inline average (source: seq< ^a>) : ^a = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'a, SeqComposer.Values<'a, int>> (SeqComposer.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = @@ -2299,7 +2291,6 @@ namespace Microsoft.FSharp.Collections [] let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T,SeqComposer.Values<'U, int>> (SeqComposer.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = @@ -2320,7 +2311,6 @@ namespace Microsoft.FSharp.Collections [] let inline min (source: seq<_>) = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = @@ -2341,7 +2331,6 @@ namespace Microsoft.FSharp.Collections [] let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with override this.ProcessNext value = @@ -2382,7 +2371,6 @@ namespace Microsoft.FSharp.Collections [] let inline max (source: seq<_>) = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = @@ -2403,7 +2391,6 @@ namespace Microsoft.FSharp.Collections [] let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with override this.ProcessNext value = @@ -2503,7 +2490,6 @@ namespace Microsoft.FSharp.Collections [] let tryLast (source : seq<_>) = source - |> toComposer |> foreach (fun _ -> { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = From 910d502c4159a4cb623ce4d87ae995e7ddaafae2 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 19:37:46 +1100 Subject: [PATCH 183/286] Made ignoring return value a bit more explicit --- src/fsharp/FSharp.Core/seq.fs | 67 ++++++++++++++++------------------- 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 8f9769bf538..afcf3d1512e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -521,6 +521,9 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) + // within a foreach, the value returned by ProcessNext is ignored + let processNextInForeach = true + let seqComponentTail = { new ISeqComponent with member __.OnComplete() = () @@ -1544,7 +1547,8 @@ namespace Microsoft.FSharp.Collections |> foreach (fun _ -> { new SeqComposer.SeqConsumer<'T,'T> () with override this.ProcessNext value = - f value; true }) + f value + SeqComposer.Helpers.processNextInForeach }) |> ignore [] @@ -1576,17 +1580,14 @@ namespace Microsoft.FSharp.Collections [] let iteri f (source : seq<'T>) = - let composedSource = toComposer source - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let mutable i = 0 - - composedSource.ForEach (fun _ -> - { new SeqComposer.SeqConsumer<'T,'T> () with - override this.ProcessNext value = - f.Invoke(i, value) - i <- i + 1 - true }) + source + |> foreach (fun _ -> + { new SeqComposer.Folder<'T, int> (0) with + override this.ProcessNext value = + f.Invoke(this.Value, value) + this.Value <- this.Value + 1 + SeqComposer.Helpers.processNextInForeach }) |> ignore [] @@ -1598,9 +1599,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Value <- true pipeline.StopFurtherProcessing () - false - else - true + SeqComposer.Helpers.processNextInForeach }) |> fun exists -> exists.Value @@ -1613,9 +1612,7 @@ namespace Microsoft.FSharp.Collections if element = value then this.Value <- true pipeline.StopFurtherProcessing() - false - else - true + SeqComposer.Helpers.processNextInForeach }) |> fun contains -> contains.Value @@ -1625,12 +1622,10 @@ namespace Microsoft.FSharp.Collections |> foreach (fun pipeline -> { new SeqComposer.Folder<'T, bool> (true) with override this.ProcessNext value = - if f value then - false - else + if not (f value) then this.Value <- false pipeline.StopFurtherProcessing() - true + SeqComposer.Helpers.processNextInForeach }) |> fun forall -> forall.Value @@ -1753,11 +1748,11 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.Folder<'T, Option<'U>> (None) with override this.ProcessNext value = match f value with - | None -> false | (Some _) as some -> this.Value <- some pipeline.StopFurtherProcessing() - true }) + | None -> () + SeqComposer.Helpers.processNextInForeach }) |> fun pick -> pick.Value [] @@ -1775,9 +1770,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Value <- Some value pipeline.StopFurtherProcessing() - true - else - false }) + SeqComposer.Helpers.processNextInForeach }) |> fun find -> find.Value [] @@ -1832,7 +1825,7 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.Folder<'T,'State> (x) with override this.ProcessNext value = this.Value <- f.Invoke (this.Value, value) - true }) + SeqComposer.Helpers.processNextInForeach }) |> fun folded -> folded.Value source @@ -1874,7 +1867,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value else this.Value._2 <- f.Invoke (this.Value._2, value) - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2259,7 +2252,7 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.Folder<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value value - true }) + SeqComposer.Helpers.processNextInForeach }) |> fun sum -> sum.Value [] @@ -2269,7 +2262,7 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value (f value) - true }) + SeqComposer.Helpers.processNextInForeach }) |> fun sum -> sum.Value [] @@ -2280,7 +2273,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 value this.Value._2 <- this.Value._2 + 1 - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2296,7 +2289,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 (f value) this.Value._2 <- this.Value._2 + 1 - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = if (this:?>SeqComposer.Folder<'T,SeqComposer.Values<'U, int>>).Value._2 = 0 then @@ -2319,7 +2312,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value elif value < this.Value._2 then this.Value._2 <- value - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2343,7 +2336,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- valueU this.Value._3 <- value | _ -> () - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2379,7 +2372,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value elif value > this.Value._2 then this.Value._2 <- value - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2403,7 +2396,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- valueU this.Value._3 <- value | _ -> () - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2496,7 +2489,7 @@ namespace Microsoft.FSharp.Collections if this.Value._1 then this.Value._1 <- false this.Value._2 <- value - true }) + SeqComposer.Helpers.processNextInForeach }) |> fun tried -> if tried.Value._1 then None From 2efbf33df17b613508db53b1d21af62b11b1727d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 22 Oct 2016 12:38:03 +1100 Subject: [PATCH 184/286] processNextInForeach was a bit verbose --- src/fsharp/FSharp.Core/seq.fs | 39 ++++++++++++++++------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index afcf3d1512e..9290f86edc7 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -521,9 +521,6 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) - // within a foreach, the value returned by ProcessNext is ignored - let processNextInForeach = true - let seqComponentTail = { new ISeqComponent with member __.OnComplete() = () @@ -1548,7 +1545,7 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.SeqConsumer<'T,'T> () with override this.ProcessNext value = f value - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> ignore [] @@ -1587,7 +1584,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = f.Invoke(this.Value, value) this.Value <- this.Value + 1 - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> ignore [] @@ -1599,7 +1596,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Value <- true pipeline.StopFurtherProcessing () - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof }) |> fun exists -> exists.Value @@ -1612,7 +1609,7 @@ namespace Microsoft.FSharp.Collections if element = value then this.Value <- true pipeline.StopFurtherProcessing() - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof }) |> fun contains -> contains.Value @@ -1625,7 +1622,7 @@ namespace Microsoft.FSharp.Collections if not (f value) then this.Value <- false pipeline.StopFurtherProcessing() - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof }) |> fun forall -> forall.Value @@ -1752,7 +1749,7 @@ namespace Microsoft.FSharp.Collections this.Value <- some pipeline.StopFurtherProcessing() | None -> () - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> fun pick -> pick.Value [] @@ -1770,7 +1767,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Value <- Some value pipeline.StopFurtherProcessing() - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> fun find -> find.Value [] @@ -1825,7 +1822,7 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.Folder<'T,'State> (x) with override this.ProcessNext value = this.Value <- f.Invoke (this.Value, value) - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> fun folded -> folded.Value source @@ -1867,7 +1864,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value else this.Value._2 <- f.Invoke (this.Value._2, value) - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2252,7 +2249,7 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.Folder<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value value - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> fun sum -> sum.Value [] @@ -2262,7 +2259,7 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value (f value) - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> fun sum -> sum.Value [] @@ -2273,7 +2270,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 value this.Value._2 <- this.Value._2 + 1 - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2289,7 +2286,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 (f value) this.Value._2 <- this.Value._2 + 1 - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete() = if (this:?>SeqComposer.Folder<'T,SeqComposer.Values<'U, int>>).Value._2 = 0 then @@ -2312,7 +2309,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value elif value < this.Value._2 then this.Value._2 <- value - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2336,7 +2333,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- valueU this.Value._3 <- value | _ -> () - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2372,7 +2369,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value elif value > this.Value._2 then this.Value._2 <- value - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2396,7 +2393,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- valueU this.Value._3 <- value | _ -> () - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2489,7 +2486,7 @@ namespace Microsoft.FSharp.Collections if this.Value._1 then this.Value._1 <- false this.Value._2 <- value - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> fun tried -> if tried.Value._1 then None From b0d933d441a488579a0ad5f2d8e61c52e19484b1 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 22 Oct 2016 13:42:57 +1100 Subject: [PATCH 185/286] Consolidated ForEach functionality --- src/fsharp/FSharp.Core/seq.fs | 194 ++++++++++++---------------------- 1 file changed, 70 insertions(+), 124 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 9290f86edc7..fb17047e96f 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -957,6 +957,68 @@ namespace Microsoft.FSharp.Collections interface ISeqPipeline with member x.StopFurtherProcessing() = halted <- true member __.Halted = halted + module ForEach = + let enumerable (enumerable:IEnumerable<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + use enumerator = enumerable.GetEnumerator () + while (not pipeline.Halted) && (enumerator.MoveNext ()) do + consumer.ProcessNext enumerator.Current |> ignore + + let array (array:array<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let mutable idx = 0 + while (not pipeline.Halted) && (idx < array.Length) do + consumer.ProcessNext array.[idx] |> ignore + idx <- idx + 1 + + let list (alist:list<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let rec iterate lst = + match pipeline.Halted, lst with + | true, _ + | false, [] -> () + | false, hd :: tl -> + consumer.ProcessNext hd |> ignore + iterate tl + iterate alist + + let unfold (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let rec iterate current = + match pipeline.Halted, generator current with + | true, _ + | false, None -> () + | false, Some (item, next) -> + consumer.ProcessNext item |> ignore + iterate next + + iterate state + + let makeIsSkipping (consumer:SeqConsumer<'T,'U>) = + match consumer with + | :? SeqComponent<'T,'U> as c -> c.Skipping + | _ -> fun () -> false + + let init f (terminatingIdx:int) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let mutable idx = -1 + let isSkipping = makeIsSkipping consumer + let mutable maybeSkipping = true + while (not pipeline.Halted) && (idx < terminatingIdx) do + if maybeSkipping then + maybeSkipping <- isSkipping () + + if (not maybeSkipping) then + consumer.ProcessNext (f (idx+1)) |> ignore + + idx <- idx + 1 + + let execute (f:ISeqPipeline->#SeqConsumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = + let pipeline = Pipeline() + let result = f pipeline + let consumer = current.Create pipeline result + try + executeOn pipeline consumer + (Helpers.upcastISeqComponent consumer).OnComplete () + result + finally + (Helpers.upcastISeqComponent consumer).OnDispose () + module Enumerable = [] type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) = @@ -1025,10 +1087,6 @@ namespace Microsoft.FSharp.Collections and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = inherit EnumerableBase<'U>() - static let iterate (enumerator:IEnumerator<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = - while (not pipeline.Halted) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1038,16 +1096,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let pipeline = Pipeline() - let result = f pipeline - let consumer = current.Create pipeline result - use enumerator = enumerable.GetEnumerator () - try - iterate enumerator pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () - result - finally - (Helpers.upcastISeqComponent consumer).OnDispose () + ForEach.execute f current (ForEach.enumerable enumerable) and AppendEnumerator<'T> (sources:list>) = let sources = sources |> List.rev @@ -1091,10 +1140,6 @@ namespace Microsoft.FSharp.Collections and AppendEnumerable<'T> (sources:list>) = inherit EnumerableBase<'T>() - static let iterate (enumerator:IEnumerator<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = - while (not pipeline.Halted) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = Helpers.upcastEnumerator (new AppendEnumerator<_> (sources)) @@ -1106,17 +1151,8 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = - let pipeline = Pipeline() - let result = f pipeline - let consumer : SeqConsumer<'T,'T> = upcast result let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) - use enumerator = enumerable.GetEnumerator () - try - iterate enumerator pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () - result - finally - (Helpers.upcastISeqComponent consumer).OnDispose () + ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable enumerable) let create enumerable current = Helpers.upcastEnumerable (Enumerable(enumerable, current)) @@ -1156,12 +1192,6 @@ namespace Microsoft.FSharp.Collections type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() - static let iterate (array:array<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = - let mutable idx = 0 - while (not pipeline.Halted) && (idx < array.Length) do - consumer.ProcessNext array.[idx] |> ignore - idx <- idx + 1 - interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1171,15 +1201,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let pipeline = Pipeline () - let result = f pipeline - let consumer = current.Create pipeline result - try - iterate (delayedArray ()) pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () - result - finally - (Helpers.upcastISeqComponent consumer).OnDispose () + ForEach.execute f current (ForEach.array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = Helpers.upcastEnumerable (Enumerable(delayedArray, current)) @@ -1217,16 +1239,6 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext list - let iterate (alist:list<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = - let rec iterate lst = - match pipeline.Halted, lst with - | true, _ - | false, [] -> () - | false, hd :: tl -> - consumer.ProcessNext hd |> ignore - iterate tl - iterate alist - type Enumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() @@ -1239,15 +1251,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let pipeline = Pipeline () - let result = f pipeline - let consumer = current.Create pipeline result - try - iterate alist pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () - result - finally - (Helpers.upcastISeqComponent consumer).OnDispose () + ForEach.execute f current (ForEach.list alist) let create alist current = Helpers.upcastEnumerable (Enumerable(alist, current)) @@ -1277,17 +1281,6 @@ namespace Microsoft.FSharp.Collections type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() - static let iterate (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = - let rec iterate current = - match pipeline.Halted, generator current with - | true, _ - | false, None -> () - | false, Some (item, next) -> - consumer.ProcessNext item |> ignore - iterate next - - iterate state - interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1297,15 +1290,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = - let pipeline = Pipeline () - let result = f pipeline - let consumer = current.Create pipeline result - try - iterate generator state pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () - result - finally - (Helpers.upcastISeqComponent consumer).OnDispose () + ForEach.execute f current (ForEach.unfold generator state) module Init = // The original implementation of "init" delayed the calculation of Current, and so it was possible @@ -1327,16 +1312,11 @@ namespace Microsoft.FSharp.Collections else System.Int32.MaxValue - let makeIsSkipping (consumer:SeqConsumer<'T,'U>) = - match consumer with - | :? SeqComponent<'T,'U> as c -> c.Skipping - | _ -> fun () -> false - type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqConsumer<'T,'U>, signal:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) let isSkipping = - makeIsSkipping seqComponent + ForEach.makeIsSkipping seqComponent let terminatingIdx = getTerminatingIdx count @@ -1374,18 +1354,6 @@ namespace Microsoft.FSharp.Collections type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() - static let iterate f (terminatingIdx:int) (isSkipping) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = - let mutable idx = -1 - let mutable maybeSkipping = true - while (not pipeline.Halted) && (idx < terminatingIdx) do - if maybeSkipping then - maybeSkipping <- isSkipping () - - if (not maybeSkipping) then - consumer.ProcessNext (f (idx+1)) |> ignore - - idx <- idx + 1 - interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () @@ -1395,17 +1363,8 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) override this.ForEach (createResult:ISeqPipeline->#SeqConsumer<'U,'U>) = - let pipeline = Pipeline () - let result = createResult pipeline - let consumer = current.Create pipeline result let terminatingIdx = getTerminatingIdx count - let isSkipping = makeIsSkipping consumer - try - iterate f terminatingIdx isSkipping pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () - result - finally - (Helpers.upcastISeqComponent consumer).OnDispose () + ForEach.execute createResult current (ForEach.init f terminatingIdx) let upto lastOption f = match lastOption with @@ -1460,10 +1419,6 @@ namespace Microsoft.FSharp.Collections type EnumerableDecider<'T>(count:Nullable, f:int->'T) = inherit Enumerable.EnumerableBase<'T>() - static let iterate (enumerator:IEnumerator<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'T>) = - while (not pipeline.Halted) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - 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 @@ -1475,16 +1430,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = - let pipeline = Pipeline () - let result = f pipeline - let consumer : SeqConsumer<'T,'T> = upcast result - use enumerator = (Helpers.upcastEnumerable this).GetEnumerator () - try - iterate enumerator pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () - result - finally - (Helpers.upcastISeqComponent consumer).OnDispose () + ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable (Helpers.upcastEnumerable this)) #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions From b67e9317514e3b36be53732743e38b78b8087432 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 22 Oct 2016 18:06:21 +1100 Subject: [PATCH 186/286] Seq.concat --- src/fsharp/FSharp.Core/seq.fs | 67 +++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index fb17047e96f..35bfe316e5e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -164,7 +164,7 @@ namespace Microsoft.FSharp.Core.CompilerServices member x.GetEnumerator() = f() interface IEnumerable with member x.GetEnumerator() = (f() :> IEnumerator) } - + [] type EmptyEnumerable<'T> = | EmptyEnumerable @@ -1020,6 +1020,21 @@ namespace Microsoft.FSharp.Collections (Helpers.upcastISeqComponent consumer).OnDispose () 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>, seqComponent:ISeqComponent) = interface IDisposable with @@ -1098,24 +1113,25 @@ namespace Microsoft.FSharp.Collections override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = ForEach.execute f current (ForEach.enumerable enumerable) - and AppendEnumerator<'T> (sources:list>) = - let sources = sources |> List.rev - + and ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = let mutable state = SeqProcessNextStates.NotStarted - let mutable remaining = sources.Tail - let mutable active = sources.Head.GetEnumerator () + let main = sources.GetEnumerator () + + let mutable active = + if main.MoveNext () + then main.Current.GetEnumerator () + else EmptyEnumerators.Element let rec moveNext () = - if active.MoveNext () then true + if active.MoveNext () then + true + elif main.MoveNext () then + active.Dispose () + active <- main.Current.GetEnumerator () + moveNext () else - match remaining with - | [] -> false - | hd :: tl -> - active.Dispose () - active <- hd.GetEnumerator () - remaining <- tl - - moveNext () + state <- SeqProcessNextStates.Finished + false interface IEnumerator<'T> with member __.Current = @@ -1135,6 +1151,7 @@ namespace Microsoft.FSharp.Collections interface IDisposable with member __.Dispose() = + main.Dispose () active.Dispose () and AppendEnumerable<'T> (sources:list>) = @@ -1142,7 +1159,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - Helpers.upcastEnumerator (new AppendEnumerator<_> (sources)) + Helpers.upcastEnumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(this, next)) @@ -1151,8 +1168,20 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = - let enumerable = Helpers.upcastEnumerable (AppendEnumerable sources) - ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable enumerable) + ForEach.execute f IdentityFactory.IdentityFactory (ForEach.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> = + Helpers.upcastEnumerator (new ConcatEnumerator<_,_> (sources)) + + override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = + Helpers.upcastEnumerable (Enumerable<'T,'V>(this, next)) + + override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = + ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) let create enumerable current = Helpers.upcastEnumerable (Enumerable(enumerable, current)) @@ -1743,7 +1772,7 @@ namespace Microsoft.FSharp.Collections [] let concat (sources:seq<#seq<'T>>) : seq<'T> = checkNonNull "sources" sources - upcast Composer.Seq.Enumerable.ConcatEnumerable sources + upcast SeqComposer.Enumerable.ConcatEnumerable sources [] let length (source : seq<'T>) = From 1b279b3948fbb63a983372838363b19b00816690 Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 22 Oct 2016 07:29:55 -0400 Subject: [PATCH 187/286] findIndex/tryFindIndex --- src/fsharp/FSharp.Core/seq.fs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 35bfe316e5e..df607ae19eb 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1989,15 +1989,16 @@ namespace Microsoft.FSharp.Collections [] let tryFindIndex p (source:seq<_>) = source - |> foreach (fun halt -> - { new Composer.Core.Folder<'T, Composer.Core.Values, int>> (Composer.Core.Values<_,_>(None, 0)) with + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, SeqComposer.Values, int>> (SeqComposer.Values<_,_>(None, 0)) with override this.ProcessNext value = if p value then this.Value._1 <- Some(this.Value._2) - halt () + pipeline.StopFurtherProcessing() else this.Value._2 <- this.Value._2 + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof + }) |> fun tried -> tried.Value._1 [] From fc8e9031cf70d3bf930914463b9c3b23089354b6 Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 22 Oct 2016 10:38:32 -0400 Subject: [PATCH 188/286] fix bug with Concat when there are side effects --- src/fsharp/FSharp.Core/seq.fs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index df607ae19eb..4631006915a 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1117,10 +1117,7 @@ namespace Microsoft.FSharp.Collections let mutable state = SeqProcessNextStates.NotStarted let main = sources.GetEnumerator () - let mutable active = - if main.MoveNext () - then main.Current.GetEnumerator () - else EmptyEnumerators.Element + let mutable active = EmptyEnumerators.Element let rec moveNext () = if active.MoveNext () then From b135d985c5a7ac318edd378683986adf5edc9a74 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 23 Oct 2016 19:30:44 +1100 Subject: [PATCH 189/286] Fix a Take bug The following caused an exception, when it shouldn't: [1;2;3] |> Seq.take 100 |> Seq.takeWhile (fun _ -> false) |> Seq.iter (fun _ -> ()) I'm not 100% happy with how I'm allocating ids, nor really with the added ceremony of the solution, but I think the idea of how to resolve is basically the right one. --- src/fsharp/FSharp.Core/seq.fs | 275 ++++++++++++++++----------------- src/fsharp/FSharp.Core/seq.fsi | 4 +- 2 files changed, 139 insertions(+), 140 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 4631006915a..5d7977b443e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -457,18 +457,18 @@ namespace Microsoft.FSharp.Collections open IEnumerator type ISeqComponent = - abstract OnComplete : unit -> unit + abstract OnComplete : int -> unit abstract OnDispose : unit -> unit type ISeqPipeline = - abstract StopFurtherProcessing : unit -> unit + abstract StopFurtherProcessing : int -> unit [] type SeqConsumer<'T,'U> () = abstract ProcessNext : input:'T -> bool interface ISeqComponent with - member __.OnComplete() = () + member __.OnComplete _ = () member __.OnDispose() = () [] @@ -523,133 +523,135 @@ namespace Microsoft.FSharp.Collections let seqComponentTail = { new ISeqComponent with - member __.OnComplete() = () + member __.OnComplete _ = () member __.OnDispose() = () } type [] SeqComponentFactory<'T,'U> () = - abstract Create<'V> : ISeqPipeline -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> + abstract Create<'V> : ISeqPipeline -> SeqConsumer<'U,'V> -> haltingIdx:int -> SeqConsumer<'T,'V> and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = inherit SeqComponentFactory<'T,'V> () - override __.Create<'W> (result:ISeqPipeline) (next:SeqConsumer<'V,'W>) : SeqConsumer<'T,'W> = - first.Create result (second.Create result next) + override __.Create<'W> (result:ISeqPipeline) (next:SeqConsumer<'V,'W>) (haltingIdx:int) : SeqConsumer<'T,'W> = + first.Create result (second.Create result next (haltingIdx+1)) (haltingIdx+2) static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = upcast ComposedFactory(first, second) and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Choose (filter, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Choose (filter, next, haltingIdx) and DistinctFactory<'T when 'T: equality> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Distinct (next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Distinct (next, haltingIdx) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next, haltingIdx) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next, haltingIdx) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = match next with - | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter - | _ -> upcast Filter (filter, next) + | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter haltingIdx + | _ -> upcast Filter (filter, next, haltingIdx) and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () static let singleton = IdentityFactory<'T>() - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = next + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (_haltingIdx:int) : SeqConsumer<'T,'V> = next static member IdentityFactory = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = match next with - | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map - | _ -> upcast Map<_,_,_> (map, next) + | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map haltingIdx + | _ -> upcast Map<_,_,_> (map, next, haltingIdx) and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next, haltingIdx) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = inherit SeqComponentFactory<'Second,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next, haltingIdx) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, haltingIdx) and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next, haltingIdx) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next, haltingIdx) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T*'T,'V>) : SeqConsumer<'T,'V> = upcast Pairwise next + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T*'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Pairwise (next, haltingIdx) and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Skip (count, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Skip (count, next, haltingIdx) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next, haltingIdx) and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next, haltingIdx) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Take (count, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Take (count, result, next, haltingIdx) and TailFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next) + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next, haltingIdx) and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next) + override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next, haltingIdx) - and [] SeqComponent<'T,'U> (next:ISeqComponent) = + and [] SeqComponent<'T,'U> (next:ISeqComponent, haltingIdx:int) = inherit SeqConsumer<'T,'U>() // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip // and it can only do it at the start of a sequence abstract Skipping : unit -> bool - abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> - abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> + abstract CreateMap<'S> : map:('S->'T) -> haltingIdx:int -> SeqComponent<'S,'U> + abstract CreateFilter : filter:('T->bool) -> haltingIdx:int -> SeqComponent<'T,'U> interface ISeqComponent with - member __.OnComplete () = next.OnComplete () + member __.OnComplete halted = next.OnComplete halted member __.OnDispose () = next.OnDispose () + member __.HaltingIdx = haltingIdx + default __.Skipping () = false - default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) - default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) + default this.CreateMap<'S> (map:'S->'T) (haltingIdx:int) = upcast Map<_,_,_> (map, this, haltingIdx) + default this.CreateFilter (filter:'T->bool) (haltingIdx:int) = upcast Filter (filter, this, haltingIdx) - and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) + and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) override __.ProcessNext (input:'T) : bool = match choose input with | Some value -> Helpers.avoidTailCall (next.ProcessNext value) | None -> false - and Distinct<'T,'V when 'T: equality> (next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and Distinct<'T,'V when 'T: equality> (next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) @@ -659,8 +661,8 @@ namespace Microsoft.FSharp.Collections else false - and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) @@ -670,8 +672,8 @@ namespace Microsoft.FSharp.Collections else false - and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) @@ -681,10 +683,10 @@ namespace Microsoft.FSharp.Collections else false - and Filter<'T,'V> (filter:'T->bool, next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and Filter<'T,'V> (filter:'T->bool, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) - override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) + override this.CreateMap<'S> (map:'S->'T) (haltingIdx:int) = upcast MapThenFilter<_,_,_> (map, filter, next, haltingIdx) override __.ProcessNext (input:'T) : bool = if filter input then @@ -692,8 +694,8 @@ namespace Microsoft.FSharp.Collections else false - and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) + and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) override __.ProcessNext (input:'T) : bool = if filter input then @@ -701,16 +703,16 @@ namespace Microsoft.FSharp.Collections else false - and Map<'T,'U,'V> (map:'T->'U, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) + and Map<'T,'U,'V> (map:'T->'U, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) - override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) + override this.CreateFilter (filter:'T->bool) (haltingIdx:int) = upcast FilterThenMap (filter, map, next, haltingIdx) override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'First,'V>(next) + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'First,'V>(next, haltingIdx) let input2 = enumerable2.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -719,7 +721,7 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) else - result.StopFurtherProcessing () + result.StopFurtherProcessing haltingIdx false interface ISeqComponent with @@ -729,8 +731,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'Second,'V>(next) + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'Second,'V>(next, haltingIdx) let input1 = enumerable1.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -739,7 +741,7 @@ namespace Microsoft.FSharp.Collections if input1.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) else - result.StopFurtherProcessing () + result.StopFurtherProcessing haltingIdx false interface ISeqComponent with @@ -749,8 +751,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'First,'V>(next) + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'First,'V>(next, haltingIdx) let input2 = enumerable2.GetEnumerator () let input3 = enumerable3.GetEnumerator () @@ -760,7 +762,7 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () && input3.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) else - result.StopFurtherProcessing () + result.StopFurtherProcessing haltingIdx false interface ISeqComponent with @@ -773,8 +775,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) override __.ProcessNext (input:'T) : bool = let u = map input @@ -783,8 +785,8 @@ namespace Microsoft.FSharp.Collections else false - and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) + and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let mutable idx = 0 let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi @@ -793,8 +795,8 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>) = - inherit SeqComponent<'First,'V>(next) + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = + inherit SeqComponent<'First,'V>(next, haltingIdx) let mutable idx = 0 let input2 = enumerable2.GetEnumerator () @@ -805,7 +807,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) else - result.StopFurtherProcessing () + result.StopFurtherProcessing haltingIdx false interface ISeqComponent with @@ -815,8 +817,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Pairwise<'T,'V> (next:SeqConsumer<'T*'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and Pairwise<'T,'V> (next:SeqConsumer<'T*'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let mutable isFirst = true let mutable lastValue = Unchecked.defaultof<'T> @@ -831,8 +833,8 @@ namespace Microsoft.FSharp.Collections lastValue <- input Helpers.avoidTailCall (next.ProcessNext currentPair) - and Skip<'T,'V> (skipCount:int, next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and Skip<'T,'V> (skipCount:int, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let mutable count = 0 @@ -851,15 +853,15 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext input) interface ISeqComponent with - override __.OnComplete () = + override __.OnComplete halted = if count < skipCount then let x = skipCount - count invalidOpFmt "tried to skip {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete () + (Helpers.upcastISeqComponent next).OnComplete halted - and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let mutable skip = true @@ -873,29 +875,29 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>) = - inherit Truncate<'T, 'V>(takeCount, result, next) + and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit Truncate<'T, 'V>(takeCount, result, next, haltingIdx) interface ISeqComponent with - override this.OnComplete () = - if this.Count < takeCount then + override this.OnComplete halted = + if halted = 0 || halted > haltingIdx && this.Count < takeCount then let x = takeCount - this.Count invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete () + (Helpers.upcastISeqComponent next).OnComplete halted - and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) override __.ProcessNext (input:'T) : bool = if predicate input then Helpers.avoidTailCall (next.ProcessNext input) else - result.StopFurtherProcessing () + result.StopFurtherProcessing haltingIdx false - and Tail<'T, 'V> (next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and Tail<'T, 'V> (next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let mutable first = true @@ -907,13 +909,13 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext input) interface ISeqComponent with - override this.OnComplete () = + override this.OnComplete halted = if first then invalidArg "source" (SR.GetString(SR.notEnoughElements)) - (Helpers.upcastISeqComponent next).OnComplete () + (Helpers.upcastISeqComponent next).OnComplete halted - and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) let mutable count = 0 @@ -923,10 +925,10 @@ namespace Microsoft.FSharp.Collections if count < truncateCount then count <- count + 1 if count = truncateCount then - result.StopFurtherProcessing () + result.StopFurtherProcessing haltingIdx next.ProcessNext input else - result.StopFurtherProcessing () + result.StopFurtherProcessing haltingIdx false type SeqProcessNextStates = @@ -935,14 +937,14 @@ namespace Microsoft.FSharp.Collections | Finished = 2 type Result<'T>() = - let mutable halted = false + let mutable haltedIdx = 0 member val Current = Unchecked.defaultof<'T> with get, set member val SeqState = SeqProcessNextStates.NotStarted with get, set - member __.Halted = halted + member __.Halted = haltedIdx interface ISeqPipeline with - member __.StopFurtherProcessing () = halted <- true + member __.StopFurtherProcessing haltingIdx = haltedIdx <- haltingIdx // SetResult<> is used at the end of the chain of SeqComponents to assign the final value type SetResult<'T> (result:Result<'T>) = @@ -953,40 +955,38 @@ namespace Microsoft.FSharp.Collections true type Pipeline() = - let mutable halted = false - interface ISeqPipeline with member x.StopFurtherProcessing() = halted <- true + let mutable halted = 0 + interface ISeqPipeline with member x.StopFurtherProcessing haltingIdx = halted <- haltingIdx member __.Halted = halted module ForEach = let enumerable (enumerable:IEnumerable<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = use enumerator = enumerable.GetEnumerator () - while (not pipeline.Halted) && (enumerator.MoveNext ()) do + while (pipeline.Halted = 0) && (enumerator.MoveNext ()) do consumer.ProcessNext enumerator.Current |> ignore let array (array:array<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = let mutable idx = 0 - while (not pipeline.Halted) && (idx < array.Length) do + while (pipeline.Halted = 0) && (idx < array.Length) do consumer.ProcessNext array.[idx] |> ignore idx <- idx + 1 let list (alist:list<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = let rec iterate lst = match pipeline.Halted, lst with - | true, _ - | false, [] -> () - | false, hd :: tl -> + | 0, hd :: tl -> consumer.ProcessNext hd |> ignore iterate tl + | _ -> () iterate alist let unfold (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = let rec iterate current = match pipeline.Halted, generator current with - | true, _ - | false, None -> () - | false, Some (item, next) -> + | 0, Some (item, next) -> consumer.ProcessNext item |> ignore iterate next + | _ -> () iterate state @@ -999,7 +999,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = -1 let isSkipping = makeIsSkipping consumer let mutable maybeSkipping = true - while (not pipeline.Halted) && (idx < terminatingIdx) do + while (pipeline.Halted = 0) && (idx < terminatingIdx) do if maybeSkipping then maybeSkipping <- isSkipping () @@ -1011,10 +1011,10 @@ namespace Microsoft.FSharp.Collections let execute (f:ISeqPipeline->#SeqConsumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = let pipeline = Pipeline() let result = f pipeline - let consumer = current.Create pipeline result + let consumer = current.Create pipeline result 1 try executeOn pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete () + (Helpers.upcastISeqComponent consumer).OnComplete pipeline.Halted result finally (Helpers.upcastISeqComponent consumer).OnDispose () @@ -1077,14 +1077,14 @@ namespace Microsoft.FSharp.Collections inherit EnumeratorBase<'U>(result, seqComponent) let rec moveNext () = - if (not result.Halted) && source.MoveNext () then + if (result.Halted = 0) && source.MoveNext () then if seqComponent.ProcessNext source.Current then true else moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete result.Halted false interface IEnumerator with @@ -1105,7 +1105,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (SetResult<'U> result) 1, result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) @@ -1199,7 +1199,7 @@ namespace Microsoft.FSharp.Collections initMoveNext <- ignore let rec moveNext () = - if (not result.Halted) && idx < array.Length then + if (result.Halted = 0) && idx < array.Length then idx <- idx+1 if seqComponent.ProcessNext array.[idx-1] then true @@ -1207,7 +1207,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete result.Halted false interface IEnumerator with @@ -1221,7 +1221,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (SetResult<'U> result) 1, result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) @@ -1249,7 +1249,7 @@ namespace Microsoft.FSharp.Collections let rec moveNext current = match result.Halted, current with - | false, head::tail -> + | 0, head::tail -> if seqComponent.ProcessNext head then list <- tail true @@ -1257,7 +1257,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete result.Halted false interface IEnumerator with @@ -1271,7 +1271,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (SetResult<'U> result) 1, result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) @@ -1290,14 +1290,13 @@ namespace Microsoft.FSharp.Collections let rec moveNext () = match signal.Halted, generator current with - | true, _ - | false, None -> false - | false, Some (item, nextState) -> + | 0, Some (item, nextState) -> current <- nextState if seqComponent.ProcessNext item then true else moveNext () + | _ -> false interface IEnumerator with member __.MoveNext () = @@ -1310,7 +1309,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (SetResult<'U> result) 1, result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) @@ -1351,7 +1350,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = -1 let rec moveNext () = - if (not signal.Halted) && idx < terminatingIdx then + if (signal.Halted = 0) && idx < terminatingIdx then idx <- idx + 1 if maybeSkipping then @@ -1365,11 +1364,11 @@ namespace Microsoft.FSharp.Collections true else moveNext () - elif (not signal.Halted) && idx = System.Int32.MaxValue then + elif (signal.Halted = 0) && idx = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else signal.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete signal.Halted false interface IEnumerator with @@ -1383,7 +1382,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (SetResult<'U> result) 1, result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) @@ -1567,7 +1566,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if f value then this.Value <- true - pipeline.StopFurtherProcessing () + pipeline.StopFurtherProcessing 1 Unchecked.defaultof }) |> fun exists -> exists.Value @@ -1580,7 +1579,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if element = value then this.Value <- true - pipeline.StopFurtherProcessing() + pipeline.StopFurtherProcessing 1 Unchecked.defaultof }) |> fun contains -> contains.Value @@ -1593,7 +1592,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if not (f value) then this.Value <- false - pipeline.StopFurtherProcessing() + pipeline.StopFurtherProcessing 1 Unchecked.defaultof }) |> fun forall -> forall.Value @@ -1719,7 +1718,7 @@ namespace Microsoft.FSharp.Collections match f value with | (Some _) as some -> this.Value <- some - pipeline.StopFurtherProcessing() + pipeline.StopFurtherProcessing 1 | None -> () Unchecked.defaultof }) |> fun pick -> pick.Value @@ -1738,7 +1737,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if f value then this.Value <- Some value - pipeline.StopFurtherProcessing() + pipeline.StopFurtherProcessing 1 Unchecked.defaultof }) |> fun find -> find.Value @@ -1839,7 +1838,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof interface SeqComposer.ISeqComponent with - member this.OnComplete() = + member this.OnComplete _ = if (this:?>SeqComposer.Folder<'T, SeqComposer.Values>).Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) @@ -1991,7 +1990,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = if p value then this.Value._1 <- Some(this.Value._2) - pipeline.StopFurtherProcessing() + pipeline.StopFurtherProcessing 1 else this.Value._2 <- this.Value._2 + 1 Unchecked.defaultof @@ -2246,7 +2245,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof interface SeqComposer.ISeqComponent with - member this.OnComplete() = + member this.OnComplete _ = if (this:?>SeqComposer.Folder<'a, SeqComposer.Values<'a, int>>).Value._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun total -> LanguagePrimitives.DivideByInt< ^a> total.Value._1 total.Value._2 @@ -2261,7 +2260,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- this.Value._2 + 1 Unchecked.defaultof interface SeqComposer.ISeqComponent with - member this.OnComplete() = + member this.OnComplete _ = if (this:?>SeqComposer.Folder<'T,SeqComposer.Values<'U, int>>).Value._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.Value._1 total.Value._2 @@ -2285,7 +2284,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof interface SeqComposer.ISeqComponent with - member this.OnComplete() = + member this.OnComplete _ = if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) @@ -2309,7 +2308,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof interface SeqComposer.ISeqComponent with - member this.OnComplete() = + member this.OnComplete _ = if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) @@ -2345,7 +2344,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof interface SeqComposer.ISeqComponent with - member this.OnComplete() = + member this.OnComplete _ = if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) @@ -2369,7 +2368,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof interface SeqComposer.ISeqComponent with - member this.OnComplete() = + member this.OnComplete _ = if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 9c1c0413e19..b3fdc5639da 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -15,11 +15,11 @@ namespace Microsoft.FSharp.Collections module Seq = module SeqComposer = type ISeqComponent = - abstract OnComplete : unit -> unit + abstract OnComplete : int -> unit abstract OnDispose : unit -> unit type ISeqPipeline = - abstract StopFurtherProcessing : unit -> unit + abstract StopFurtherProcessing : int -> unit [] type SeqConsumer<'T,'U> = From f48c4a80180fe06c44bce0e4b1779a0fef3d8dc5 Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 22 Oct 2016 17:04:03 -0400 Subject: [PATCH 190/286] Seq.scan --- src/fsharp/FSharp.Core/seq.fs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 5d7977b443e..0a358001be8 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -597,6 +597,10 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'T*'T> () override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T*'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Pairwise (next, haltingIdx) + and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = + inherit SeqComponentFactory<'T,'State> () + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'State,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next, haltingIdx) + and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Skip (count, next, haltingIdx) @@ -833,6 +837,16 @@ namespace Microsoft.FSharp.Collections lastValue <- input Helpers.avoidTailCall (next.ProcessNext currentPair) + and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:SeqConsumer<'State,'V>, haltingIdx:int) = + inherit SeqComponent<'T,'V>(next, haltingIdx) + + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder + let mutable foldResult = initialState + + override __.ProcessNext (input:'T) : bool = + foldResult <- f.Invoke(foldResult, input) + Helpers.avoidTailCall (next.ProcessNext foldResult) + and Skip<'T,'V> (skipCount:int, next:SeqConsumer<'T,'V>, haltingIdx:int) = inherit SeqComponent<'T,'V>(next, haltingIdx) @@ -1961,8 +1975,8 @@ namespace Microsoft.FSharp.Collections [] let scan<'T,'State> f (z:'State) (source : seq<'T>): seq<'State> = let first = [|z|] :> IEnumerable<'State> - let rest = source |> seqFactory (Composer.Seq.ScanFactory (f, z)) - upcast Composer.Seq.Enumerable.ConcatEnumerable [|first; rest;|] + let rest = source |> seqFactory (SeqComposer.ScanFactory (f, z)) + upcast SeqComposer.Enumerable.ConcatEnumerable [|first; rest;|] [] let tryFindBack f (source : seq<'T>) = From c13e59902c7823781669c2426f1fcecdafa4615b Mon Sep 17 00:00:00 2001 From: liboz Date: Sun, 23 Oct 2016 10:05:30 -0400 Subject: [PATCH 191/286] Seq.tryItem, tryHead, head, exactlyOne --- src/fsharp/FSharp.Core/seq.fs | 56 +++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 0a358001be8..ee553cff95f 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1554,8 +1554,19 @@ namespace Microsoft.FSharp.Collections | Some value -> value [] - let tryItem i (source:seq<'T>) = - Composer.Seq.tryItem i (toComposer source) + let tryItem i (source : seq<'T>) = + if i < 0 then None else + source + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, SeqComposer.Values>> (SeqComposer.Values<_, _> (0, None)) with + override this.ProcessNext value = + if this.Value._1 = i then + this.Value._2 <- Some value + pipeline.StopFurtherProcessing 1 + else + this.Value._1 <- this.Value._1 + 1 + Unchecked.defaultof }) + |> fun item -> item.Value._2 [] let nth i (source : seq<'T>) = item i source @@ -2420,25 +2431,23 @@ namespace Microsoft.FSharp.Collections use e2 = source2.GetEnumerator() let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(p) - source1 - |> foreach (fun halt -> - { new Composer.Core.Folder<_,bool> (true) with - override this.ProcessNext value = - if (e2.MoveNext()) then - if not (p.Invoke(value, e2.Current)) then - this.Value <- false - halt() - else - halt() - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun all -> all.Value - [] let exists2 p (source1: seq<_>) (source2: seq<_>) = checkNonNull "source2" source2 use e2 = source2.GetEnumerator() let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(p) + + [] + let tryHead (source : seq<_>) = + source + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, Option<'T>> (None) with + override this.ProcessNext value = + this.Value <- Some value + pipeline.StopFurtherProcessing 1 + Unchecked.defaultof }) + |> fun head -> head.Value source1 |> foreach (fun halt -> @@ -2488,16 +2497,25 @@ namespace Microsoft.FSharp.Collections [] let exactlyOne (source : seq<_>) = source - |> foreach (fun halt -> - { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values(true, Unchecked.defaultof<'T>, false)) with + |> foreach (fun pipeline -> + { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values(true, Unchecked.defaultof<'T>, false)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false this.Value._2 <- value else this.Value._3 <- true - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + pipeline.StopFurtherProcessing 1 + Unchecked.defaultof + interface SeqComposer.ISeqComponent with + member this.OnComplete _ = + let value = (this:?>SeqComposer.Folder<'T,SeqComposer.Values>) + if value.Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + elif value.Value._3 then + invalidArg "source" (SR.GetString(SR.inputSequenceTooLong)) + }) + |> fun one -> one.Value._2 member this.OnComplete _ = if this.Value._1 then From 7a0a563f64877504442913070175eb4982376f64 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 24 Oct 2016 20:17:12 +1100 Subject: [PATCH 192/286] Another take on halting index - Shrank public interface by removing ISeqPipeline from ForEach. - Renamed haltingIdx to pipelineDepth - Removed haltingIdx from where I could --- src/fsharp/FSharp.Core/seq.fs | 284 +++++++++++++++++---------------- src/fsharp/FSharp.Core/seq.fsi | 5 +- 2 files changed, 150 insertions(+), 139 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ee553cff95f..e36b91248b5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -506,7 +506,7 @@ namespace Microsoft.FSharp.Collections [] type SeqEnumerable<'T>() = - abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:(ISeqPipeline->'a) -> 'a + abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:((unit->unit)->'a) -> 'a module Helpers = // used for performance reasons; these are not recursive calls, so should be safe @@ -527,135 +527,149 @@ namespace Microsoft.FSharp.Collections member __.OnDispose() = () } type [] SeqComponentFactory<'T,'U> () = - abstract Create<'V> : ISeqPipeline -> SeqConsumer<'U,'V> -> haltingIdx:int -> SeqConsumer<'T,'V> + let mutable pipelineDepth = Nullable () + + abstract Create<'V> : ISeqPipeline -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> + + member __.PipelineDepth = + if pipelineDepth.HasValue + then pipelineDepth.Value + else 1 + + member __.SetPipelineDepth depth = + if pipelineDepth.HasValue + then failwith "libray implementation error: factory depth can only be set once" + else pipelineDepth <- Nullable depth and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = inherit SeqComponentFactory<'T,'V> () - override __.Create<'W> (result:ISeqPipeline) (next:SeqConsumer<'V,'W>) (haltingIdx:int) : SeqConsumer<'T,'W> = - first.Create result (second.Create result next (haltingIdx+1)) (haltingIdx+2) + override __.Create<'W> (result:ISeqPipeline) (next:SeqConsumer<'V,'W>) : SeqConsumer<'T,'W> = + first.Create result (second.Create result next) static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = - upcast ComposedFactory(first, second) + let composed = ComposedFactory(first, second) + let nextDepth = first.PipelineDepth + 1 + second.SetPipelineDepth nextDepth + composed.SetPipelineDepth nextDepth + upcast composed and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Choose (filter, next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Choose (filter, next) and DistinctFactory<'T when 'T: equality> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Distinct (next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = match next with - | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter haltingIdx - | _ -> upcast Filter (filter, next, haltingIdx) + | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter + | _ -> upcast Filter (filter, next) and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () static let singleton = IdentityFactory<'T>() - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (_haltingIdx:int) : SeqConsumer<'T,'V> = next + override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = next static member IdentityFactory = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = match next with - | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map haltingIdx - | _ -> upcast Map<_,_,_> (map, next, haltingIdx) + | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map + | _ -> upcast Map<_,_,_> (map, next) and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next, haltingIdx) + override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next, this.PipelineDepth) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = inherit SeqComponentFactory<'Second,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next, haltingIdx) + override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next, this.PipelineDepth) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, haltingIdx) + override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, this.PipelineDepth) and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) (haltingIdx:int) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next, haltingIdx) + override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next, this.PipelineDepth) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T*'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Pairwise (next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T*'T,'V>) : SeqConsumer<'T,'V> = upcast Pairwise (next) and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = inherit SeqComponentFactory<'T,'State> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'State,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'State,'V>) : SeqConsumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Skip (count, next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next, haltingIdx) + override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next, this.PipelineDepth) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Take (count, result, next, haltingIdx) + override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Take (count, result, next, this.PipelineDepth) and TailFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next, haltingIdx) + override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override __.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) (haltingIdx:int) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next, haltingIdx) + override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next, this.PipelineDepth) - and [] SeqComponent<'T,'U> (next:ISeqComponent, haltingIdx:int) = + and [] SeqComponent<'T,'U> (next:ISeqComponent) = inherit SeqConsumer<'T,'U>() // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip // and it can only do it at the start of a sequence abstract Skipping : unit -> bool - abstract CreateMap<'S> : map:('S->'T) -> haltingIdx:int -> SeqComponent<'S,'U> - abstract CreateFilter : filter:('T->bool) -> haltingIdx:int -> SeqComponent<'T,'U> + abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> + abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> interface ISeqComponent with - member __.OnComplete halted = next.OnComplete halted + member __.OnComplete terminatingDepth = next.OnComplete terminatingDepth member __.OnDispose () = next.OnDispose () - member __.HaltingIdx = haltingIdx - default __.Skipping () = false - default this.CreateMap<'S> (map:'S->'T) (haltingIdx:int) = upcast Map<_,_,_> (map, this, haltingIdx) - default this.CreateFilter (filter:'T->bool) (haltingIdx:int) = upcast Filter (filter, this, haltingIdx) + default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) + default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) - and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqConsumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = match choose input with | Some value -> Helpers.avoidTailCall (next.ProcessNext value) | None -> false - and Distinct<'T,'V when 'T: equality> (next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Distinct<'T,'V when 'T: equality> (next:SeqConsumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) @@ -665,8 +679,8 @@ namespace Microsoft.FSharp.Collections else false - and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqConsumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) @@ -676,8 +690,8 @@ namespace Microsoft.FSharp.Collections else false - and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqConsumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) @@ -687,10 +701,10 @@ namespace Microsoft.FSharp.Collections else false - and Filter<'T,'V> (filter:'T->bool, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Filter<'T,'V> (filter:'T->bool, next:SeqConsumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) - override this.CreateMap<'S> (map:'S->'T) (haltingIdx:int) = upcast MapThenFilter<_,_,_> (map, filter, next, haltingIdx) + override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) override __.ProcessNext (input:'T) : bool = if filter input then @@ -698,8 +712,8 @@ namespace Microsoft.FSharp.Collections else false - and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqConsumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = if filter input then @@ -707,16 +721,16 @@ namespace Microsoft.FSharp.Collections else false - and Map<'T,'U,'V> (map:'T->'U, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Map<'T,'U,'V> (map:'T->'U, next:SeqConsumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) - override this.CreateFilter (filter:'T->bool) (haltingIdx:int) = upcast FilterThenMap (filter, map, next, haltingIdx) + override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'First,'V>(next, haltingIdx) + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -725,7 +739,7 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) else - result.StopFurtherProcessing haltingIdx + result.StopFurtherProcessing pipelineDepth false interface ISeqComponent with @@ -735,8 +749,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'Second,'V>(next, haltingIdx) + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + inherit SeqComponent<'Second,'V>(next) let input1 = enumerable1.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -745,7 +759,7 @@ namespace Microsoft.FSharp.Collections if input1.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) else - result.StopFurtherProcessing haltingIdx + result.StopFurtherProcessing pipelineDepth false interface ISeqComponent with @@ -755,8 +769,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'First,'V>(next, haltingIdx) + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () let input3 = enumerable3.GetEnumerator () @@ -766,7 +780,7 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () && input3.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) else - result.StopFurtherProcessing haltingIdx + result.StopFurtherProcessing pipelineDepth false interface ISeqComponent with @@ -779,8 +793,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqConsumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = let u = map input @@ -789,8 +803,8 @@ namespace Microsoft.FSharp.Collections else false - and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqConsumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) let mutable idx = 0 let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi @@ -799,8 +813,8 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, haltingIdx:int) = - inherit SeqComponent<'First,'V>(next, haltingIdx) + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + inherit SeqComponent<'First,'V>(next) let mutable idx = 0 let input2 = enumerable2.GetEnumerator () @@ -811,7 +825,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) else - result.StopFurtherProcessing haltingIdx + result.StopFurtherProcessing pipelineDepth false interface ISeqComponent with @@ -821,8 +835,8 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Pairwise<'T,'V> (next:SeqConsumer<'T*'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Pairwise<'T,'V> (next:SeqConsumer<'T*'T,'V>) = + inherit SeqComponent<'T,'V>(next) let mutable isFirst = true let mutable lastValue = Unchecked.defaultof<'T> @@ -837,8 +851,8 @@ namespace Microsoft.FSharp.Collections lastValue <- input Helpers.avoidTailCall (next.ProcessNext currentPair) - and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:SeqConsumer<'State,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:SeqConsumer<'State,'V>) = + inherit SeqComponent<'T,'V>(next) let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let mutable foldResult = initialState @@ -847,8 +861,8 @@ namespace Microsoft.FSharp.Collections foldResult <- f.Invoke(foldResult, input) Helpers.avoidTailCall (next.ProcessNext foldResult) - and Skip<'T,'V> (skipCount:int, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Skip<'T,'V> (skipCount:int, next:SeqConsumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -867,15 +881,15 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext input) interface ISeqComponent with - override __.OnComplete halted = + override __.OnComplete terminatingDepth = if count < skipCount then let x = skipCount - count invalidOpFmt "tried to skip {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete halted + (Helpers.upcastISeqComponent next).OnComplete terminatingDepth - and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) let mutable skip = true @@ -889,29 +903,29 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit Truncate<'T, 'V>(takeCount, result, next, haltingIdx) + and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineDepth:int) = + inherit Truncate<'T, 'V>(takeCount, result, next, pipelineDepth) interface ISeqComponent with - override this.OnComplete halted = - if halted = 0 || halted > haltingIdx && this.Count < takeCount then + override this.OnComplete terminatingDepth = + if terminatingDepth < pipelineDepth && this.Count < takeCount then let x = takeCount - this.Count invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete halted + (Helpers.upcastISeqComponent next).OnComplete terminatingDepth - and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineDepth:int) = + inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = if predicate input then Helpers.avoidTailCall (next.ProcessNext input) else - result.StopFurtherProcessing haltingIdx + result.StopFurtherProcessing pipelineDepth false - and Tail<'T, 'V> (next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Tail<'T, 'V> (next:SeqConsumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) let mutable first = true @@ -923,13 +937,13 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext input) interface ISeqComponent with - override this.OnComplete halted = + override this.OnComplete terminatingDepth = if first then invalidArg "source" (SR.GetString(SR.notEnoughElements)) - (Helpers.upcastISeqComponent next).OnComplete halted + (Helpers.upcastISeqComponent next).OnComplete terminatingDepth - and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, haltingIdx:int) = - inherit SeqComponent<'T,'V>(next, haltingIdx) + and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineDepth:int) = + inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -939,10 +953,10 @@ namespace Microsoft.FSharp.Collections if count < truncateCount then count <- count + 1 if count = truncateCount then - result.StopFurtherProcessing haltingIdx + result.StopFurtherProcessing pipelineDepth next.ProcessNext input else - result.StopFurtherProcessing haltingIdx + result.StopFurtherProcessing pipelineDepth false type SeqProcessNextStates = @@ -951,14 +965,14 @@ namespace Microsoft.FSharp.Collections | Finished = 2 type Result<'T>() = - let mutable haltedIdx = 0 + let mutable haltedDepth = 0 member val Current = Unchecked.defaultof<'T> with get, set member val SeqState = SeqProcessNextStates.NotStarted with get, set - member __.Halted = haltedIdx + member __.Halted = haltedDepth interface ISeqPipeline with - member __.StopFurtherProcessing haltingIdx = haltedIdx <- haltingIdx + member __.StopFurtherProcessing pipelineDepth = haltedDepth <- pipelineDepth // SetResult<> is used at the end of the chain of SeqComponents to assign the final value type SetResult<'T> (result:Result<'T>) = @@ -969,9 +983,9 @@ namespace Microsoft.FSharp.Collections true type Pipeline() = - let mutable halted = 0 - interface ISeqPipeline with member x.StopFurtherProcessing haltingIdx = halted <- haltingIdx - member __.Halted = halted + let mutable haltedDepth = 0 + interface ISeqPipeline with member x.StopFurtherProcessing pipelineDepth = haltedDepth <- pipelineDepth + member __.Halted = haltedDepth module ForEach = let enumerable (enumerable:IEnumerable<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = @@ -1022,10 +1036,10 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 - let execute (f:ISeqPipeline->#SeqConsumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = + let execute (f:(unit->unit)->#SeqConsumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = let pipeline = Pipeline() - let result = f pipeline - let consumer = current.Create pipeline result 1 + let result = f (fun () -> (pipeline:>ISeqPipeline).StopFurtherProcessing (current.PipelineDepth+1)) + let consumer = current.Create pipeline result try executeOn pipeline consumer (Helpers.upcastISeqComponent consumer).OnComplete pipeline.Halted @@ -1119,12 +1133,12 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (SetResult<'U> result) 1, result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = ForEach.execute f current (ForEach.enumerable enumerable) and ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = @@ -1178,7 +1192,7 @@ namespace Microsoft.FSharp.Collections override this.Append source = Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = + override this.ForEach (f:(unit->unit)->#SeqConsumer<'T,'T>) = ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) and ConcatEnumerable<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = @@ -1191,7 +1205,7 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(this, next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = + override this.ForEach (f:(unit->unit)->#SeqConsumer<'T,'T>) = ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) let create enumerable current = @@ -1235,12 +1249,12 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (SetResult<'U> result) 1, result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = ForEach.execute f current (ForEach.array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = @@ -1285,12 +1299,12 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (SetResult<'U> result) 1, result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = ForEach.execute f current (ForEach.list alist) let create alist current = @@ -1323,12 +1337,12 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (SetResult<'U> result) 1, result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (SetResult<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = ForEach.execute f current (ForEach.unfold generator state) module Init = @@ -1396,12 +1410,12 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (SetResult<'U> result) 1, result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (SetResult<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) - override this.ForEach (createResult:ISeqPipeline->#SeqConsumer<'U,'U>) = + override this.ForEach (createResult:(unit->unit)->#SeqConsumer<'U,'U>) = let terminatingIdx = getTerminatingIdx count ForEach.execute createResult current (ForEach.init f terminatingIdx) @@ -1468,7 +1482,7 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) - override this.ForEach (f:ISeqPipeline->#SeqConsumer<'T,'T>) = + override this.ForEach (f:(unit->unit)->#SeqConsumer<'T,'T>) = ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable (Helpers.upcastEnumerable this)) #if FX_NO_ICLONEABLE @@ -1557,12 +1571,12 @@ namespace Microsoft.FSharp.Collections let tryItem i (source : seq<'T>) = if i < 0 then None else source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, SeqComposer.Values>> (SeqComposer.Values<_, _> (0, None)) with override this.ProcessNext value = if this.Value._1 = i then this.Value._2 <- Some value - pipeline.StopFurtherProcessing 1 + halt () else this.Value._1 <- this.Value._1 + 1 Unchecked.defaultof }) @@ -1586,12 +1600,12 @@ namespace Microsoft.FSharp.Collections [] let exists f (source : seq<'T>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, bool> (false) with override this.ProcessNext value = if f value then this.Value <- true - pipeline.StopFurtherProcessing 1 + halt () Unchecked.defaultof }) |> fun exists -> exists.Value @@ -1599,12 +1613,12 @@ namespace Microsoft.FSharp.Collections [] let inline contains element (source : seq<'T>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, bool> (false) with override this.ProcessNext value = if element = value then this.Value <- true - pipeline.StopFurtherProcessing 1 + halt () Unchecked.defaultof }) |> fun contains -> contains.Value @@ -1612,12 +1626,12 @@ namespace Microsoft.FSharp.Collections [] let forall f (source : seq<'T>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, bool> (true) with override this.ProcessNext value = if not (f value) then this.Value <- false - pipeline.StopFurtherProcessing 1 + halt () Unchecked.defaultof }) |> fun forall -> forall.Value @@ -1737,13 +1751,13 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source : seq<'T>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, Option<'U>> (None) with override this.ProcessNext value = match f value with | (Some _) as some -> this.Value <- some - pipeline.StopFurtherProcessing 1 + halt () | None -> () Unchecked.defaultof }) |> fun pick -> pick.Value @@ -1757,12 +1771,12 @@ namespace Microsoft.FSharp.Collections [] let tryFind f (source : seq<'T>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, Option<'T>> (None) with override this.ProcessNext value = if f value then this.Value <- Some value - pipeline.StopFurtherProcessing 1 + halt () Unchecked.defaultof }) |> fun find -> find.Value @@ -2010,12 +2024,12 @@ namespace Microsoft.FSharp.Collections [] let tryFindIndex p (source:seq<_>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, SeqComposer.Values, int>> (SeqComposer.Values<_,_>(None, 0)) with override this.ProcessNext value = if p value then this.Value._1 <- Some(this.Value._2) - pipeline.StopFurtherProcessing 1 + halt () else this.Value._2 <- this.Value._2 + 1 Unchecked.defaultof @@ -2441,11 +2455,11 @@ namespace Microsoft.FSharp.Collections [] let tryHead (source : seq<_>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, Option<'T>> (None) with override this.ProcessNext value = this.Value <- Some value - pipeline.StopFurtherProcessing 1 + halt () Unchecked.defaultof }) |> fun head -> head.Value @@ -2497,7 +2511,7 @@ namespace Microsoft.FSharp.Collections [] let exactlyOne (source : seq<_>) = source - |> foreach (fun pipeline -> + |> foreach (fun halt -> { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values(true, Unchecked.defaultof<'T>, false)) with override this.ProcessNext value = if this.Value._1 then @@ -2505,7 +2519,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value else this.Value._3 <- true - pipeline.StopFurtherProcessing 1 + halt () Unchecked.defaultof interface SeqComposer.ISeqComponent with member this.OnComplete _ = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index b3fdc5639da..dd5ee5d9016 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -18,9 +18,6 @@ namespace Microsoft.FSharp.Collections abstract OnComplete : int -> unit abstract OnDispose : unit -> unit - type ISeqPipeline = - abstract StopFurtherProcessing : int -> unit - [] type SeqConsumer<'T,'U> = new : unit -> SeqConsumer<'T,'U> @@ -54,7 +51,7 @@ namespace Microsoft.FSharp.Collections [] type SeqEnumerable<'T> = - abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:(ISeqPipeline->'a) -> 'a + abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:((unit->unit)->'a) -> 'a /// Returns a new sequence that contains the cartesian product of the two input sequences. /// The first sequence. From 49d44c47e03a35667a2e308341f72b56e6129b23 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 25 Oct 2016 19:21:05 +1100 Subject: [PATCH 193/286] Remove mutable state in SeqComponentFactory - Changed "depth" to "idx" to better communicate the function --- src/fsharp/FSharp.Core/seq.fs | 183 ++++++++++++++++----------------- src/fsharp/FSharp.Core/seq.fsi | 4 +- 2 files changed, 92 insertions(+), 95 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index e36b91248b5..9fd7c389580 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -456,12 +456,18 @@ namespace Microsoft.FSharp.Collections module SeqComposer = open IEnumerator + type PipeIdx = int + type ``PipeIdx?`` = Nullable + let emptyPipeIdx = Nullable () + let inline getPipeIdx (maybePipeIdx:``PipeIdx?``) = if maybePipeIdx.HasValue then maybePipeIdx.Value else 1 + let inline makePipeIdx (pipeIdx:PipeIdx) = Nullable pipeIdx + type ISeqComponent = - abstract OnComplete : int -> unit + abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit type ISeqPipeline = - abstract StopFurtherProcessing : int -> unit + abstract StopFurtherProcessing : PipeIdx -> unit [] type SeqConsumer<'T,'U> () = @@ -526,52 +532,41 @@ namespace Microsoft.FSharp.Collections member __.OnComplete _ = () member __.OnDispose() = () } - type [] SeqComponentFactory<'T,'U> () = - let mutable pipelineDepth = Nullable () + type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = + abstract Create<'V> : ISeqPipeline -> ``PipeIdx?`` -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> - abstract Create<'V> : ISeqPipeline -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> + new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) - member __.PipelineDepth = - if pipelineDepth.HasValue - then pipelineDepth.Value - else 1 + member __.PipeIdx = getPipeIdx pipeIdx - member __.SetPipelineDepth depth = - if pipelineDepth.HasValue - then failwith "libray implementation error: factory depth can only be set once" - else pipelineDepth <- Nullable depth + and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>, secondPipeIdx:PipeIdx) = + inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) - and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) = - inherit SeqComponentFactory<'T,'V> () - override __.Create<'W> (result:ISeqPipeline) (next:SeqConsumer<'V,'W>) : SeqConsumer<'T,'W> = - first.Create result (second.Create result next) + override this.Create<'W> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'V,'W>) : SeqConsumer<'T,'W> = + first.Create result pipeIdx (second.Create result (makePipeIdx secondPipeIdx) next) static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = - let composed = ComposedFactory(first, second) - let nextDepth = first.PipelineDepth + 1 - second.SetPipelineDepth nextDepth - composed.SetPipelineDepth nextDepth - upcast composed + upcast ComposedFactory(first, second, first.PipeIdx+1) and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Choose (filter, next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Choose (filter, next) and DistinctFactory<'T when 'T: equality> () = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Distinct (next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = match next with | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter | _ -> upcast Filter (filter, next) @@ -579,67 +574,67 @@ namespace Microsoft.FSharp.Collections and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () static let singleton = IdentityFactory<'T>() - override __.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = next + override __.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = next static member IdentityFactory = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = match next with | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map | _ -> upcast Map<_,_,_> (map, next) and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next, this.PipelineDepth) + override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next, getPipeIdx pipeIdx) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = inherit SeqComponentFactory<'Second,'U> () - override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next, this.PipelineDepth) + override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next, getPipeIdx pipeIdx) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, this.PipelineDepth) + override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, getPipeIdx pipeIdx) and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next, this.PipelineDepth) + override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next, getPipeIdx pipeIdx) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T*'T,'V>) : SeqConsumer<'T,'V> = upcast Pairwise (next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T*'T,'V>) : SeqConsumer<'T,'V> = upcast Pairwise (next) and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = inherit SeqComponentFactory<'T,'State> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'State,'V>) : SeqConsumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'State,'V>) : SeqConsumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Skip (count, next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next, this.PipelineDepth) + override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next, getPipeIdx pipeIdx) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Take (count, result, next, this.PipelineDepth) + override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Take (count, result, next, getPipeIdx pipeIdx) and TailFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next) + override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:ISeqPipeline) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next, this.PipelineDepth) + override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next, getPipeIdx pipeIdx) and [] SeqComponent<'T,'U> (next:ISeqComponent) = inherit SeqConsumer<'T,'U>() @@ -652,7 +647,7 @@ namespace Microsoft.FSharp.Collections abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> interface ISeqComponent with - member __.OnComplete terminatingDepth = next.OnComplete terminatingDepth + member __.OnComplete terminatingIdx = next.OnComplete terminatingIdx member __.OnDispose () = next.OnDispose () default __.Skipping () = false @@ -729,7 +724,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -739,7 +734,7 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) else - result.StopFurtherProcessing pipelineDepth + result.StopFurtherProcessing pipeIdx false interface ISeqComponent with @@ -749,7 +744,7 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'Second,'V>(next) let input1 = enumerable1.GetEnumerator () @@ -759,7 +754,7 @@ namespace Microsoft.FSharp.Collections if input1.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) else - result.StopFurtherProcessing pipelineDepth + result.StopFurtherProcessing pipeIdx false interface ISeqComponent with @@ -769,7 +764,7 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent next).OnDispose () - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -780,7 +775,7 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () && input3.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) else - result.StopFurtherProcessing pipelineDepth + result.StopFurtherProcessing pipeIdx false interface ISeqComponent with @@ -813,7 +808,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipelineDepth:int) = + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let mutable idx = 0 @@ -825,7 +820,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) else - result.StopFurtherProcessing pipelineDepth + result.StopFurtherProcessing pipeIdx false interface ISeqComponent with @@ -881,12 +876,12 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext input) interface ISeqComponent with - override __.OnComplete terminatingDepth = + override __.OnComplete terminatingIdx = if count < skipCount then let x = skipCount - count invalidOpFmt "tried to skip {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete terminatingDepth + (Helpers.upcastISeqComponent next).OnComplete terminatingIdx and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -903,25 +898,25 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineDepth:int) = - inherit Truncate<'T, 'V>(takeCount, result, next, pipelineDepth) + and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineIdx:int) = + inherit Truncate<'T, 'V>(takeCount, result, next, pipelineIdx) interface ISeqComponent with - override this.OnComplete terminatingDepth = - if terminatingDepth < pipelineDepth && this.Count < takeCount then + override this.OnComplete terminatingIdx = + if terminatingIdx < pipelineIdx && this.Count < takeCount then let x = takeCount - this.Count invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete terminatingDepth + (Helpers.upcastISeqComponent next).OnComplete terminatingIdx - and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineDepth:int) = + and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = if predicate input then Helpers.avoidTailCall (next.ProcessNext input) else - result.StopFurtherProcessing pipelineDepth + result.StopFurtherProcessing pipeIdx false and Tail<'T, 'V> (next:SeqConsumer<'T,'V>) = @@ -937,12 +932,12 @@ namespace Microsoft.FSharp.Collections Helpers.avoidTailCall (next.ProcessNext input) interface ISeqComponent with - override this.OnComplete terminatingDepth = + override this.OnComplete terminatingIdx = if first then invalidArg "source" (SR.GetString(SR.notEnoughElements)) - (Helpers.upcastISeqComponent next).OnComplete terminatingDepth + (Helpers.upcastISeqComponent next).OnComplete terminatingIdx - and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineDepth:int) = + and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -953,10 +948,10 @@ namespace Microsoft.FSharp.Collections if count < truncateCount then count <- count + 1 if count = truncateCount then - result.StopFurtherProcessing pipelineDepth + result.StopFurtherProcessing pipeIdx next.ProcessNext input else - result.StopFurtherProcessing pipelineDepth + result.StopFurtherProcessing pipeIdx false type SeqProcessNextStates = @@ -965,14 +960,14 @@ namespace Microsoft.FSharp.Collections | Finished = 2 type Result<'T>() = - let mutable haltedDepth = 0 + let mutable haltedIdx = 0 member val Current = Unchecked.defaultof<'T> with get, set member val SeqState = SeqProcessNextStates.NotStarted with get, set - member __.Halted = haltedDepth + member __.HaltedIdx = haltedIdx interface ISeqPipeline with - member __.StopFurtherProcessing pipelineDepth = haltedDepth <- pipelineDepth + member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx // SetResult<> is used at the end of the chain of SeqComponents to assign the final value type SetResult<'T> (result:Result<'T>) = @@ -983,25 +978,25 @@ namespace Microsoft.FSharp.Collections true type Pipeline() = - let mutable haltedDepth = 0 - interface ISeqPipeline with member x.StopFurtherProcessing pipelineDepth = haltedDepth <- pipelineDepth - member __.Halted = haltedDepth + let mutable haltedIdx = 0 + interface ISeqPipeline with member x.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx + member __.HaltedIdx = haltedIdx module ForEach = let enumerable (enumerable:IEnumerable<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = use enumerator = enumerable.GetEnumerator () - while (pipeline.Halted = 0) && (enumerator.MoveNext ()) do + while (pipeline.HaltedIdx = 0) && (enumerator.MoveNext ()) do consumer.ProcessNext enumerator.Current |> ignore let array (array:array<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = let mutable idx = 0 - while (pipeline.Halted = 0) && (idx < array.Length) do + while (pipeline.HaltedIdx = 0) && (idx < array.Length) do consumer.ProcessNext array.[idx] |> ignore idx <- idx + 1 let list (alist:list<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = let rec iterate lst = - match pipeline.Halted, lst with + match pipeline.HaltedIdx, lst with | 0, hd :: tl -> consumer.ProcessNext hd |> ignore iterate tl @@ -1010,7 +1005,7 @@ namespace Microsoft.FSharp.Collections let unfold (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = let rec iterate current = - match pipeline.Halted, generator current with + match pipeline.HaltedIdx, generator current with | 0, Some (item, next) -> consumer.ProcessNext item |> ignore iterate next @@ -1027,7 +1022,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = -1 let isSkipping = makeIsSkipping consumer let mutable maybeSkipping = true - while (pipeline.Halted = 0) && (idx < terminatingIdx) do + while (pipeline.HaltedIdx = 0) && (idx < terminatingIdx) do if maybeSkipping then maybeSkipping <- isSkipping () @@ -1038,11 +1033,11 @@ namespace Microsoft.FSharp.Collections let execute (f:(unit->unit)->#SeqConsumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = let pipeline = Pipeline() - let result = f (fun () -> (pipeline:>ISeqPipeline).StopFurtherProcessing (current.PipelineDepth+1)) - let consumer = current.Create pipeline result + let result = f (fun () -> (pipeline:>ISeqPipeline).StopFurtherProcessing (current.PipeIdx+1)) + let consumer = current.Create pipeline emptyPipeIdx result try executeOn pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete pipeline.Halted + (Helpers.upcastISeqComponent consumer).OnComplete pipeline.HaltedIdx result finally (Helpers.upcastISeqComponent consumer).OnDispose () @@ -1105,14 +1100,14 @@ namespace Microsoft.FSharp.Collections inherit EnumeratorBase<'U>(result, seqComponent) let rec moveNext () = - if (result.Halted = 0) && source.MoveNext () then + if (result.HaltedIdx = 0) && source.MoveNext () then if seqComponent.ProcessNext source.Current then true else moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete result.Halted + (Helpers.upcastISeqComponent seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1133,7 +1128,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) @@ -1227,7 +1222,7 @@ namespace Microsoft.FSharp.Collections initMoveNext <- ignore let rec moveNext () = - if (result.Halted = 0) && idx < array.Length then + if (result.HaltedIdx = 0) && idx < array.Length then idx <- idx+1 if seqComponent.ProcessNext array.[idx-1] then true @@ -1235,7 +1230,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete result.Halted + (Helpers.upcastISeqComponent seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1249,7 +1244,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) @@ -1276,7 +1271,7 @@ namespace Microsoft.FSharp.Collections let mutable list = alist let rec moveNext current = - match result.Halted, current with + match result.HaltedIdx, current with | 0, head::tail -> if seqComponent.ProcessNext head then list <- tail @@ -1285,7 +1280,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete result.Halted + (Helpers.upcastISeqComponent seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1299,7 +1294,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) @@ -1317,7 +1312,7 @@ namespace Microsoft.FSharp.Collections let mutable current = state let rec moveNext () = - match signal.Halted, generator current with + match signal.HaltedIdx, generator current with | 0, Some (item, nextState) -> current <- nextState if seqComponent.ProcessNext item then @@ -1337,7 +1332,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) @@ -1378,7 +1373,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = -1 let rec moveNext () = - if (signal.Halted = 0) && idx < terminatingIdx then + if (signal.HaltedIdx = 0) && idx < terminatingIdx then idx <- idx + 1 if maybeSkipping then @@ -1392,11 +1387,11 @@ namespace Microsoft.FSharp.Collections true else moveNext () - elif (signal.Halted = 0) && idx = System.Int32.MaxValue then + elif (signal.HaltedIdx = 0) && idx = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else signal.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete signal.Halted + (Helpers.upcastISeqComponent seqComponent).OnComplete signal.HaltedIdx false interface IEnumerator with @@ -1410,7 +1405,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (SetResult<'U> result), result)) + Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index dd5ee5d9016..c4d49945fb6 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -14,8 +14,10 @@ namespace Microsoft.FSharp.Collections [] module Seq = module SeqComposer = + type PipeIdx = int + type ISeqComponent = - abstract OnComplete : int -> unit + abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit [] From e32a1daf41f0630bdc110c7c76e072885f86cf3f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 26 Oct 2016 19:46:49 +1100 Subject: [PATCH 194/286] Simplified use of OnComplete & OnDispose Pushed the chaining functionality into the interface and added extra methods on SeqConsumer. This means the consumer can ignore the interface and just implement their version, which means less likely to be an issue of the message not being chained correctly. It also has the advantage that in the object expressions we don't have to cast back to the base type, which was a potentital area for errors. --- src/fsharp/FSharp.Core/seq.fs | 125 +++++++++++++-------------------- src/fsharp/FSharp.Core/seq.fsi | 12 ++-- 2 files changed, 54 insertions(+), 83 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 9fd7c389580..e87a73cf523 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -473,9 +473,17 @@ namespace Microsoft.FSharp.Collections type SeqConsumer<'T,'U> () = abstract ProcessNext : input:'T -> bool + abstract OnComplete : PipeIdx -> unit + abstract OnDispose : unit -> unit + + default __.OnComplete _ = () + default __.OnDispose () = () + interface ISeqComponent with - member __.OnComplete _ = () - member __.OnDispose() = () + member this.OnComplete terminatingIdx = this.OnComplete terminatingIdx + member this.OnDispose () = + try this.OnDispose () + finally () [] type Values<'a,'b> = @@ -527,11 +535,6 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) - let seqComponentTail = - { new ISeqComponent with - member __.OnComplete _ = () - member __.OnDispose() = () } - type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = abstract Create<'V> : ISeqPipeline -> ``PipeIdx?`` -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> @@ -647,8 +650,12 @@ namespace Microsoft.FSharp.Collections abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> interface ISeqComponent with - member __.OnComplete terminatingIdx = next.OnComplete terminatingIdx - member __.OnDispose () = next.OnDispose () + member this.OnComplete terminatingIdx = + this.OnComplete terminatingIdx + next.OnComplete terminatingIdx + member this.OnDispose () = + try this.OnDispose () + finally next.OnDispose () default __.Skipping () = false @@ -737,12 +744,8 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing pipeIdx false - interface ISeqComponent with - override __.OnDispose () = - try - input2.Dispose () - finally - (Helpers.upcastISeqComponent next).OnDispose () + override __.OnDispose () = + input2.Dispose () and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'Second,'V>(next) @@ -757,12 +760,8 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing pipeIdx false - interface ISeqComponent with - override __.OnDispose () = - try - input1.Dispose () - finally - (Helpers.upcastISeqComponent next).OnDispose () + override __.OnDispose () = + input1.Dispose () and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) @@ -778,15 +777,9 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing pipeIdx false - interface ISeqComponent with - override __.OnDispose () = - try - input2.Dispose () - finally - try - input3.Dispose () - finally - (Helpers.upcastISeqComponent next).OnDispose () + override __.OnDispose () = + try input2.Dispose () + finally input3.Dispose () and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqConsumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) @@ -823,12 +816,8 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing pipeIdx false - interface ISeqComponent with - override __.OnDispose () = - try - input2.Dispose () - finally - (Helpers.upcastISeqComponent next).OnDispose () + override __.OnDispose () = + input2.Dispose () and Pairwise<'T,'V> (next:SeqConsumer<'T*'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -875,13 +864,11 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - interface ISeqComponent with - override __.OnComplete terminatingIdx = - if count < skipCount then - let x = skipCount - count - invalidOpFmt "tried to skip {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete terminatingIdx + override __.OnComplete _ = + if count < skipCount then + let x = skipCount - count + invalidOpFmt "tried to skip {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -901,13 +888,11 @@ namespace Microsoft.FSharp.Collections and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineIdx:int) = inherit Truncate<'T, 'V>(takeCount, result, next, pipelineIdx) - interface ISeqComponent with - override this.OnComplete terminatingIdx = - if terminatingIdx < pipelineIdx && this.Count < takeCount then - let x = takeCount - this.Count - invalidOpFmt "tried to take {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - (Helpers.upcastISeqComponent next).OnComplete terminatingIdx + override this.OnComplete terminatingIdx = + if terminatingIdx < pipelineIdx && this.Count < takeCount then + let x = takeCount - this.Count + invalidOpFmt "tried to take {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) @@ -931,11 +916,9 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - interface ISeqComponent with - override this.OnComplete terminatingIdx = - if first then - invalidArg "source" (SR.GetString(SR.notEnoughElements)) - (Helpers.upcastISeqComponent next).OnComplete terminatingIdx + override this.OnComplete _ = + if first then + invalidArg "source" (SR.GetString(SR.notEnoughElements)) and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) @@ -1871,9 +1854,8 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- f.Invoke (this.Value._2, value) Unchecked.defaultof - interface SeqComposer.ISeqComponent with member this.OnComplete _ = - if (this:?>SeqComposer.Folder<'T, SeqComposer.Values>).Value._1 then + if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun reduced -> reduced.Value._2 @@ -2278,9 +2260,8 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- this.Value._2 + 1 Unchecked.defaultof - interface SeqComposer.ISeqComponent with member this.OnComplete _ = - if (this:?>SeqComposer.Folder<'a, SeqComposer.Values<'a, int>>).Value._2 = 0 then + if this.Value._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun total -> LanguagePrimitives.DivideByInt< ^a> total.Value._1 total.Value._2 @@ -2293,9 +2274,9 @@ namespace Microsoft.FSharp.Collections this.Value._1 <- Checked.(+) this.Value._1 (f value) this.Value._2 <- this.Value._2 + 1 Unchecked.defaultof - interface SeqComposer.ISeqComponent with + member this.OnComplete _ = - if (this:?>SeqComposer.Folder<'T,SeqComposer.Values<'U, int>>).Value._2 = 0 then + if this.Value._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.Value._1 total.Value._2 @@ -2317,9 +2298,8 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value Unchecked.defaultof - interface SeqComposer.ISeqComponent with member this.OnComplete _ = - if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun min -> min.Value._2 @@ -2341,9 +2321,8 @@ namespace Microsoft.FSharp.Collections | _ -> () Unchecked.defaultof - interface SeqComposer.ISeqComponent with member this.OnComplete _ = - if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun min -> min.Value._3 @@ -2377,9 +2356,8 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value Unchecked.defaultof - interface SeqComposer.ISeqComponent with member this.OnComplete _ = - if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun max -> max.Value._2 @@ -2401,9 +2379,8 @@ namespace Microsoft.FSharp.Collections | _ -> () Unchecked.defaultof - interface SeqComposer.ISeqComponent with member this.OnComplete _ = - if (this:?>SeqComposer.Folder<'T,SeqComposer.Values>).Value._1 then + if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun min -> min.Value._3 @@ -2516,14 +2493,12 @@ namespace Microsoft.FSharp.Collections this.Value._3 <- true halt () Unchecked.defaultof - interface SeqComposer.ISeqComponent with + member this.OnComplete _ = - let value = (this:?>SeqComposer.Folder<'T,SeqComposer.Values>) - if value.Value._1 then + if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - elif value.Value._3 then - invalidArg "source" (SR.GetString(SR.inputSequenceTooLong)) - }) + elif this.Value._3 then + invalidArg "source" (SR.GetString(SR.inputSequenceTooLong)) }) |> fun one -> one.Value._2 member this.OnComplete _ = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index c4d49945fb6..d6db4f484b1 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -22,34 +22,30 @@ namespace Microsoft.FSharp.Collections [] type SeqConsumer<'T,'U> = - new : unit -> SeqConsumer<'T,'U> - abstract ProcessNext : input:'T -> bool interface ISeqComponent + new : unit -> SeqConsumer<'T,'U> + abstract member ProcessNext : input:'T -> bool + abstract member OnComplete : PipeIdx -> unit + abstract member OnDispose : unit -> unit [] type Values<'a,'b> = - struct new : a:'a * b:'b -> Values<'a,'b> val mutable _1: 'a val mutable _2: 'b - end [] type Values<'a,'b,'c> = - struct new : a:'a * b:'b * c:'c -> Values<'a,'b,'c> val mutable _1: 'a val mutable _2: 'b val mutable _3: 'c - end [] type Folder<'T,'U> = - class inherit SeqConsumer<'T,'T> new : init:'U -> Folder<'T,'U> val mutable Value: 'U - end [] type SeqEnumerable<'T> = From 7934948a6706c2c2e2dabf8c90702429e20f0589 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 26 Oct 2016 20:24:17 +1100 Subject: [PATCH 195/286] Starting to finalise namespacing and comments Still playing around, happy for some input here... --- src/fsharp/FSharp.Core/seq.fs | 395 +++++++++++++++++---------------- src/fsharp/FSharp.Core/seq.fsi | 99 +++++---- 2 files changed, 260 insertions(+), 234 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index e87a73cf523..3dfb9f9f3de 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -453,74 +453,79 @@ namespace Microsoft.FSharp.Collections [] [] module Seq = - module SeqComposer = + module Composer = open IEnumerator - type PipeIdx = int - type ``PipeIdx?`` = Nullable - let emptyPipeIdx = Nullable () - let inline getPipeIdx (maybePipeIdx:``PipeIdx?``) = if maybePipeIdx.HasValue then maybePipeIdx.Value else 1 - let inline makePipeIdx (pipeIdx:PipeIdx) = Nullable pipeIdx + module Internal = + type PipeIdx = int + type ``PipeIdx?`` = Nullable + let emptyPipeIdx = Nullable () + let inline getPipeIdx (maybePipeIdx:``PipeIdx?``) = if maybePipeIdx.HasValue then maybePipeIdx.Value else 1 + let inline makePipeIdx (pipeIdx:PipeIdx) = Nullable pipeIdx - type ISeqComponent = - abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit + type ICompletionChaining = + abstract OnComplete : PipeIdx -> unit + abstract OnDispose : unit -> unit - type ISeqPipeline = - abstract StopFurtherProcessing : PipeIdx -> unit + type IPipeline = + abstract StopFurtherProcessing : PipeIdx -> unit - [] - type SeqConsumer<'T,'U> () = - abstract ProcessNext : input:'T -> bool + [] + type Consumer<'T,'U> () = + abstract ProcessNext : input:'T -> bool + + abstract OnComplete : PipeIdx -> unit + abstract OnDispose : unit -> unit - abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit + default __.OnComplete _ = () + default __.OnDispose () = () - default __.OnComplete _ = () - default __.OnDispose () = () + interface ICompletionChaining with + member this.OnComplete terminatingIdx = + this.OnComplete terminatingIdx - interface ISeqComponent with - member this.OnComplete terminatingIdx = this.OnComplete terminatingIdx - member this.OnDispose () = - try this.OnDispose () - finally () + member this.OnDispose () = + try this.OnDispose () + finally () - [] - type Values<'a,'b> = - val mutable _1 : 'a - val mutable _2 : 'b + [] + type Values<'a,'b> = + val mutable _1 : 'a + val mutable _2 : 'b - new (a:'a, b: 'b) = { - _1 = a - _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 + [] + 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 - } + new (a:'a, b:'b, c:'c) = { + _1 = a + _2 = b + _3 = c + } + + [] + type Folder<'T, 'U> = + inherit Consumer<'T,'T> - [] - type Folder<'T, 'U> = - inherit SeqConsumer<'T,'T> + val mutable Value : 'U - val mutable Value : 'U + new (init) = { + inherit Consumer<'T,'T>() + Value = init + } - new (init) = { - inherit SeqConsumer<'T,'T>() - Value = init - } + [] + type SeqEnumerable<'T>() = + abstract member ForEach<'a when 'a :> Consumer<'T,'T>> : f:((unit->unit)->'a) -> 'a - [] - type SeqEnumerable<'T>() = - abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:((unit->unit)->'a) -> 'a + open Internal module Helpers = // used for performance reasons; these are not recursive calls, so should be safe @@ -533,10 +538,10 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline upcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #) + let inline upcastISeqComponent (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = - abstract Create<'V> : ISeqPipeline -> ``PipeIdx?`` -> SeqConsumer<'U,'V> -> SeqConsumer<'T,'V> + abstract Create<'V> : IPipeline -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) @@ -545,7 +550,7 @@ namespace Microsoft.FSharp.Collections and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>, secondPipeIdx:PipeIdx) = inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) - override this.Create<'W> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'V,'W>) : SeqConsumer<'T,'W> = + override this.Create<'W> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = first.Create result pipeIdx (second.Create result (makePipeIdx secondPipeIdx) next) static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = @@ -553,23 +558,23 @@ namespace Microsoft.FSharp.Collections and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Choose (filter, next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) and DistinctFactory<'T when 'T: equality> () = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Distinct (next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast DistinctBy (keyFunction, next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Except (itemsToExclude, next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = match next with | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter | _ -> upcast Filter (filter, next) @@ -577,79 +582,79 @@ namespace Microsoft.FSharp.Collections and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () static let singleton = IdentityFactory<'T>() - override __.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = next + override __.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next static member IdentityFactory = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = match next with | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map | _ -> upcast Map<_,_,_> (map, next) and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map2First (map, input2, result, next, getPipeIdx pipeIdx) + override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, result, next, getPipeIdx pipeIdx) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = inherit SeqComponentFactory<'Second,'U> () - override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'Second,'V> = upcast Map2Second (map, input1, result, next, getPipeIdx pipeIdx) + override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, result, next, getPipeIdx pipeIdx) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, getPipeIdx pipeIdx) + override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, getPipeIdx pipeIdx) and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'T,'V> = upcast Mapi (mapi, next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'U,'V>) : SeqConsumer<'First,'V> = upcast Mapi2 (map, input2, result, next, getPipeIdx pipeIdx) + override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, result, next, getPipeIdx pipeIdx) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T*'T,'V>) : SeqConsumer<'T,'V> = upcast Pairwise (next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = inherit SeqComponentFactory<'T,'State> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'State,'V>) : SeqConsumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Skip (count, next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast SkipWhile (predicate, next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast TakeWhile (predicate, result, next, getPipeIdx pipeIdx) + override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, result, next, getPipeIdx pipeIdx) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Take (count, result, next, getPipeIdx pipeIdx) + override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, result, next, getPipeIdx pipeIdx) and TailFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:ISeqPipeline) (_pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Tail<'T,'V> (next) + override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:ISeqPipeline) (pipeIdx:``PipeIdx?``) (next:SeqConsumer<'T,'V>) : SeqConsumer<'T,'V> = upcast Truncate (count, result, next, getPipeIdx pipeIdx) + override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, result, next, getPipeIdx pipeIdx) - and [] SeqComponent<'T,'U> (next:ISeqComponent) = - inherit SeqConsumer<'T,'U>() + and [] SeqComponent<'T,'U> (next:ICompletionChaining) = + inherit Consumer<'T,'U>() - // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip + // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip // and it can only do it at the start of a sequence abstract Skipping : unit -> bool abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> - interface ISeqComponent with + interface ICompletionChaining with member this.OnComplete terminatingIdx = this.OnComplete terminatingIdx next.OnComplete terminatingIdx @@ -662,7 +667,7 @@ namespace Microsoft.FSharp.Collections default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) - and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqConsumer<'U,'V>) = + and Choose<'T,'U,'V> (choose:'T->option<'U>, next:Consumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -670,7 +675,7 @@ namespace Microsoft.FSharp.Collections | Some value -> Helpers.avoidTailCall (next.ProcessNext value) | None -> false - and Distinct<'T,'V when 'T: equality> (next:SeqConsumer<'T,'V>) = + and Distinct<'T,'V when 'T: equality> (next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) @@ -681,7 +686,7 @@ namespace Microsoft.FSharp.Collections else false - and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqConsumer<'T,'V>) = + and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) @@ -692,7 +697,7 @@ namespace Microsoft.FSharp.Collections else false - and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqConsumer<'T,'V>) = + and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) @@ -703,7 +708,7 @@ namespace Microsoft.FSharp.Collections else false - and Filter<'T,'V> (filter:'T->bool, next:SeqConsumer<'T,'V>) = + and Filter<'T,'V> (filter:'T->bool, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) @@ -714,7 +719,7 @@ namespace Microsoft.FSharp.Collections else false - and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqConsumer<'U,'V>) = + and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:Consumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -723,7 +728,7 @@ namespace Microsoft.FSharp.Collections else false - and Map<'T,'U,'V> (map:'T->'U, next:SeqConsumer<'U,'V>) = + and Map<'T,'U,'V> (map:'T->'U, next:Consumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) @@ -731,7 +736,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -747,7 +752,7 @@ namespace Microsoft.FSharp.Collections override __.OnDispose () = input2.Dispose () - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'Second,'V>(next) let input1 = enumerable1.GetEnumerator () @@ -763,7 +768,7 @@ namespace Microsoft.FSharp.Collections override __.OnDispose () = input1.Dispose () - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -781,7 +786,7 @@ namespace Microsoft.FSharp.Collections try input2.Dispose () finally input3.Dispose () - and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqConsumer<'U,'V>) = + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:Consumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -791,7 +796,7 @@ namespace Microsoft.FSharp.Collections else false - and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqConsumer<'U,'V>) = + and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:Consumer<'U,'V>) = inherit SeqComponent<'T,'V>(next) let mutable idx = 0 @@ -801,7 +806,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:ISeqPipeline, next:SeqConsumer<'U,'V>, pipeIdx:int) = + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let mutable idx = 0 @@ -819,7 +824,7 @@ namespace Microsoft.FSharp.Collections override __.OnDispose () = input2.Dispose () - and Pairwise<'T,'V> (next:SeqConsumer<'T*'T,'V>) = + and Pairwise<'T,'V> (next:Consumer<'T*'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable isFirst = true @@ -835,7 +840,7 @@ namespace Microsoft.FSharp.Collections lastValue <- input Helpers.avoidTailCall (next.ProcessNext currentPair) - and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:SeqConsumer<'State,'V>) = + and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:Consumer<'State,'V>) = inherit SeqComponent<'T,'V>(next) let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder @@ -845,7 +850,7 @@ namespace Microsoft.FSharp.Collections foldResult <- f.Invoke(foldResult, input) Helpers.avoidTailCall (next.ProcessNext foldResult) - and Skip<'T,'V> (skipCount:int, next:SeqConsumer<'T,'V>) = + and Skip<'T,'V> (skipCount:int, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -870,7 +875,7 @@ namespace Microsoft.FSharp.Collections invalidOpFmt "tried to skip {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqConsumer<'T,'V>) = + and SkipWhile<'T,'V> (predicate:'T->bool, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable skip = true @@ -885,7 +890,7 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - and Take<'T,'V> (takeCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipelineIdx:int) = + and Take<'T,'V> (takeCount:int, result:IPipeline, next:Consumer<'T,'V>, pipelineIdx:int) = inherit Truncate<'T, 'V>(takeCount, result, next, pipelineIdx) override this.OnComplete terminatingIdx = @@ -894,7 +899,7 @@ namespace Microsoft.FSharp.Collections invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - and TakeWhile<'T,'V> (predicate:'T->bool, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipeIdx:int) = + and TakeWhile<'T,'V> (predicate:'T->bool, result:IPipeline, next:Consumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = @@ -904,7 +909,7 @@ namespace Microsoft.FSharp.Collections result.StopFurtherProcessing pipeIdx false - and Tail<'T, 'V> (next:SeqConsumer<'T,'V>) = + and Tail<'T, 'V> (next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable first = true @@ -920,7 +925,7 @@ namespace Microsoft.FSharp.Collections if first then invalidArg "source" (SR.GetString(SR.notEnoughElements)) - and Truncate<'T,'V> (truncateCount:int, result:ISeqPipeline, next:SeqConsumer<'T,'V>, pipeIdx:int) = + and Truncate<'T,'V> (truncateCount:int, result:IPipeline, next:Consumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -949,12 +954,12 @@ namespace Microsoft.FSharp.Collections member val SeqState = SeqProcessNextStates.NotStarted with get, set member __.HaltedIdx = haltedIdx - interface ISeqPipeline with + interface IPipeline with member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx // SetResult<> is used at the end of the chain of SeqComponents to assign the final value type SetResult<'T> (result:Result<'T>) = - inherit SeqConsumer<'T,'T>() + inherit Consumer<'T,'T>() override __.ProcessNext (input:'T) : bool = result.Current <- input @@ -962,22 +967,22 @@ namespace Microsoft.FSharp.Collections type Pipeline() = let mutable haltedIdx = 0 - interface ISeqPipeline with member x.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx + interface IPipeline with member x.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx member __.HaltedIdx = haltedIdx module ForEach = - let enumerable (enumerable:IEnumerable<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let enumerable (enumerable:IEnumerable<'T>) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = use enumerator = enumerable.GetEnumerator () while (pipeline.HaltedIdx = 0) && (enumerator.MoveNext ()) do consumer.ProcessNext enumerator.Current |> ignore - let array (array:array<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let array (array:array<'T>) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = let mutable idx = 0 while (pipeline.HaltedIdx = 0) && (idx < array.Length) do consumer.ProcessNext array.[idx] |> ignore idx <- idx + 1 - let list (alist:list<'T>) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let list (alist:list<'T>) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = let rec iterate lst = match pipeline.HaltedIdx, lst with | 0, hd :: tl -> @@ -986,7 +991,7 @@ namespace Microsoft.FSharp.Collections | _ -> () iterate alist - let unfold (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let unfold (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = let rec iterate current = match pipeline.HaltedIdx, generator current with | 0, Some (item, next) -> @@ -996,12 +1001,12 @@ namespace Microsoft.FSharp.Collections iterate state - let makeIsSkipping (consumer:SeqConsumer<'T,'U>) = + let makeIsSkipping (consumer:Consumer<'T,'U>) = match consumer with | :? SeqComponent<'T,'U> as c -> c.Skipping | _ -> fun () -> false - let init f (terminatingIdx:int) (pipeline:Pipeline) (consumer:SeqConsumer<'T,'U>) = + let init f (terminatingIdx:int) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = let mutable idx = -1 let isSkipping = makeIsSkipping consumer let mutable maybeSkipping = true @@ -1014,9 +1019,9 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 - let execute (f:(unit->unit)->#SeqConsumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = + let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = let pipeline = Pipeline() - let result = f (fun () -> (pipeline:>ISeqPipeline).StopFurtherProcessing (current.PipeIdx+1)) + let result = f (fun () -> (pipeline:>IPipeline).StopFurtherProcessing (current.PipeIdx+1)) let consumer = current.Create pipeline emptyPipeIdx result try executeOn pipeline consumer @@ -1042,7 +1047,7 @@ namespace Microsoft.FSharp.Collections static member Element = element [] - type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) = + type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ICompletionChaining) = interface IDisposable with member __.Dispose() : unit = seqComponent.OnDispose () @@ -1079,7 +1084,7 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" - and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqConsumer<'T,'U>, result:Result<'U>) = + and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, seqComponent) let rec moveNext () = @@ -1116,7 +1121,7 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.enumerable enumerable) and ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = @@ -1170,7 +1175,7 @@ namespace Microsoft.FSharp.Collections override this.Append source = Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) - override this.ForEach (f:(unit->unit)->#SeqConsumer<'T,'T>) = + override this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) and ConcatEnumerable<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = @@ -1183,14 +1188,14 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(this, next)) - override this.ForEach (f:(unit->unit)->#SeqConsumer<'T,'T>) = + override this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) let create enumerable current = Helpers.upcastEnumerable (Enumerable(enumerable, current)) module Array = - type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:SeqConsumer<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable idx = 0 @@ -1232,7 +1237,7 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = @@ -1248,7 +1253,7 @@ namespace Microsoft.FSharp.Collections create array IdentityFactory.IdentityFactory module List = - type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqConsumer<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U>(alist:list<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable list = alist @@ -1282,14 +1287,14 @@ namespace Microsoft.FSharp.Collections override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.list alist) let create alist current = Helpers.upcastEnumerable (Enumerable(alist, current)) module Unfold = - type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:SeqConsumer<'T,'U>, signal:Result<'U>) = + type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, signal:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) let mutable current = state @@ -1320,7 +1325,7 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#SeqConsumer<'U,'U>) = + override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.unfold generator state) module Init = @@ -1343,7 +1348,7 @@ namespace Microsoft.FSharp.Collections else System.Int32.MaxValue - type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqConsumer<'T,'U>, signal:Result<'U>) = + type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:Consumer<'T,'U>, signal:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) let isSkipping = @@ -1393,7 +1398,7 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) - override this.ForEach (createResult:(unit->unit)->#SeqConsumer<'U,'U>) = + override this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = let terminatingIdx = getTerminatingIdx count ForEach.execute createResult current (ForEach.init f terminatingIdx) @@ -1460,7 +1465,7 @@ namespace Microsoft.FSharp.Collections override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) - override this.ForEach (f:(unit->unit)->#SeqConsumer<'T,'T>) = + override this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable (Helpers.upcastEnumerable this)) #if FX_NO_ICLONEABLE @@ -1471,13 +1476,13 @@ namespace Microsoft.FSharp.Collections let inline indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) [] - let toComposer (source:seq<'T>): SeqComposer.SeqEnumerable<'T> = + let toComposer (source:seq<'T>): Composer.Internal.SeqEnumerable<'T> = checkNonNull "source" source match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> upcast s - | :? array<'T> as a -> upcast SeqComposer.Array.Enumerable((fun () -> a), SeqComposer.IdentityFactory.IdentityFactory) - | :? list<'T> as a -> upcast SeqComposer.List.Enumerable(a, SeqComposer.IdentityFactory.IdentityFactory) - | _ -> upcast SeqComposer.Enumerable.Enumerable<'T,'T>(source, SeqComposer.IdentityFactory.IdentityFactory) + | :? Composer.Enumerable.EnumerableBase<'T> as s -> upcast s + | :? array<'T> as a -> upcast Composer.Array.Enumerable((fun () -> a), Composer.IdentityFactory.IdentityFactory) + | :? list<'T> as a -> upcast Composer.List.Enumerable(a, Composer.IdentityFactory.IdentityFactory) + | _ -> upcast Composer.Enumerable.Enumerable<'T,'T>(source, Composer.IdentityFactory.IdentityFactory) let inline foreach f (source:seq<_>) = source @@ -1500,26 +1505,26 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : seq<'T> = - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Unfold.Enumerable<'T,'T,'State>(generator, state, SeqComposer.IdentityFactory.IdentityFactory)) + Composer.Helpers.upcastEnumerable (new Composer.Unfold.Enumerable<'T,'T,'State>(generator, state, Composer.IdentityFactory.IdentityFactory)) [] let empty<'T> = (EmptyEnumerable :> seq<'T>) [] let initInfinite<'T> (f:int->'T) : IEnumerable<'T> = - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable (), f)) + Composer.Helpers.upcastEnumerable (new Composer.Init.EnumerableDecider<'T>(Nullable (), f)) [] let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> = if count < 0 then invalidArgInputMustBeNonNegative "count" count elif count = 0 then empty else - SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable count, f)) + Composer.Helpers.upcastEnumerable (new Composer.Init.EnumerableDecider<'T>(Nullable count, f)) [] let iter f (source : seq<'T>) = source |> foreach (fun _ -> - { new SeqComposer.SeqConsumer<'T,'T> () with + { new Composer.Internal.Consumer<'T,'T> () with override this.ProcessNext value = f value Unchecked.defaultof }) @@ -1550,7 +1555,7 @@ namespace Microsoft.FSharp.Collections if i < 0 then None else source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, SeqComposer.Values>> (SeqComposer.Values<_, _> (0, None)) with + { new Composer.Internal.Folder<'T, Composer.Internal.Values>> (Composer.Internal.Values<_, _> (0, None)) with override this.ProcessNext value = if this.Value._1 = i then this.Value._2 <- Some value @@ -1568,7 +1573,7 @@ namespace Microsoft.FSharp.Collections let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) source |> foreach (fun _ -> - { new SeqComposer.Folder<'T, int> (0) with + { new Composer.Internal.Folder<'T, int> (0) with override this.ProcessNext value = f.Invoke(this.Value, value) this.Value <- this.Value + 1 @@ -1579,7 +1584,7 @@ namespace Microsoft.FSharp.Collections let exists f (source : seq<'T>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, bool> (false) with + { new Composer.Internal.Folder<'T, bool> (false) with override this.ProcessNext value = if f value then this.Value <- true @@ -1592,7 +1597,7 @@ namespace Microsoft.FSharp.Collections let inline contains element (source : seq<'T>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, bool> (false) with + { new Composer.Internal.Folder<'T, bool> (false) with override this.ProcessNext value = if element = value then this.Value <- true @@ -1605,7 +1610,7 @@ namespace Microsoft.FSharp.Collections let forall f (source : seq<'T>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, bool> (true) with + { new Composer.Internal.Folder<'T, bool> (true) with override this.ProcessNext value = if not (f value) then this.Value <- false @@ -1661,57 +1666,51 @@ namespace Microsoft.FSharp.Collections let private seqFactory createSeqComponent (source:seq<'T>) = checkNonNull "source" source match source with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose createSeqComponent - | :? array<'T> as a -> SeqComposer.Array.create a createSeqComponent - | :? list<'T> as a -> SeqComposer.List.create a createSeqComponent - | _ -> SeqComposer.Enumerable.create source createSeqComponent + | :? Composer.Enumerable.EnumerableBase<'T> as s -> s.Compose createSeqComponent + | :? array<'T> as a -> Composer.Array.create a createSeqComponent + | :? list<'T> as a -> Composer.List.create a createSeqComponent + | _ -> Composer.Enumerable.create source createSeqComponent [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = - Composer.Seq.filter f (toComposer source) - |> Upcast.enumerable + source |> seqFactory (Composer.FilterFactory f) [] let where f source = filter f source [] let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> = - Composer.Seq.map f (toComposer source) - |> Upcast.enumerable + source |> seqFactory (Composer.MapFactory f) [] - let mapi f source = - let f' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f - Composer.Seq.mapi_adapt f' (toComposer source) - |> Upcast.enumerable + let mapi f source = + source |> seqFactory (Composer.MapiFactory f) [] let mapi2 f source1 source2 = checkNonNull "source2" source2 - source1 |> seqFactory (SeqComposer.Mapi2Factory (f, source2)) + source1 |> seqFactory (Composer.Mapi2Factory (f, source2)) [] let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = checkNonNull "source1" source1 match source1 with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2)) - | _ -> source2 |> seqFactory (SeqComposer.Map2SecondFactory (f, source1)) + | :? Composer.Enumerable.EnumerableBase<'T> as s -> s.Compose (Composer.Map2FirstFactory (f, source2)) + | _ -> source2 |> seqFactory (Composer.Map2SecondFactory (f, source1)) [] let map3 f source1 source2 source3 = checkNonNull "source2" source2 checkNonNull "source3" source3 - source1 |> seqFactory (SeqComposer.Map3Factory (f, source2, source3)) + source1 |> seqFactory (Composer.Map3Factory (f, source2, source3)) [] - let choose f source = - Composer.Seq.choose f (toComposer source) - |> Upcast.enumerable + let choose f source = + source |> seqFactory (Composer.ChooseFactory f) [] let indexed source = - Composer.Seq.indexed (toComposer source) - |> Upcast.enumerable + source |> seqFactory (Composer.MapiFactory (fun i x -> i,x) ) [] let zip source1 source2 = @@ -1730,7 +1729,7 @@ namespace Microsoft.FSharp.Collections let tryPick f (source : seq<'T>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, Option<'U>> (None) with + { new Composer.Internal.Folder<'T, Option<'U>> (None) with override this.ProcessNext value = match f value with | (Some _) as some -> @@ -1750,7 +1749,7 @@ namespace Microsoft.FSharp.Collections let tryFind f (source : seq<'T>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, Option<'T>> (None) with + { new Composer.Internal.Folder<'T, Option<'T>> (None) with override this.ProcessNext value = if f value then this.Value <- Some value @@ -1769,7 +1768,7 @@ namespace Microsoft.FSharp.Collections if count < 0 then invalidArgInputMustBeNonNegative "count" count (* Note: don't create or dispose any IEnumerable if n = 0 *) if count = 0 then empty else - source |> seqFactory (Composer.Seq.TakeFactory count) + source |> seqFactory (Composer.TakeFactory count) [] let isEmpty (source : seq<'T>) = @@ -1785,7 +1784,7 @@ namespace Microsoft.FSharp.Collections [] let concat (sources:seq<#seq<'T>>) : seq<'T> = checkNonNull "sources" sources - upcast SeqComposer.Enumerable.ConcatEnumerable sources + upcast Composer.Enumerable.ConcatEnumerable sources [] let length (source : seq<'T>) = @@ -1807,7 +1806,7 @@ namespace Microsoft.FSharp.Collections source |> foreach (fun _ -> - { new SeqComposer.Folder<'T,'State> (x) with + { new Composer.Internal.Folder<'T,'State> (x) with override this.ProcessNext value = this.Value <- f.Invoke (this.Value, value) Unchecked.defaultof }) @@ -1845,7 +1844,7 @@ namespace Microsoft.FSharp.Collections source |> foreach (fun _ -> - { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with + { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -1869,8 +1868,8 @@ namespace Microsoft.FSharp.Collections checkNonNull "source1" source1 checkNonNull "source2" source2 match source1 with - | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Append source2 - | _ -> SeqComposer.Helpers.upcastEnumerable (new SeqComposer.Enumerable.AppendEnumerable<_>([source2; source1])) + | :? Composer.Enumerable.EnumerableBase<'T> as s -> s.Append source2 + | _ -> Composer.Helpers.upcastEnumerable (new Composer.Enumerable.AppendEnumerable<_>([source2; source1])) [] @@ -1914,7 +1913,7 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source : 'T array) = checkNonNull "source" source - SeqComposer.Array.createId source + Composer.Array.createId source [] let toArray (source : seq<'T>) = @@ -1968,17 +1967,17 @@ namespace Microsoft.FSharp.Collections [] let truncate n (source: seq<'T>) = if n <= 0 then empty else - source |> seqFactory (Composer.Seq.TruncateFactory n) + source |> seqFactory (Composer.TruncateFactory n) [] let pairwise<'T> (source:seq<'T>) : seq<'T*'T> = - source |> seqFactory (Composer.Seq.PairwiseFactory ()) + source |> seqFactory (Composer.PairwiseFactory ()) [] let scan<'T,'State> f (z:'State) (source : seq<'T>): seq<'State> = let first = [|z|] :> IEnumerable<'State> - let rest = source |> seqFactory (SeqComposer.ScanFactory (f, z)) - upcast SeqComposer.Enumerable.ConcatEnumerable [|first; rest;|] + let rest = source |> seqFactory (Composer.ScanFactory (f, z)) + upcast Composer.Enumerable.ConcatEnumerable [|first; rest;|] [] let tryFindBack f (source : seq<'T>) = @@ -2002,7 +2001,7 @@ namespace Microsoft.FSharp.Collections let tryFindIndex p (source:seq<_>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, SeqComposer.Values, int>> (SeqComposer.Values<_,_>(None, 0)) with + { new Composer.Internal.Folder<'T, Composer.Internal.Values, int>> (Composer.Internal.Values<_,_>(None, 0)) with override this.ProcessNext value = if p value then this.Value._1 <- Some(this.Value._2) @@ -2152,11 +2151,11 @@ namespace Microsoft.FSharp.Collections [] let distinct source = - source |> seqFactory (Composer.Seq.DistinctFactory ()) + source |> seqFactory (Composer.DistinctFactory ()) [] let distinctBy keyf source = - source |> seqFactory (Composer.Seq.DistinctByFactory keyf) + source |> seqFactory (Composer.DistinctByFactory keyf) [] let sortBy keyf source = @@ -2165,7 +2164,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceBy keyf array array - SeqComposer.Array.createDelayedId delayedSort + Composer.Array.createDelayedId delayedSort [] let sort source = @@ -2174,7 +2173,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlace array array - SeqComposer.Array.createDelayedId delayedSort + Composer.Array.createDelayedId delayedSort [] let sortWith f source = @@ -2183,7 +2182,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceWith f array array - SeqComposer.Array.createDelayedId delayedSort + Composer.Array.createDelayedId delayedSort [] let inline sortByDescending keyf source = @@ -2234,7 +2233,7 @@ namespace Microsoft.FSharp.Collections let inline sum (source:seq<'a>) : 'a = source |> foreach (fun _ -> - { new SeqComposer.Folder<'a,'a> (LanguagePrimitives.GenericZero) with + { new Composer.Internal.Folder<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value value Unchecked.defaultof }) @@ -2244,7 +2243,7 @@ namespace Microsoft.FSharp.Collections let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = source |> foreach (fun _ -> - { new SeqComposer.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + { new Composer.Internal.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value (f value) Unchecked.defaultof }) @@ -2254,7 +2253,7 @@ namespace Microsoft.FSharp.Collections let inline average (source: seq< ^a>) : ^a = source |> foreach (fun _ -> - { new SeqComposer.Folder<'a, SeqComposer.Values<'a, int>> (SeqComposer.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + { new Composer.Internal.Folder<'a, Composer.Internal.Values<'a, int>> (Composer.Internal.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 value this.Value._2 <- this.Value._2 + 1 @@ -2269,7 +2268,7 @@ namespace Microsoft.FSharp.Collections let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = source |> foreach (fun _ -> - { new SeqComposer.Folder<'T,SeqComposer.Values<'U, int>> (SeqComposer.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + { new Composer.Internal.Folder<'T,Composer.Internal.Values<'U, int>> (Composer.Internal.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 (f value) this.Value._2 <- this.Value._2 + 1 @@ -2289,7 +2288,7 @@ namespace Microsoft.FSharp.Collections let inline min (source: seq<_>) = source |> foreach (fun _ -> - { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with + { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2308,7 +2307,7 @@ namespace Microsoft.FSharp.Collections let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = source |> foreach (fun _ -> - { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with override this.ProcessNext value = match this.Value._1, f value with | true, valueU -> @@ -2347,7 +2346,7 @@ namespace Microsoft.FSharp.Collections let inline max (source: seq<_>) = source |> foreach (fun _ -> - { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_>(true, Unchecked.defaultof<'T>)) with + { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2366,7 +2365,7 @@ namespace Microsoft.FSharp.Collections let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = source |> foreach (fun _ -> - { new SeqComposer.Folder<'T,SeqComposer.Values> (SeqComposer.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with override this.ProcessNext value = match this.Value._1, f value with | true, valueU -> @@ -2404,11 +2403,15 @@ namespace Microsoft.FSharp.Collections *) [] let takeWhile p (source: seq<_>) = - source |> seqFactory (Composer.Seq.TakeWhileFactory p) + source |> seqFactory (Composer.TakeWhileFactory p) + + [] + let skip count (source: seq<_>) = + source |> seqFactory (Composer.SkipFactory count) [] let skipWhile p (source: seq<_>) = - source |> seqFactory (Composer.Seq.SkipWhileFactory p) + source |> seqFactory (Composer.SkipWhileFactory p) [] let forall2 p (source1: seq<_>) (source2: seq<_>) = @@ -2428,7 +2431,7 @@ namespace Microsoft.FSharp.Collections let tryHead (source : seq<_>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, Option<'T>> (None) with + { new Composer.Internal.Folder<'T, Option<'T>> (None) with override this.ProcessNext value = this.Value <- Some value halt () @@ -2456,13 +2459,13 @@ namespace Microsoft.FSharp.Collections [] let tail (source: seq<'T>) = - source |> seqFactory (SeqComposer.TailFactory ()) + source |> seqFactory (Composer.TailFactory ()) [] let tryLast (source : seq<_>) = source |> foreach (fun _ -> - { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values(true, Unchecked.defaultof<'T>)) with + { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2484,7 +2487,7 @@ namespace Microsoft.FSharp.Collections let exactlyOne (source : seq<_>) = source |> foreach (fun halt -> - { new SeqComposer.Folder<'T, SeqComposer.Values> (SeqComposer.Values(true, Unchecked.defaultof<'T>, false)) with + { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values(true, Unchecked.defaultof<'T>, false)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2515,7 +2518,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.Reverse array array - SeqComposer.Array.createDelayedId delayedReverse + Composer.Array.createDelayedId delayedReverse [] let permute f (source:seq<_>) = @@ -2524,7 +2527,7 @@ namespace Microsoft.FSharp.Collections source |> toArray |> Array.permute f - SeqComposer.Array.createDelayedId delayedPermute + Composer.Array.createDelayedId delayedPermute [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = @@ -2542,7 +2545,7 @@ namespace Microsoft.FSharp.Collections [] let except (itemsToExclude: seq<'T>) (source: seq<'T>) = checkNonNull "itemsToExclude" itemsToExclude - source |> seqFactory (Composer.Seq.ExceptFactory itemsToExclude) + source |> seqFactory (Composer.ExceptFactory itemsToExclude) [] let chunkBySize chunkSize (source : seq<_>) = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index d6db4f484b1..b554294d6d8 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -13,43 +13,66 @@ namespace Microsoft.FSharp.Collections [] [] module Seq = - module SeqComposer = - type PipeIdx = int - - type ISeqComponent = - abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit - - [] - type SeqConsumer<'T,'U> = - interface ISeqComponent - new : unit -> SeqConsumer<'T,'U> - abstract member ProcessNext : input:'T -> bool - abstract member OnComplete : PipeIdx -> unit - abstract member OnDispose : unit -> unit - - [] - type Values<'a,'b> = - new : a:'a * b:'b -> Values<'a,'b> - val mutable _1: 'a - val mutable _2: 'b - - [] - 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 - - [] - type Folder<'T,'U> = - inherit SeqConsumer<'T,'T> - new : init:'U -> Folder<'T,'U> - val mutable Value: 'U - - [] - type SeqEnumerable<'T> = - abstract member ForEach<'a when 'a :> SeqConsumer<'T,'T>> : f:((unit->unit)->'a) -> 'a + module Composer = + module Internal = + /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the + /// source of the chain. + type PipeIdx = int + + /// ICompletionChaining is used to correctly handle cleaning up of the pipeline. A + /// base implementation is provided in Consumer, and should not be overwritten. Consumer + /// provides it's own OnComplete and OnDispose function which should be used to handle + /// a particular consumers cleanup. + type ICompletionChaining = + /// OnComplete is used to determine if the object has been processed correctly, + /// and possibly throw exceptions to denote incorrect application (i.e. such as a Take + /// operation which didn't have a source at least as large as was required). It is + /// not called in the case of an exception being thrown whilst the stream is still + /// being processed. + abstract OnComplete : PipeIdx -> unit + /// OnDispose is used to cleanup the stream. It is always called at the last operation + /// after the enumeration has completed. + abstract OnDispose : unit -> unit + + /// Consumer is the base class of all elements within the pipeline + [] + type Consumer<'T,'U> = + interface ICompletionChaining + new : unit -> Consumer<'T,'U> + abstract member ProcessNext : input:'T -> bool + abstract member OnComplete : PipeIdx -> unit + abstract member OnDispose : unit -> unit + + /// 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 + + /// 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 ForEach function. + [] + type Folder<'T,'U> = + inherit Consumer<'T,'T> + new : init:'U -> Folder<'T,'U> + val mutable Value: 'U + + /// SeqEnumerable functions provide the enhance seq experience + [] + type SeqEnumerable<'T> = + abstract member ForEach<'a when 'a :> Consumer<'T,'T>> : f:((unit->unit)->'a) -> 'a /// Returns a new sequence that contains the cartesian product of the two input sequences. /// The first sequence. @@ -1242,7 +1265,7 @@ namespace Microsoft.FSharp.Collections /// /// Thrown when the input sequence is null. [] - val toComposer : source:seq<'T> -> SeqComposer.SeqEnumerable<'T> + val toComposer : source:seq<'T> -> Composer.Internal.SeqEnumerable<'T> /// Builds a list from the given collection. /// From d6f85cb4032be5ae3b14eefc6ddbd5fd72ad9212 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 26 Oct 2016 22:09:06 -0400 Subject: [PATCH 196/286] seq.comparewith --- src/fsharp/FSharp.Core/seq.fs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 3dfb9f9f3de..86b76fa7e0c 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1881,24 +1881,34 @@ namespace Microsoft.FSharp.Collections use e2 = source2.GetEnumerator() let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) + let mutable e2ok = Unchecked.defaultof source1 |> foreach (fun halt -> - { new Composer.Core.Folder<'T,int> (0) with + { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values<_,_>(false, 0)) with override this.ProcessNext value = - if not (e2.MoveNext()) then - this.Value <- 1 + e2ok <- e2.MoveNext() + if not e2ok then + this.Value._1 <- true + this.Value._2 <- 1 halt () else - let c = f.Invoke (value, e2.Current) + let c = f.Invoke(value, e2.Current) if c <> 0 then - this.Value <- c + this.Value._1 <- true + this.Value._2 <- c halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + Unchecked.defaultof member this.OnComplete _ = - if this.Value = 0 && e2.MoveNext() then - this.Value <- -1 }) - |> fun compare -> compare.Value + if not this.Value._1 then + e2ok <- e2.MoveNext() + if e2ok then + this.Value._2 <- -1 + else + this.Value._2 <- 0 + + }) + |> fun compare -> compare.Value._2 [] let ofList (source : 'T list) = From b707e6cbc9851d653af6fe655478c92ca6eb8769 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 27 Oct 2016 17:49:21 +1100 Subject: [PATCH 197/286] More compact Seq.compareWith Bit faster on 64 bit, as don't need to access the ref of e2ok --- src/fsharp/FSharp.Core/seq.fs | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 86b76fa7e0c..84441604922 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1881,34 +1881,24 @@ namespace Microsoft.FSharp.Collections use e2 = source2.GetEnumerator() let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - let mutable e2ok = Unchecked.defaultof source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values<_,_>(false, 0)) with + { new Composer.Internal.Folder<'T,bool> (0) with override this.ProcessNext value = - e2ok <- e2.MoveNext() - if not e2ok then - this.Value._1 <- true - this.Value._2 <- 1 + if not (e2.MoveNext()) then + this.Value <- 1 halt () else - let c = f.Invoke(value, e2.Current) + let c = f.Invoke (value, e2.Current) if c <> 0 then - this.Value._1 <- true - this.Value._2 <- c + this.Value <- c halt () Unchecked.defaultof member this.OnComplete _ = - if not this.Value._1 then - e2ok <- e2.MoveNext() - if e2ok then - this.Value._2 <- -1 - else - this.Value._2 <- 0 - - }) - |> fun compare -> compare.Value._2 + if this.Value = 0 && e2.MoveNext() then + this.Value <- -1 }) + |> fun compare -> compare.Value [] let ofList (source : 'T list) = From fa11ea9b17bc49f258cae852cea305ea71997346 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 27 Oct 2016 18:59:23 +1100 Subject: [PATCH 198/286] oops, type-o ! --- src/fsharp/FSharp.Core/seq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 84441604922..90c455b1d31 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1884,7 +1884,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<'T,bool> (0) with + { new Composer.Internal.Folder<'T,int> (0) with override this.ProcessNext value = if not (e2.MoveNext()) then this.Value <- 1 From 71150245ffb319eecb03fbd24e98281b8bb36672 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 13:17:25 +1100 Subject: [PATCH 199/286] Minimalist exposure of factory infrastructire - made SeqEnumerable<> into an interface (ISeq<>) - made SeqComponentFactory<> into an interface (ISeqFactory<>) --- src/fsharp/FSharp.Core/seq.fs | 230 +++++++++++++++++++-------------- src/fsharp/FSharp.Core/seq.fsi | 18 ++- 2 files changed, 147 insertions(+), 101 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 90c455b1d31..e309676c6a5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -521,9 +521,14 @@ namespace Microsoft.FSharp.Collections Value = init } - [] - type SeqEnumerable<'T>() = - abstract member ForEach<'a when 'a :> Consumer<'T,'T>> : f:((unit->unit)->'a) -> 'a + type ISeqFactory<'T,'U> = + abstract PipeIdx : PipeIdx + abstract Create<'V> : IPipeline -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> + + type ISeq<'T> = + inherit IEnumerable<'T> + abstract member Compose<'U> : (ISeqFactory<'T,'U>) -> ISeq<'U> + abstract member ForEach<'consumer when 'consumer :> Consumer<'T,'T>> : f:((unit->unit)->'consumer) -> 'consumer open Internal @@ -535,114 +540,136 @@ 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 upcastSeq (t:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) let inline upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastISeqComponent (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = - abstract Create<'V> : IPipeline -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> - new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) - member __.PipeIdx = getPipeIdx pipeIdx + interface ISeqFactory<'T,'U> with + member __.PipeIdx = getPipeIdx pipeIdx + member __.Create _ _ _ = failwith "library implementation error: Create on base factory should not be called" - and ComposedFactory<'T,'U,'V> private (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>, secondPipeIdx:PipeIdx) = + and ComposedFactory<'T,'U,'V> private (first:ISeqFactory<'T,'U>, second:ISeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) - override this.Create<'W> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = - first.Create result pipeIdx (second.Create result (makePipeIdx secondPipeIdx) next) + interface ISeqFactory<'T,'V> with + member this.Create<'W> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = + first.Create result pipeIdx (second.Create result (makePipeIdx secondPipeIdx) next) - static member Combine (first:SeqComponentFactory<'T,'U>) (second:SeqComponentFactory<'U,'V>) : SeqComponentFactory<'T,'V> = + static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = upcast ComposedFactory(first, second, first.PipeIdx+1) and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) + interface ISeqFactory<'T,'U> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) and DistinctFactory<'T when 'T: equality> () = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = - match next with - | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter - | _ -> upcast Filter (filter, next) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = + match next with + | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter + | _ -> upcast Filter (filter, next) and IdentityFactory<'T> () = inherit SeqComponentFactory<'T,'T> () static let singleton = IdentityFactory<'T>() - override __.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next + interface ISeqFactory<'T,'T> with + member __.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next static member IdentityFactory = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = - match next with - | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map - | _ -> upcast Map<_,_,_> (map, next) + interface ISeqFactory<'T,'U> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = + match next with + | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map + | _ -> upcast Map<_,_,_> (map, next) and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, result, next, getPipeIdx pipeIdx) + interface ISeqFactory<'First,'U> with + member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, result, next, getPipeIdx pipeIdx) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = inherit SeqComponentFactory<'Second,'U> () - override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, result, next, getPipeIdx pipeIdx) + interface ISeqFactory<'Second,'U> with + member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, result, next, getPipeIdx pipeIdx) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, getPipeIdx pipeIdx) + interface ISeqFactory<'First,'U> with + member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, getPipeIdx pipeIdx) and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) + interface ISeqFactory<'T,'U> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () - override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, result, next, getPipeIdx pipeIdx) + interface ISeqFactory<'First,'U> with + member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, result, next, getPipeIdx pipeIdx) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) + interface ISeqFactory<'T,'T*'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = inherit SeqComponentFactory<'T,'State> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) + interface ISeqFactory<'T,'State> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, result, next, getPipeIdx pipeIdx) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, result, next, getPipeIdx pipeIdx) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, result, next, getPipeIdx pipeIdx) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, result, next, getPipeIdx pipeIdx) and TailFactory<'T> () = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () - override this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, result, next, getPipeIdx pipeIdx) + interface ISeqFactory<'T,'T> with + member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, result, next, getPipeIdx pipeIdx) and [] SeqComponent<'T,'U> (next:ICompletionChaining) = inherit Consumer<'T,'U>() @@ -1019,7 +1046,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 - let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:SeqComponentFactory<'T,'U>) executeOn = + let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:ISeqFactory<'T,'U>) executeOn = let pipeline = Pipeline() let result = f (fun () -> (pipeline:>IPipeline).StopFurtherProcessing (current.PipeIdx+1)) let consumer = current.Create pipeline emptyPipeIdx result @@ -1067,9 +1094,9 @@ namespace Microsoft.FSharp.Collections | _ -> failwith "library implementation error: all states should have been handled" and [] EnumerableBase<'T> () = - inherit SeqEnumerable<'T>() + let derivedClassShouldImplement () = + failwith "library implementation error: derived class should implement (should be abstract)" - abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U> abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> default this.Append source = Helpers.upcastEnumerable (AppendEnumerable [this; source]) @@ -1081,8 +1108,11 @@ namespace Microsoft.FSharp.Collections Helpers.upcastEnumeratorNonGeneric genericEnumerator interface IEnumerable<'T> with - member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)" + member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () + interface ISeq<'T> with + member __.Compose _ = derivedClassShouldImplement () + member __.ForEach _ = derivedClassShouldImplement () and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, seqComponent) @@ -1110,7 +1140,7 @@ namespace Microsoft.FSharp.Collections finally (Helpers.upcastISeqComponent seqComponent).OnDispose () - and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) = + and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:ISeqFactory<'T,'U>) = inherit EnumerableBase<'U>() interface IEnumerable<'U> with @@ -1118,11 +1148,12 @@ namespace Microsoft.FSharp.Collections let result = Result<'U> () Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) - override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) + interface ISeq<'U> with + member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + Helpers.upcastSeq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.enumerable enumerable) + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.enumerable enumerable) and ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = let mutable state = SeqProcessNextStates.NotStarted @@ -1169,14 +1200,15 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () : IEnumerator<'T> = Helpers.upcastEnumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) - override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = - Helpers.upcastEnumerable (Enumerable<'T,'V>(this, next)) - override this.Append source = Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) - override this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) + interface ISeq<'T> with + member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + Helpers.upcastSeq (Enumerable<'T,'V>(this, next)) + + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) and ConcatEnumerable<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = inherit EnumerableBase<'T>() @@ -1185,14 +1217,15 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () : IEnumerator<'T> = Helpers.upcastEnumerator (new ConcatEnumerator<_,_> (sources)) - override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = - Helpers.upcastEnumerable (Enumerable<'T,'V>(this, next)) + interface ISeq<'T> with + member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + Helpers.upcastSeq (Enumerable<'T,'V>(this, next)) - override this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) let create enumerable current = - Helpers.upcastEnumerable (Enumerable(enumerable, current)) + Helpers.upcastSeq (Enumerable(enumerable, current)) module Array = type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = @@ -1226,7 +1259,7 @@ namespace Microsoft.FSharp.Collections initMoveNext () moveNext () - type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqComponentFactory<'T,'U>) = + type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:ISeqFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with @@ -1234,16 +1267,17 @@ namespace Microsoft.FSharp.Collections let result = Result<'U> () Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) + interface ISeq<'U> with + member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + Helpers.upcastSeq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.array (delayedArray ())) + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.array (delayedArray ())) - let createDelayed (delayedArray:unit->array<'T>) (current:SeqComponentFactory<'T,'U>) = - Helpers.upcastEnumerable (Enumerable(delayedArray, current)) + let createDelayed (delayedArray:unit->array<'T>) (current:ISeqFactory<'T,'U>) = + Helpers.upcastSeq (Enumerable(delayedArray, current)) - let create (array:array<'T>) (current:SeqComponentFactory<'T,'U>) = + let create (array:array<'T>) (current:ISeqFactory<'T,'U>) = createDelayed (fun () -> array) current let createDelayedId (delayedArray:unit -> array<'T>) = @@ -1276,7 +1310,7 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext list - type Enumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) = + type Enumerable<'T,'U>(alist:list<'T>, current:ISeqFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with @@ -1284,14 +1318,15 @@ namespace Microsoft.FSharp.Collections let result = Result<'U> () Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) + interface ISeq<'U> with + member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + Helpers.upcastSeq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.list alist) + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.list alist) let create alist current = - Helpers.upcastEnumerable (Enumerable(alist, current)) + Helpers.upcastSeq (Enumerable(alist, current)) module Unfold = type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, signal:Result<'U>) = @@ -1314,7 +1349,7 @@ namespace Microsoft.FSharp.Collections signal.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:SeqComponentFactory<'T,'U>) = + type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:ISeqFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with @@ -1322,11 +1357,12 @@ namespace Microsoft.FSharp.Collections let result = Result<'U> () Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) + interface ISeq<'U> with + member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + Helpers.upcastSeq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) - override this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.unfold generator state) + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.unfold generator state) module Init = // The original implementation of "init" delayed the calculation of Current, and so it was possible @@ -1387,7 +1423,7 @@ namespace Microsoft.FSharp.Collections signal.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) = + type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:ISeqFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with @@ -1395,12 +1431,13 @@ namespace Microsoft.FSharp.Collections let result = Result<'U> () Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> = - Helpers.upcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) + interface ISeq<'U> with + member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + Helpers.upcastSeq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) - override this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = - let terminatingIdx = getTerminatingIdx count - ForEach.execute createResult current (ForEach.init f terminatingIdx) + member this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = + let terminatingIdx = getTerminatingIdx count + ForEach.execute createResult current (ForEach.init f terminatingIdx) let upto lastOption f = match lastOption with @@ -1462,11 +1499,12 @@ namespace Microsoft.FSharp.Collections // in the way presented, but it's possible. upto (if count.HasValue then Some (count.Value-1) else None) f - override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> = - Helpers.upcastEnumerable (Enumerable<'T,'V>(count, f, next)) + interface ISeq<'T> with + member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + Helpers.upcastSeq (Enumerable<'T,'V>(count, f, next)) - override this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable (Helpers.upcastEnumerable this)) + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable (Helpers.upcastEnumerable this)) #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions @@ -1476,7 +1514,7 @@ namespace Microsoft.FSharp.Collections let inline indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) [] - let toComposer (source:seq<'T>): Composer.Internal.SeqEnumerable<'T> = + let toComposer (source:seq<'T>): Composer.Internal.ISeq<'T> = checkNonNull "source" source match source with | :? Composer.Enumerable.EnumerableBase<'T> as s -> upcast s @@ -1666,10 +1704,10 @@ namespace Microsoft.FSharp.Collections let private seqFactory createSeqComponent (source:seq<'T>) = checkNonNull "source" source match source with - | :? Composer.Enumerable.EnumerableBase<'T> as s -> s.Compose createSeqComponent - | :? array<'T> as a -> Composer.Array.create a createSeqComponent - | :? list<'T> as a -> Composer.List.create a createSeqComponent - | _ -> Composer.Enumerable.create source createSeqComponent + | :? Composer.Internal.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose createSeqComponent) + | :? array<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.Array.create a createSeqComponent) + | :? list<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.List.create a createSeqComponent) + | _ -> Composer.Helpers.upcastEnumerable (Composer.Enumerable.create source createSeqComponent) [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = @@ -1695,7 +1733,7 @@ namespace Microsoft.FSharp.Collections let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = checkNonNull "source1" source1 match source1 with - | :? Composer.Enumerable.EnumerableBase<'T> as s -> s.Compose (Composer.Map2FirstFactory (f, source2)) + | :? Composer.Internal.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose (Composer.Map2FirstFactory (f, source2))) | _ -> source2 |> seqFactory (Composer.Map2SecondFactory (f, source1)) [] @@ -1913,7 +1951,7 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source : 'T array) = checkNonNull "source" source - Composer.Array.createId source + Composer.Helpers.upcastEnumerable (Composer.Array.createId source) [] let toArray (source : seq<'T>) = @@ -2164,7 +2202,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceBy keyf array array - Composer.Array.createDelayedId delayedSort + Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedSort) [] let sort source = @@ -2173,7 +2211,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlace array array - Composer.Array.createDelayedId delayedSort + Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedSort) [] let sortWith f source = @@ -2182,7 +2220,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceWith f array array - Composer.Array.createDelayedId delayedSort + Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedSort) [] let inline sortByDescending keyf source = @@ -2518,7 +2556,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.Reverse array array - Composer.Array.createDelayedId delayedReverse + Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedReverse) [] let permute f (source:seq<_>) = @@ -2527,7 +2565,7 @@ namespace Microsoft.FSharp.Collections source |> toArray |> Array.permute f - Composer.Array.createDelayedId delayedPermute + Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedPermute) [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index b554294d6d8..7c4b8c34dcc 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -18,6 +18,7 @@ namespace Microsoft.FSharp.Collections /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the /// source of the chain. type PipeIdx = int + type ``PipeIdx?`` = Nullable /// ICompletionChaining is used to correctly handle cleaning up of the pipeline. A /// base implementation is provided in Consumer, and should not be overwritten. Consumer @@ -34,6 +35,9 @@ namespace Microsoft.FSharp.Collections /// after the enumeration has completed. abstract OnDispose : unit -> unit + type IPipeline = + abstract StopFurtherProcessing : PipeIdx -> unit + /// Consumer is the base class of all elements within the pipeline [] type Consumer<'T,'U> = @@ -69,10 +73,14 @@ namespace Microsoft.FSharp.Collections new : init:'U -> Folder<'T,'U> val mutable Value: 'U - /// SeqEnumerable functions provide the enhance seq experience - [] - type SeqEnumerable<'T> = - abstract member ForEach<'a when 'a :> Consumer<'T,'T>> : f:((unit->unit)->'a) -> 'a + type ISeqFactory<'T,'U> = + abstract member Create : IPipeline -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> + abstract member PipeIdx : PipeIdx + + type ISeq<'T> = + inherit System.Collections.Generic.IEnumerable<'T> + abstract member Compose : ISeqFactory<'T,'U> -> ISeq<'U> + abstract member ForEach : f:((unit -> unit) -> 'a) -> 'a when 'a :> Consumer<'T,'T> /// Returns a new sequence that contains the cartesian product of the two input sequences. /// The first sequence. @@ -1265,7 +1273,7 @@ namespace Microsoft.FSharp.Collections /// /// Thrown when the input sequence is null. [] - val toComposer : source:seq<'T> -> Composer.Internal.SeqEnumerable<'T> + val toComposer : source:seq<'T> -> Composer.Internal.ISeq<'T> /// Builds a list from the given collection. /// From 4f0e2f05db48e430417c874593226bf9b9f9026b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 13:36:13 +1100 Subject: [PATCH 200/286] Renaming recommentations base on @rmunn feedback --- src/fsharp/FSharp.Core/seq.fs | 144 ++++++++++++++++----------------- src/fsharp/FSharp.Core/seq.fsi | 4 +- 2 files changed, 74 insertions(+), 74 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index e309676c6a5..e386fe13488 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -467,7 +467,7 @@ namespace Microsoft.FSharp.Collections abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit - type IPipeline = + type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit [] @@ -523,7 +523,7 @@ namespace Microsoft.FSharp.Collections type ISeqFactory<'T,'U> = abstract PipeIdx : PipeIdx - abstract Create<'V> : IPipeline -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> + abstract Create<'V> : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> type ISeq<'T> = inherit IEnumerable<'T> @@ -544,7 +544,7 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline upcastISeqComponent (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) + let inline upcastICompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) @@ -557,8 +557,8 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) interface ISeqFactory<'T,'V> with - member this.Create<'W> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = - first.Create result pipeIdx (second.Create result (makePipeIdx secondPipeIdx) next) + member this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = + first.Create outOfBand pipeIdx (second.Create outOfBand (makePipeIdx secondPipeIdx) next) static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = upcast ComposedFactory(first, second, first.PipeIdx+1) @@ -566,27 +566,27 @@ namespace Microsoft.FSharp.Collections and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () interface ISeqFactory<'T,'U> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) and DistinctFactory<'T when 'T: equality> () = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) and FilterFactory<'T> (filter:'T->bool) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = match next with | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter | _ -> upcast Filter (filter, next) @@ -595,13 +595,13 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'T> () static let singleton = IdentityFactory<'T>() interface ISeqFactory<'T,'T> with - member __.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next + member __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next static member IdentityFactory = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () interface ISeqFactory<'T,'U> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = match next with | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map | _ -> upcast Map<_,_,_> (map, next) @@ -609,67 +609,67 @@ namespace Microsoft.FSharp.Collections and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () interface ISeqFactory<'First,'U> with - member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, result, next, getPipeIdx pipeIdx) + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, outOfBand, next, getPipeIdx pipeIdx) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = inherit SeqComponentFactory<'Second,'U> () interface ISeqFactory<'Second,'U> with - member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, result, next, getPipeIdx pipeIdx) + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, outOfBand, next, getPipeIdx pipeIdx) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = inherit SeqComponentFactory<'First,'U> () interface ISeqFactory<'First,'U> with - member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, result, next, getPipeIdx pipeIdx) + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, outOfBand, next, getPipeIdx pipeIdx) and MapiFactory<'T,'U> (mapi:int->'T->'U) = inherit SeqComponentFactory<'T,'U> () interface ISeqFactory<'T,'U> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqComponentFactory<'First,'U> () interface ISeqFactory<'First,'U> with - member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, result, next, getPipeIdx pipeIdx) + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, outOfBand, next, getPipeIdx pipeIdx) and PairwiseFactory<'T> () = inherit SeqComponentFactory<'T,'T*'T> () interface ISeqFactory<'T,'T*'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = inherit SeqComponentFactory<'T,'State> () interface ISeqFactory<'T,'State> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) and SkipFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, result, next, getPipeIdx pipeIdx) + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, outOfBand, next, getPipeIdx pipeIdx) and TakeFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, result, next, getPipeIdx pipeIdx) + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, getPipeIdx pipeIdx) and TailFactory<'T> () = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_result:IPipeline) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (result:IPipeline) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, result, next, getPipeIdx pipeIdx) + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, getPipeIdx pipeIdx) and [] SeqComponent<'T,'U> (next:ICompletionChaining) = inherit Consumer<'T,'U>() @@ -763,7 +763,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = Helpers.avoidTailCall (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -773,13 +773,13 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) else - result.StopFurtherProcessing pipeIdx + outOfBand.StopFurtherProcessing pipeIdx false override __.OnDispose () = input2.Dispose () - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = + and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'Second,'V>(next) let input1 = enumerable1.GetEnumerator () @@ -789,13 +789,13 @@ namespace Microsoft.FSharp.Collections if input1.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) else - result.StopFurtherProcessing pipeIdx + outOfBand.StopFurtherProcessing pipeIdx false override __.OnDispose () = input1.Dispose () - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = + and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () @@ -806,7 +806,7 @@ namespace Microsoft.FSharp.Collections if input2.MoveNext () && input3.MoveNext () then Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) else - result.StopFurtherProcessing pipeIdx + outOfBand.StopFurtherProcessing pipeIdx false override __.OnDispose () = @@ -833,7 +833,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:IPipeline, next:Consumer<'U,'V>, pipeIdx:int) = + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) let mutable idx = 0 @@ -845,7 +845,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 Helpers.avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) else - result.StopFurtherProcessing pipeIdx + outOfBand.StopFurtherProcessing pipeIdx false override __.OnDispose () = @@ -917,8 +917,8 @@ namespace Microsoft.FSharp.Collections else Helpers.avoidTailCall (next.ProcessNext input) - and Take<'T,'V> (takeCount:int, result:IPipeline, next:Consumer<'T,'V>, pipelineIdx:int) = - inherit Truncate<'T, 'V>(takeCount, result, next, pipelineIdx) + and Take<'T,'V> (takeCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipelineIdx:int) = + inherit Truncate<'T, 'V>(takeCount, outOfBand, next, pipelineIdx) override this.OnComplete terminatingIdx = if terminatingIdx < pipelineIdx && this.Count < takeCount then @@ -926,14 +926,14 @@ namespace Microsoft.FSharp.Collections invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - and TakeWhile<'T,'V> (predicate:'T->bool, result:IPipeline, next:Consumer<'T,'V>, pipeIdx:int) = + and TakeWhile<'T,'V> (predicate:'T->bool, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = if predicate input then Helpers.avoidTailCall (next.ProcessNext input) else - result.StopFurtherProcessing pipeIdx + outOfBand.StopFurtherProcessing pipeIdx false and Tail<'T, 'V> (next:Consumer<'T,'V>) = @@ -952,7 +952,7 @@ namespace Microsoft.FSharp.Collections if first then invalidArg "source" (SR.GetString(SR.notEnoughElements)) - and Truncate<'T,'V> (truncateCount:int, result:IPipeline, next:Consumer<'T,'V>, pipeIdx:int) = + and Truncate<'T,'V> (truncateCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -963,10 +963,10 @@ namespace Microsoft.FSharp.Collections if count < truncateCount then count <- count + 1 if count = truncateCount then - result.StopFurtherProcessing pipeIdx + outOfBand.StopFurtherProcessing pipeIdx next.ProcessNext input else - result.StopFurtherProcessing pipeIdx + outOfBand.StopFurtherProcessing pipeIdx false type SeqProcessNextStates = @@ -981,7 +981,7 @@ namespace Microsoft.FSharp.Collections member val SeqState = SeqProcessNextStates.NotStarted with get, set member __.HaltedIdx = haltedIdx - interface IPipeline with + interface IOutOfBand with member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx // SetResult<> is used at the end of the chain of SeqComponents to assign the final value @@ -992,35 +992,35 @@ namespace Microsoft.FSharp.Collections result.Current <- input true - type Pipeline() = + type OutOfBand() = let mutable haltedIdx = 0 - interface IPipeline with member x.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx + interface IOutOfBand with member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx member __.HaltedIdx = haltedIdx module ForEach = - let enumerable (enumerable:IEnumerable<'T>) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = + let enumerable (enumerable:IEnumerable<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = use enumerator = enumerable.GetEnumerator () - while (pipeline.HaltedIdx = 0) && (enumerator.MoveNext ()) do + while (outOfBand.HaltedIdx = 0) && (enumerator.MoveNext ()) do consumer.ProcessNext enumerator.Current |> ignore - let array (array:array<'T>) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = + let array (array:array<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = let mutable idx = 0 - while (pipeline.HaltedIdx = 0) && (idx < array.Length) do + while (outOfBand.HaltedIdx = 0) && (idx < array.Length) do consumer.ProcessNext array.[idx] |> ignore idx <- idx + 1 - let list (alist:list<'T>) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = + let list (alist:list<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = let rec iterate lst = - match pipeline.HaltedIdx, lst with + match outOfBand.HaltedIdx, lst with | 0, hd :: tl -> consumer.ProcessNext hd |> ignore iterate tl | _ -> () iterate alist - let unfold (generator:'S->option<'T*'S>) state (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = + let unfold (generator:'S->option<'T*'S>) state (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = let rec iterate current = - match pipeline.HaltedIdx, generator current with + match outOfBand.HaltedIdx, generator current with | 0, Some (item, next) -> consumer.ProcessNext item |> ignore iterate next @@ -1033,11 +1033,11 @@ namespace Microsoft.FSharp.Collections | :? SeqComponent<'T,'U> as c -> c.Skipping | _ -> fun () -> false - let init f (terminatingIdx:int) (pipeline:Pipeline) (consumer:Consumer<'T,'U>) = + let init f (terminatingIdx:int) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = let mutable idx = -1 let isSkipping = makeIsSkipping consumer let mutable maybeSkipping = true - while (pipeline.HaltedIdx = 0) && (idx < terminatingIdx) do + while (outOfBand.HaltedIdx = 0) && (idx < terminatingIdx) do if maybeSkipping then maybeSkipping <- isSkipping () @@ -1047,15 +1047,15 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:ISeqFactory<'T,'U>) executeOn = - let pipeline = Pipeline() - let result = f (fun () -> (pipeline:>IPipeline).StopFurtherProcessing (current.PipeIdx+1)) + let pipeline = OutOfBand() + let result = f (fun () -> (pipeline:>IOutOfBand).StopFurtherProcessing (current.PipeIdx+1)) let consumer = current.Create pipeline emptyPipeIdx result try executeOn pipeline consumer - (Helpers.upcastISeqComponent consumer).OnComplete pipeline.HaltedIdx + (Helpers.upcastICompletionChaining consumer).OnComplete pipeline.HaltedIdx result finally - (Helpers.upcastISeqComponent consumer).OnDispose () + (Helpers.upcastICompletionChaining consumer).OnDispose () module Enumerable = type Empty<'T>() = @@ -1125,7 +1125,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete result.HaltedIdx + (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1138,7 +1138,7 @@ namespace Microsoft.FSharp.Collections try source.Dispose () finally - (Helpers.upcastISeqComponent seqComponent).OnDispose () + (Helpers.upcastICompletionChaining seqComponent).OnDispose () and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:ISeqFactory<'T,'U>) = inherit EnumerableBase<'U>() @@ -1251,7 +1251,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete result.HaltedIdx + (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1302,7 +1302,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete result.HaltedIdx + (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1329,13 +1329,13 @@ namespace Microsoft.FSharp.Collections Helpers.upcastSeq (Enumerable(alist, current)) module Unfold = - type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, signal:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) + type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable current = state let rec moveNext () = - match signal.HaltedIdx, generator current with + match result.HaltedIdx, generator current with | 0, Some (item, nextState) -> current <- nextState if seqComponent.ProcessNext item then @@ -1346,7 +1346,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerator with member __.MoveNext () = - signal.SeqState <- SeqProcessNextStates.InProcess + result.SeqState <- SeqProcessNextStates.InProcess moveNext () type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:ISeqFactory<'T,'U>) = @@ -1384,8 +1384,8 @@ namespace Microsoft.FSharp.Collections else System.Int32.MaxValue - type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:Consumer<'T,'U>, signal:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent) + type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let isSkipping = ForEach.makeIsSkipping seqComponent @@ -1397,7 +1397,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = -1 let rec moveNext () = - if (signal.HaltedIdx = 0) && idx < terminatingIdx then + if (result.HaltedIdx = 0) && idx < terminatingIdx then idx <- idx + 1 if maybeSkipping then @@ -1411,16 +1411,16 @@ namespace Microsoft.FSharp.Collections true else moveNext () - elif (signal.HaltedIdx = 0) && idx = System.Int32.MaxValue then + elif (result.HaltedIdx = 0) && idx = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else - signal.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastISeqComponent seqComponent).OnComplete signal.HaltedIdx + result.SeqState <- SeqProcessNextStates.Finished + (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with member __.MoveNext () = - signal.SeqState <- SeqProcessNextStates.InProcess + result.SeqState <- SeqProcessNextStates.InProcess moveNext () type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:ISeqFactory<'T,'U>) = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 7c4b8c34dcc..a84a71fc037 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -35,7 +35,7 @@ namespace Microsoft.FSharp.Collections /// after the enumeration has completed. abstract OnDispose : unit -> unit - type IPipeline = + type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit /// Consumer is the base class of all elements within the pipeline @@ -74,7 +74,7 @@ namespace Microsoft.FSharp.Collections val mutable Value: 'U type ISeqFactory<'T,'U> = - abstract member Create : IPipeline -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> + abstract member Create : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> abstract member PipeIdx : PipeIdx type ISeq<'T> = From 72787b6bb8bf931e736c91cac5a893127b221a8b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 13:40:36 +1100 Subject: [PATCH 201/286] Commented strange Unchecked.default usage --- src/fsharp/FSharp.Core/seq.fs | 47 +++++++++++++++++------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index e386fe13488..12a387d2991 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1565,7 +1565,7 @@ namespace Microsoft.FSharp.Collections { new Composer.Internal.Consumer<'T,'T> () with override this.ProcessNext value = f value - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore [] @@ -1600,7 +1600,7 @@ namespace Microsoft.FSharp.Collections halt () else this.Value._1 <- this.Value._1 + 1 - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun item -> item.Value._2 [] @@ -1615,7 +1615,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = f.Invoke(this.Value, value) this.Value <- this.Value + 1 - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore [] @@ -1627,7 +1627,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Value <- true halt () - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun exists -> exists.Value @@ -1640,7 +1640,7 @@ namespace Microsoft.FSharp.Collections if element = value then this.Value <- true halt () - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun contains -> contains.Value @@ -1653,7 +1653,7 @@ namespace Microsoft.FSharp.Collections if not (f value) then this.Value <- false halt () - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun forall -> forall.Value @@ -1774,7 +1774,7 @@ namespace Microsoft.FSharp.Collections this.Value <- some halt () | None -> () - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun pick -> pick.Value [] @@ -1792,7 +1792,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Value <- Some value halt () - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun find -> find.Value [] @@ -1847,7 +1847,7 @@ namespace Microsoft.FSharp.Collections { new Composer.Internal.Folder<'T,'State> (x) with override this.ProcessNext value = this.Value <- f.Invoke (this.Value, value) - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun folded -> folded.Value source @@ -1889,7 +1889,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value else this.Value._2 <- f.Invoke (this.Value._2, value) - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._1 then @@ -1932,7 +1932,7 @@ namespace Microsoft.FSharp.Collections if c <> 0 then this.Value <- c halt () - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value = 0 && e2.MoveNext() then this.Value <- -1 }) @@ -2046,8 +2046,7 @@ namespace Microsoft.FSharp.Collections halt () else this.Value._2 <- this.Value._2 + 1 - Unchecked.defaultof - }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun tried -> tried.Value._1 [] @@ -2274,7 +2273,7 @@ namespace Microsoft.FSharp.Collections { new Composer.Internal.Folder<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value value - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun sum -> sum.Value [] @@ -2284,7 +2283,7 @@ namespace Microsoft.FSharp.Collections { new Composer.Internal.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value (f value) - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun sum -> sum.Value [] @@ -2295,7 +2294,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 value this.Value._2 <- this.Value._2 + 1 - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._2 = 0 then @@ -2310,7 +2309,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 (f value) this.Value._2 <- this.Value._2 + 1 - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._2 = 0 then @@ -2333,7 +2332,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value elif value < this.Value._2 then this.Value._2 <- value - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._1 then @@ -2356,7 +2355,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- valueU this.Value._3 <- value | _ -> () - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._1 then @@ -2391,7 +2390,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value elif value > this.Value._2 then this.Value._2 <- value - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._1 then @@ -2414,7 +2413,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- valueU this.Value._3 <- value | _ -> () - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._1 then @@ -2473,7 +2472,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Value <- Some value halt () - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun head -> head.Value source1 @@ -2508,7 +2507,7 @@ namespace Microsoft.FSharp.Collections if this.Value._1 then this.Value._1 <- false this.Value._2 <- value - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun tried -> if tried.Value._1 then None @@ -2533,7 +2532,7 @@ namespace Microsoft.FSharp.Collections else this.Value._3 <- true halt () - Unchecked.defaultof + Unchecked.defaultof<_> (* return value unsed in ForEach context *) member this.OnComplete _ = if this.Value._1 then From 92eb76891d40dde4b48112baed2ec99ac8b91785 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 19:58:10 +1100 Subject: [PATCH 202/286] Partial move to Composer module In the Composer module we use ISeq rather than seq. An end goal could be be publicly expose this module for enhanced performancy. --- src/fsharp/FSharp.Core/seq.fs | 332 +++++++++++++++++++++++----------- 1 file changed, 222 insertions(+), 110 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 12a387d2991..ea249208d6d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -541,6 +541,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 upcastSeq (t:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) + let inline upcastFactory (t:#ISeqFactory<'T,'U>) : ISeqFactory<'T,'U> = (# "" t : ISeqFactory<'T,'U> #) let inline upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) @@ -561,7 +562,7 @@ namespace Microsoft.FSharp.Collections first.Create outOfBand pipeIdx (second.Create outOfBand (makePipeIdx secondPipeIdx) next) static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = - upcast ComposedFactory(first, second, first.PipeIdx+1) + ComposedFactory(first, second, first.PipeIdx+1) |> Helpers.upcastFactory and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () @@ -596,7 +597,7 @@ namespace Microsoft.FSharp.Collections static let singleton = IdentityFactory<'T>() interface ISeqFactory<'T,'T> with member __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next - static member IdentityFactory = singleton + static member Instance = singleton and MapFactory<'T,'U> (map:'T->'U) = inherit SeqComponentFactory<'T,'U> () @@ -1208,7 +1209,7 @@ namespace Microsoft.FSharp.Collections Helpers.upcastSeq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) and ConcatEnumerable<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = inherit EnumerableBase<'T>() @@ -1222,11 +1223,33 @@ namespace Microsoft.FSharp.Collections Helpers.upcastSeq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable this) + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) let create enumerable current = Helpers.upcastSeq (Enumerable(enumerable, current)) + 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 = + Helpers.upcastEnumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) + + interface ISeq<'T> with + member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + Helpers.upcastSeq (Enumerable.Enumerable<'T,'V>(this, next)) + + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) + + + module Array = type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) @@ -1281,10 +1304,10 @@ namespace Microsoft.FSharp.Collections createDelayed (fun () -> array) current let createDelayedId (delayedArray:unit -> array<'T>) = - createDelayed delayedArray IdentityFactory.IdentityFactory + createDelayed delayedArray IdentityFactory.Instance let createId (array:array<'T>) = - create array IdentityFactory.IdentityFactory + create array IdentityFactory.Instance module List = type Enumerator<'T,'U>(alist:list<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = @@ -1504,7 +1527,167 @@ namespace Microsoft.FSharp.Collections Helpers.upcastSeq (Enumerable<'T,'V>(count, f, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.IdentityFactory (ForEach.enumerable (Helpers.upcastEnumerable this)) + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (Helpers.upcastEnumerable this)) + + open RuntimeHelpers + + [] + let toComposer (source:seq<'T>) : ISeq<'T> = + checkNonNull "source" source + match source with + | :? ISeq<'T> as s -> s + | :? array<'T> as a -> Helpers.upcastSeq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) + | :? list<'T> as a -> Helpers.upcastSeq (List.Enumerable(a, IdentityFactory.Instance)) + | _ -> Helpers.upcastSeq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) + + let inline foreach f (source:ISeq<_>) = + source.ForEach f + + let inline compose factory (source:ISeq<'T>) = + source.Compose factory + + [] + let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance + + [] + let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = + Helpers.upcastSeq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) + + [] + let initInfinite<'T> (f:int->'T) : ISeq<'T> = + Helpers.upcastSeq (new Init.EnumerableDecider<'T>(Nullable (), f)) + + [] + let init<'T> (count:int) (f:int->'T) : ISeq<'T> = + if count < 0 then invalidArgInputMustBeNonNegative "count" count + elif count = 0 then empty else + Helpers.upcastSeq (new Init.EnumerableDecider<'T>(Nullable count, f)) + + [] + let iter f (source:ISeq<'T>) = + source + |> foreach (fun _ -> + { new Consumer<'T,'T> () with + override this.ProcessNext value = + f value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> ignore + + [] + let tryItem i (source:ISeq<'T>) = + if i < 0 then None else + source + |> foreach (fun halt -> + { new Folder<'T, Values>> (Values<_,_> (0, None)) with + override this.ProcessNext value = + if this.Value._1 = i then + this.Value._2 <- Some value + halt () + else + this.Value._1 <- this.Value._1 + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun item -> item.Value._2 + + [] + let iteri f (source:ISeq<'T>) = + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f + + source + |> foreach (fun _ -> + { new Folder<'T, int> (0) with + override this.ProcessNext value = + f.Invoke(this.Value, value) + this.Value <- this.Value + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> ignore + + [] + let exists f (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, bool> (false) with + override this.ProcessNext value = + if f value then + this.Value <- true + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun exists -> exists.Value + + [] + let inline contains element (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, bool> (false) with + override this.ProcessNext value = + if element = value then + this.Value <- true + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun contains -> contains.Value + + [] + let forall f (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, bool> (true) with + override this.ProcessNext value = + if not (f value) then + this.Value <- false + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun forall -> forall.Value + + [] + let filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = + source + |> compose (FilterFactory f) + + [] + let map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = + source + |> compose (MapFactory f) + + [] + let mapi f source = + source + |> compose (MapiFactory f) + + [] + let choose f source = + source + |> compose (ChooseFactory f) + + [] + let indexed source = + source + |> compose (MapiFactory (fun i x -> i,x)) + + [] + let tryPick f (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, Option<'U>> (None) with + override this.ProcessNext value = + match f value with + | (Some _) as some -> + this.Value <- some + halt () + | None -> () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun pick -> pick.Value + + [] + let tryFind f (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, Option<'T>> (None) with + override this.ProcessNext value = + if f value then + this.Value <- Some value + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun find -> find.Value + #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions @@ -1515,17 +1698,10 @@ namespace Microsoft.FSharp.Collections [] let toComposer (source:seq<'T>): Composer.Internal.ISeq<'T> = - checkNonNull "source" source - match source with - | :? Composer.Enumerable.EnumerableBase<'T> as s -> upcast s - | :? array<'T> as a -> upcast Composer.Array.Enumerable((fun () -> a), Composer.IdentityFactory.IdentityFactory) - | :? list<'T> as a -> upcast Composer.List.Enumerable(a, Composer.IdentityFactory.IdentityFactory) - | _ -> upcast Composer.Enumerable.Enumerable<'T,'T>(source, Composer.IdentityFactory.IdentityFactory) + Composer.toComposer source let inline foreach f (source:seq<_>) = - source - |> toComposer - |> fun composer -> composer.ForEach f + Composer.foreach f (toComposer source) let inline foreach f (source:seq<_>) = Composer.Seq.foreach f (toComposer source) @@ -1543,30 +1719,25 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : seq<'T> = - Composer.Helpers.upcastEnumerable (new Composer.Unfold.Enumerable<'T,'T,'State>(generator, state, Composer.IdentityFactory.IdentityFactory)) + Composer.unfold generator state + |> Composer.Helpers.upcastEnumerable [] let empty<'T> = (EmptyEnumerable :> seq<'T>) [] let initInfinite<'T> (f:int->'T) : IEnumerable<'T> = - Composer.Helpers.upcastEnumerable (new Composer.Init.EnumerableDecider<'T>(Nullable (), f)) + Composer.initInfinite f + |> Composer.Helpers.upcastEnumerable [] let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> = - if count < 0 then invalidArgInputMustBeNonNegative "count" count - elif count = 0 then empty else - Composer.Helpers.upcastEnumerable (new Composer.Init.EnumerableDecider<'T>(Nullable count, f)) + Composer.init count f + |> Composer.Helpers.upcastEnumerable [] let iter f (source : seq<'T>) = - source - |> foreach (fun _ -> - { new Composer.Internal.Consumer<'T,'T> () with - override this.ProcessNext value = - f value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> ignore + Composer.iter f (toComposer source) [] let tryHead (source : seq<_>) = @@ -1589,73 +1760,27 @@ namespace Microsoft.FSharp.Collections | Some value -> value [] - let tryItem i (source : seq<'T>) = - if i < 0 then None else - source - |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Composer.Internal.Values>> (Composer.Internal.Values<_, _> (0, None)) with - override this.ProcessNext value = - if this.Value._1 = i then - this.Value._2 <- Some value - halt () - else - this.Value._1 <- this.Value._1 + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun item -> item.Value._2 + let tryItem i (source:seq<'T>) = + Composer.tryItem i (toComposer source) [] let nth i (source : seq<'T>) = item i source [] - let iteri f (source : seq<'T>) = - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - source - |> foreach (fun _ -> - { new Composer.Internal.Folder<'T, int> (0) with - override this.ProcessNext value = - f.Invoke(this.Value, value) - this.Value <- this.Value + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> ignore + let iteri f (source:seq<'T>) = + Composer.iteri f (toComposer source) [] - let exists f (source : seq<'T>) = - source - |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, bool> (false) with - override this.ProcessNext value = - if f value then - this.Value <- true - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - }) - |> fun exists -> exists.Value + let exists f (source:seq<'T>) = + Composer.exists f (toComposer source) [] - let inline contains element (source : seq<'T>) = - source - |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, bool> (false) with - override this.ProcessNext value = - if element = value then - this.Value <- true - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - }) - |> fun contains -> contains.Value + let inline contains element (source:seq<'T>) = + Composer.contains element (toComposer source) [] - let forall f (source : seq<'T>) = - source - |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, bool> (true) with - override this.ProcessNext value = - if not (f value) then - this.Value <- false - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - }) - |> fun forall -> forall.Value + let forall f (source:seq<'T>) = + Composer.forall f (toComposer source) [] let iter2 f (source1 : seq<_>) (source2 : seq<_>) = @@ -1711,18 +1836,21 @@ namespace Microsoft.FSharp.Collections [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = - source |> seqFactory (Composer.FilterFactory f) + Composer.filter f (toComposer source) + |> Composer.Helpers.upcastEnumerable [] let where f source = filter f source [] let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> = - source |> seqFactory (Composer.MapFactory f) + Composer.map f (toComposer source) + |> Composer.Helpers.upcastEnumerable [] let mapi f source = - source |> seqFactory (Composer.MapiFactory f) + Composer.mapi f (toComposer source) + |> Composer.Helpers.upcastEnumerable [] let mapi2 f source1 source2 = @@ -1743,12 +1871,14 @@ namespace Microsoft.FSharp.Collections source1 |> seqFactory (Composer.Map3Factory (f, source2, source3)) [] - let choose f source = - source |> seqFactory (Composer.ChooseFactory f) + let choose f source = + Composer.choose f (toComposer source) + |> Composer.Helpers.upcastEnumerable [] let indexed source = - source |> seqFactory (Composer.MapiFactory (fun i x -> i,x) ) + Composer.indexed (toComposer source) + |> Composer.Helpers.upcastEnumerable [] let zip source1 source2 = @@ -1765,17 +1895,7 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source : seq<'T>) = - source - |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Option<'U>> (None) with - override this.ProcessNext value = - match f value with - | (Some _) as some -> - this.Value <- some - halt () - | None -> () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun pick -> pick.Value + Composer.tryPick f (toComposer source) [] let pick f source = @@ -1785,15 +1905,7 @@ namespace Microsoft.FSharp.Collections [] let tryFind f (source : seq<'T>) = - source - |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Option<'T>> (None) with - override this.ProcessNext value = - if f value then - this.Value <- Some value - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun find -> find.Value + Composer.tryFind f (toComposer source) [] let find f source = From 766e16852950cfbf9fbdb33f80193bbfc71d8758 Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 29 Oct 2016 22:26:16 -0400 Subject: [PATCH 203/286] Seq.item/iter2/iteri2/fold2/forall2/exists2 --- src/fsharp/FSharp.Core/seq.fs | 63 ++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ea249208d6d..36116e3bc7e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1752,12 +1752,25 @@ namespace Microsoft.FSharp.Collections [] let item i (source : seq<'T>) = if i < 0 then invalidArgInputMustBeNonNegative "index" i else - source - |> seqFactory (Composer.Seq.SkipFactory (i, invalidArgumnetIndex)) - |> tryHead - |> function - | None -> invalidArgFmt "index" "{0}\nseq was short by 1 element" [|SR.GetString SR.notEnoughElements|] - | Some value -> value + source + |> foreach (fun halt -> + { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values<_,_,_> (0, false, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 = i then + this.Value._2 <- true + this.Value._3 <- value + halt () + else + this.Value._1 <- this.Value._1 + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + override this.OnComplete _ = + if not this.Value._2 then + let index = i - this.Value._1 + 1 + invalidArgFmt "index" + "{0}\nseq was short by {1} {2}" + [|SR.GetString SR.notEnoughElements; index; (if index=1 then "element" else "elements")|] + }) + |> fun item -> item.Value._3 [] let tryItem i (source:seq<'T>) = @@ -1791,7 +1804,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Core.Folder<_,_> () with + { new Composer.Internal.Folder<_,_> () with override this.ProcessNext value = if (e2.MoveNext()) then f.Invoke(value, e2.Current) @@ -1809,7 +1822,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Core.Folder<_,int> (0) with + { new Composer.Internal.Folder<_,int> (0) with override this.ProcessNext value = if (e2.MoveNext()) then f.Invoke(this.Value, value, e2.Current) @@ -1979,7 +1992,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Core.Folder<_,'State> (state) with + { new Composer.Internal.Folder<_,'State> (state) with override this.ProcessNext value = if (e2.MoveNext()) then this.Value <- f.Invoke(this.Value, value, e2.Current) @@ -2011,7 +2024,13 @@ namespace Microsoft.FSharp.Collections [] let replicate count x = + #if FX_ATLEAST_40 System.Linq.Enumerable.Repeat(x,count) + #else + if count < 0 then invalidArg "count" (SR.GetString(SR.inputMustBeNonNegative)) + seq { for _ in 1 .. count -> x } + #endif + [] let append (source1: seq<'T>) (source2: seq<'T>) = @@ -2569,12 +2588,38 @@ namespace Microsoft.FSharp.Collections use e2 = source2.GetEnumerator() let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(p) + source1 + |> foreach (fun halt -> + { new Composer.Internal.Folder<_,bool> (true) with + override this.ProcessNext value = + if (e2.MoveNext()) then + if not (p.Invoke(value, e2.Current)) then + this.Value <- false + halt() + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun all -> all.Value + [] let exists2 p (source1: seq<_>) (source2: seq<_>) = checkNonNull "source2" source2 use e2 = source2.GetEnumerator() let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(p) + + source1 + |> foreach (fun halt -> + { new Composer.Internal.Folder<_,bool> (false) with + override this.ProcessNext value = + if (e2.MoveNext()) then + if p.Invoke(value, e2.Current) then + this.Value <- true + halt() + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun exists -> exists.Value [] let tryHead (source : seq<_>) = From 062da7b4b0fc75f3836d2350134e49951f3090e7 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 30 Oct 2016 14:56:56 +1100 Subject: [PATCH 204/286] Removed Helpers. qualifier Names are unique and descriptive enough --- src/fsharp/FSharp.Core/seq.fs | 126 +++++++++++++++++----------------- 1 file changed, 64 insertions(+), 62 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 36116e3bc7e..18e837ab9a2 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -547,6 +547,8 @@ namespace Microsoft.FSharp.Collections let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline upcastICompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) + open Helpers + type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) @@ -562,7 +564,7 @@ namespace Microsoft.FSharp.Collections first.Create outOfBand pipeIdx (second.Create outOfBand (makePipeIdx secondPipeIdx) next) static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = - ComposedFactory(first, second, first.PipeIdx+1) |> Helpers.upcastFactory + ComposedFactory(first, second, first.PipeIdx+1) |> upcastFactory and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () @@ -700,7 +702,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = match choose input with - | Some value -> Helpers.avoidTailCall (next.ProcessNext value) + | Some value -> avoidTailCall (next.ProcessNext value) | None -> false and Distinct<'T,'V when 'T: equality> (next:Consumer<'T,'V>) = @@ -710,7 +712,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if hashSet.Add input then - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else false @@ -721,7 +723,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if hashSet.Add(keyFunction input) then - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else false @@ -732,7 +734,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if cached.Value.Add input then - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else false @@ -743,7 +745,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if filter input then - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else false @@ -752,7 +754,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if filter input then - Helpers.avoidTailCall (next.ProcessNext (map input)) + avoidTailCall (next.ProcessNext (map input)) else false @@ -762,7 +764,7 @@ namespace Microsoft.FSharp.Collections override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) override __.ProcessNext (input:'T) : bool = - Helpers.avoidTailCall (next.ProcessNext (map input)) + avoidTailCall (next.ProcessNext (map input)) and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) @@ -772,7 +774,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'First) : bool = if input2.MoveNext () then - Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) + avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -788,7 +790,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'Second) : bool = if input1.MoveNext () then - Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) + avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -805,7 +807,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'First) : bool = if input2.MoveNext () && input3.MoveNext () then - Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) + avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -820,7 +822,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = let u = map input if filter u then - Helpers.avoidTailCall (next.ProcessNext u) + avoidTailCall (next.ProcessNext u) else false @@ -832,7 +834,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = idx <- idx + 1 - Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) + avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) @@ -844,7 +846,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'First) : bool = if input2.MoveNext () then idx <- idx + 1 - Helpers.avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) + avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -866,7 +868,7 @@ namespace Microsoft.FSharp.Collections else let currentPair = lastValue, input lastValue <- input - Helpers.avoidTailCall (next.ProcessNext currentPair) + avoidTailCall (next.ProcessNext currentPair) and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:Consumer<'State,'V>) = inherit SeqComponent<'T,'V>(next) @@ -876,7 +878,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = foldResult <- f.Invoke(foldResult, input) - Helpers.avoidTailCall (next.ProcessNext foldResult) + avoidTailCall (next.ProcessNext foldResult) and Skip<'T,'V> (skipCount:int, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -895,7 +897,7 @@ namespace Microsoft.FSharp.Collections count <- count + 1 false else - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) override __.OnComplete _ = if count < skipCount then @@ -914,9 +916,9 @@ namespace Microsoft.FSharp.Collections if skip then false else - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) and Take<'T,'V> (takeCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipelineIdx:int) = inherit Truncate<'T, 'V>(takeCount, outOfBand, next, pipelineIdx) @@ -932,7 +934,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if predicate input then - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else outOfBand.StopFurtherProcessing pipeIdx false @@ -947,7 +949,7 @@ namespace Microsoft.FSharp.Collections first <- false false else - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) override this.OnComplete _ = if first then @@ -965,7 +967,7 @@ namespace Microsoft.FSharp.Collections count <- count + 1 if count = truncateCount then outOfBand.StopFurtherProcessing pipeIdx - next.ProcessNext input + avoidTailCall (next.ProcessNext input) else outOfBand.StopFurtherProcessing pipeIdx false @@ -1053,10 +1055,10 @@ namespace Microsoft.FSharp.Collections let consumer = current.Create pipeline emptyPipeIdx result try executeOn pipeline consumer - (Helpers.upcastICompletionChaining consumer).OnComplete pipeline.HaltedIdx + (upcastICompletionChaining consumer).OnComplete pipeline.HaltedIdx result finally - (Helpers.upcastICompletionChaining consumer).OnDispose () + (upcastICompletionChaining consumer).OnDispose () module Enumerable = type Empty<'T>() = @@ -1081,7 +1083,7 @@ namespace Microsoft.FSharp.Collections seqComponent.OnDispose () interface IEnumerator with - member this.Current : obj = box ((Helpers.upcastEnumerator this)).Current + member this.Current : obj = box ((upcastEnumerator this)).Current member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)" member __.Reset () : unit = noReset () @@ -1100,13 +1102,13 @@ namespace Microsoft.FSharp.Collections abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T> - default this.Append source = Helpers.upcastEnumerable (AppendEnumerable [this; source]) + default this.Append source = upcastEnumerable (AppendEnumerable [this; source]) interface IEnumerable with member this.GetEnumerator () : IEnumerator = - let genericEnumerable = Helpers.upcastEnumerable this + let genericEnumerable = upcastEnumerable this let genericEnumerator = genericEnumerable.GetEnumerator () - Helpers.upcastEnumeratorNonGeneric genericEnumerator + upcastEnumeratorNonGeneric genericEnumerator interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () @@ -1126,7 +1128,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1139,7 +1141,7 @@ namespace Microsoft.FSharp.Collections try source.Dispose () finally - (Helpers.upcastICompletionChaining seqComponent).OnDispose () + (upcastICompletionChaining seqComponent).OnDispose () and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:ISeqFactory<'T,'U>) = inherit EnumerableBase<'U>() @@ -1147,11 +1149,11 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) + upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - Helpers.upcastSeq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) + upcastSeq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.enumerable enumerable) @@ -1183,7 +1185,7 @@ namespace Microsoft.FSharp.Collections | _ -> failwith "library implementation error: all states should have been handled" interface IEnumerator with - member this.Current = box ((Helpers.upcastEnumerator this)).Current + member this.Current = box ((upcastEnumerator this)).Current member __.MoveNext () = state <- SeqProcessNextStates.InProcess moveNext () @@ -1199,14 +1201,14 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - Helpers.upcastEnumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) + upcastEnumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) override this.Append source = - Helpers.upcastEnumerable (AppendEnumerable (source :: sources)) + upcastEnumerable (AppendEnumerable (source :: sources)) interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - Helpers.upcastSeq (Enumerable<'T,'V>(this, next)) + upcastSeq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) @@ -1216,17 +1218,17 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - Helpers.upcastEnumerator (new ConcatEnumerator<_,_> (sources)) + upcastEnumerator (new ConcatEnumerator<_,_> (sources)) interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - Helpers.upcastSeq (Enumerable<'T,'V>(this, next)) + upcastSeq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) let create enumerable current = - Helpers.upcastSeq (Enumerable(enumerable, current)) + upcastSeq (Enumerable(enumerable, current)) module EmptyEnumerable = type Enumerable<'T> () = @@ -1239,11 +1241,11 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () : IEnumerator<'T> = IEnumerator.Empty<'T>() override this.Append source = - Helpers.upcastEnumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) + upcastEnumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - Helpers.upcastSeq (Enumerable.Enumerable<'T,'V>(this, next)) + upcastSeq (Enumerable.Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) @@ -1274,7 +1276,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1288,17 +1290,17 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - Helpers.upcastSeq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) + upcastSeq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:ISeqFactory<'T,'U>) = - Helpers.upcastSeq (Enumerable(delayedArray, current)) + upcastSeq (Enumerable(delayedArray, current)) let create (array:array<'T>) (current:ISeqFactory<'T,'U>) = createDelayed (fun () -> array) current @@ -1325,7 +1327,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1339,17 +1341,17 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - Helpers.upcastSeq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) + upcastSeq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.list alist) let create alist current = - Helpers.upcastSeq (Enumerable(alist, current)) + upcastSeq (Enumerable(alist, current)) module Unfold = type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, result:Result<'U>) = @@ -1378,11 +1380,11 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - Helpers.upcastSeq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) + upcastSeq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.unfold generator state) @@ -1438,7 +1440,7 @@ namespace Microsoft.FSharp.Collections raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1452,11 +1454,11 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Helpers.upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - Helpers.upcastSeq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) + upcastSeq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) member this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = let terminatingIdx = getTerminatingIdx count @@ -1524,10 +1526,10 @@ namespace Microsoft.FSharp.Collections interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - Helpers.upcastSeq (Enumerable<'T,'V>(count, f, next)) + upcastSeq (Enumerable<'T,'V>(count, f, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (Helpers.upcastEnumerable this)) + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (upcastEnumerable this)) open RuntimeHelpers @@ -1536,9 +1538,9 @@ namespace Microsoft.FSharp.Collections checkNonNull "source" source match source with | :? ISeq<'T> as s -> s - | :? array<'T> as a -> Helpers.upcastSeq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) - | :? list<'T> as a -> Helpers.upcastSeq (List.Enumerable(a, IdentityFactory.Instance)) - | _ -> Helpers.upcastSeq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) + | :? array<'T> as a -> upcastSeq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) + | :? list<'T> as a -> upcastSeq (List.Enumerable(a, IdentityFactory.Instance)) + | _ -> upcastSeq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) let inline foreach f (source:ISeq<_>) = source.ForEach f @@ -1551,17 +1553,17 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = - Helpers.upcastSeq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) + upcastSeq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) [] let initInfinite<'T> (f:int->'T) : ISeq<'T> = - Helpers.upcastSeq (new Init.EnumerableDecider<'T>(Nullable (), f)) + upcastSeq (new Init.EnumerableDecider<'T>(Nullable (), f)) [] let init<'T> (count:int) (f:int->'T) : ISeq<'T> = if count < 0 then invalidArgInputMustBeNonNegative "count" count elif count = 0 then empty else - Helpers.upcastSeq (new Init.EnumerableDecider<'T>(Nullable count, f)) + upcastSeq (new Init.EnumerableDecider<'T>(Nullable count, f)) [] let iter f (source:ISeq<'T>) = From 7ac6c93be8b79278f5d6aa44a9671637670a1ed8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 30 Oct 2016 19:08:45 +1100 Subject: [PATCH 205/286] Adding types to try to appease test Adding the types doesn't work. Only appearing in portable build, so pondering if it is a compiler bug? Will need to get onto someone about it I think. --- src/fsharp/FSharp.Core/seq.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 18e837ab9a2..9f19891ccc6 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -554,7 +554,7 @@ namespace Microsoft.FSharp.Collections interface ISeqFactory<'T,'U> with member __.PipeIdx = getPipeIdx pipeIdx - member __.Create _ _ _ = failwith "library implementation error: Create on base factory should not be called" + member __.Create<'V> (_:IOutOfBand) (_:``PipeIdx?``) (_:Consumer<'U,'V>) : Consumer<'T,'V> = failwith "library implementation error: Create on base factory should not be called" and ComposedFactory<'T,'U,'V> private (first:ISeqFactory<'T,'U>, second:ISeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) From 0834bcd15fb5a82ccf4bd343aa680a95c3e00ab9 Mon Sep 17 00:00:00 2001 From: liboz Date: Mon, 31 Oct 2016 19:40:51 -0400 Subject: [PATCH 206/286] seq.windowed --- src/fsharp/FSharp.Core/seq.fs | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 9f19891ccc6..c688866dae6 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -673,6 +673,11 @@ namespace Microsoft.FSharp.Collections inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, getPipeIdx pipeIdx) + + and WindowedFactory<'T> (windowSize:int) = + inherit SeqComponentFactory<'T, 'T[]> () + interface ISeqFactory<'T, 'T[]> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T[],'V>) : Consumer<'T,'V> = upcast Windowed (windowSize, next) and [] SeqComponent<'T,'U> (next:ICompletionChaining) = inherit Consumer<'T,'U>() @@ -972,6 +977,34 @@ namespace Microsoft.FSharp.Collections outOfBand.StopFurtherProcessing pipeIdx false + and Windowed<'T,'V> (windowSize: int, next:Consumer<'T[],'V>) = + inherit SeqComponent<'T,'V>(next) + + let arr = Array.zeroCreateUnchecked windowSize + let r = ref (windowSize - 1) + let i = ref 0 + + let arrWindow innerDerefI j = arr.[(innerDerefI+j) % windowSize] + + override __.ProcessNext (input:'T) : bool = + let derefI = !i + arr.[derefI] <- input + i := (derefI + 1) % windowSize + let derefR = !r + if derefR = 0 then + let innerDerefI = !i + if windowSize < 32 then + let window = Array.init windowSize (arrWindow innerDerefI) + avoidTailCall (next.ProcessNext window) + else + let window = Array.zeroCreateUnchecked windowSize + Array.Copy(arr, innerDerefI, window, 0, windowSize - innerDerefI) + Array.Copy(arr, 0, window, windowSize - innerDerefI, innerDerefI) + avoidTailCall (next.ProcessNext window) + else + r := (derefR - 1) + false + type SeqProcessNextStates = | InProcess = 0 | NotStarted = 1 @@ -2203,7 +2236,7 @@ namespace Microsoft.FSharp.Collections let windowed windowSize (source: seq<_>) = if windowSize <= 0 then invalidArgFmt "windowSize" "{0}\nwindowSize = {1}" [|SR.GetString SR.inputMustBePositive; windowSize|] - source |> seqFactory (Composer.Seq.WindowedFactory (windowSize)) + source |> seqFactory (Composer.WindowedFactory (windowSize)) [] let cache (source : seq<'T>) = From bdf7301ace7219b2481ed6dce1b28a84fc219a8a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 1 Nov 2016 18:25:18 +1100 Subject: [PATCH 207/286] Tightening up Seq.windowed - removed ref vars, as can just us let mutable - renamed variables to more meaningful names - removed modulus because I can --- src/fsharp/FSharp.Core/seq.fs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index c688866dae6..e79b57a4ed8 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -980,30 +980,30 @@ namespace Microsoft.FSharp.Collections and Windowed<'T,'V> (windowSize: int, next:Consumer<'T[],'V>) = inherit SeqComponent<'T,'V>(next) - let arr = Array.zeroCreateUnchecked windowSize - let r = ref (windowSize - 1) - let i = ref 0 + let circularBuffer = Array.zeroCreateUnchecked windowSize + let mutable idx = 0 - let arrWindow innerDerefI j = arr.[(innerDerefI+j) % windowSize] + let mutable priming = windowSize - 1 override __.ProcessNext (input:'T) : bool = - let derefI = !i - arr.[derefI] <- input - i := (derefI + 1) % windowSize - let derefR = !r - if derefR = 0 then - let innerDerefI = !i + circularBuffer.[idx] <- input + + idx <- idx + 1 + if idx = windowSize then + idx <- 0 + + if priming > 0 then + priming <- priming - 1 + false + else if windowSize < 32 then - let window = Array.init windowSize (arrWindow innerDerefI) + let window = Array.init windowSize (fun i -> circularBuffer.[(idx+i) % windowSize]) avoidTailCall (next.ProcessNext window) else let window = Array.zeroCreateUnchecked windowSize - Array.Copy(arr, innerDerefI, window, 0, windowSize - innerDerefI) - Array.Copy(arr, 0, window, windowSize - innerDerefI, innerDerefI) + Array.Copy(circularBuffer, idx, window, 0, windowSize - idx) + Array.Copy(circularBuffer, 0, window, windowSize - idx, idx) avoidTailCall (next.ProcessNext window) - else - r := (derefR - 1) - false type SeqProcessNextStates = | InProcess = 0 From 9cd812d06445074cd63a1ec3df6c44ed91a04567 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 3 Nov 2016 22:50:07 -0400 Subject: [PATCH 208/286] Reduce the diff on seq.fs so that it is easier to review on GitHub --- src/fsharp/FSharp.Core/seq.fs | 1830 +----------------------- src/fsharp/FSharp.Core/seq.fsi | 73 +- src/fsharp/FSharp.Core/seqcomposer.fs | 560 ++++---- src/fsharp/FSharp.Core/seqcomposer.fsi | 260 ++-- 4 files changed, 551 insertions(+), 2172 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index e79b57a4ed8..daafe8076c0 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1,423 +1,5 @@ // 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 Microsoft.FSharp.Core - open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators - open Microsoft.FSharp.Core.Operators - open Microsoft.FSharp.Control - open Microsoft.FSharp.Collections - - module IEnumerator = - - let noReset() = raise (new System.NotSupportedException(SR.GetString(SR.resetNotSupported))) - let notStarted() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationNotStarted))) - let alreadyFinished() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationAlreadyFinished))) - let check started = if not started then notStarted() - let dispose (r : System.IDisposable) = r.Dispose() - - let cast (e : IEnumerator) : IEnumerator<'T> = - { new IEnumerator<'T> with - member x.Current = unbox<'T> e.Current - interface IEnumerator with - member x.Current = unbox<'T> e.Current :> obj - member x.MoveNext() = e.MoveNext() - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = - match e with - | :? System.IDisposable as e -> e.Dispose() - | _ -> () } - - /// A concrete implementation of an enumerator that returns no values - [] - type EmptyEnumerator<'T>() = - let mutable started = false - interface IEnumerator<'T> with - member x.Current = - check started - (alreadyFinished() : 'T) - - interface System.Collections.IEnumerator with - member x.Current = - check started - (alreadyFinished() : obj) - member x.MoveNext() = - if not started then started <- true - false - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = () - - let Empty<'T> () = (new EmptyEnumerator<'T>() :> IEnumerator<'T>) - - let rec tryItem index (e : IEnumerator<'T>) = - if not (e.MoveNext()) then None - elif index = 0 then Some(e.Current) - else tryItem (index-1) e - - let rec nth index (e : IEnumerator<'T>) = - if not (e.MoveNext()) then - let shortBy = index + 1 - invalidArgFmt "index" - "{0}\nseq was short by {1} {2}" - [|SR.GetString SR.notEnoughElements; shortBy; (if shortBy = 1 then "element" else "elements")|] - if index = 0 then e.Current - else nth (index-1) e - - let readAndClear r = - lock r (fun () -> match !r with None -> None | Some _ as res -> r := None; res) - - let generateWhileSome openf compute closef : IEnumerator<'U> = - let started = ref false - let curr = ref None - let state = ref (Some(openf())) - let getCurr() = - check !started - match !curr with None -> alreadyFinished() | Some x -> x - let start() = if not !started then (started := true) - - let dispose() = readAndClear state |> Option.iter closef - let finish() = (try dispose() finally curr := None) - { new IEnumerator<'U> with - member x.Current = getCurr() - interface IEnumerator with - member x.Current = box (getCurr()) - member x.MoveNext() = - start() - match !state with - | None -> false (* we started, then reached the end, then got another MoveNext *) - | Some s -> - match (try compute s with e -> finish(); reraise()) with - | None -> finish(); false - | Some _ as x -> curr := x; true - - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = dispose() } - - [] - type Singleton<'T>(v:'T) = - let mutable started = false - interface IEnumerator<'T> with - member x.Current = v - interface IEnumerator with - member x.Current = box v - member x.MoveNext() = if started then false else (started <- true; true) - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = () - - let Singleton x = (new Singleton<'T>(x) :> IEnumerator<'T>) - - let EnumerateThenFinally f (e : IEnumerator<'T>) = - { new IEnumerator<'T> with - member x.Current = e.Current - interface IEnumerator with - member x.Current = (e :> IEnumerator).Current - member x.MoveNext() = e.MoveNext() - member x.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = - try - e.Dispose() - finally - f() - } - - -namespace Microsoft.FSharp.Core.CompilerServices - - open System - open System.Diagnostics - open Microsoft.FSharp.Core - open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators - open Microsoft.FSharp.Core.Operators - open Microsoft.FSharp.Control - open Microsoft.FSharp.Collections - open Microsoft.FSharp.Primitives.Basics - open System.Collections - open System.Collections.Generic - - 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 inline checkNonNull argName arg = - match box arg with - | null -> nullArg argName - | _ -> () - - let mkSeq f = - { new IEnumerable<'U> with - member x.GetEnumerator() = f() - interface IEnumerable with - member x.GetEnumerator() = (f() :> IEnumerator) } - - [] - type EmptyEnumerable<'T> = - | EmptyEnumerable - interface IEnumerable<'T> with - member x.GetEnumerator() = IEnumerator.Empty<'T>() - interface IEnumerable with - member x.GetEnumerator() = (IEnumerator.Empty<'T>() :> IEnumerator) - - let Generate openf compute closef = - mkSeq (fun () -> IEnumerator.generateWhileSome openf compute closef) - - let GenerateUsing (openf : unit -> ('U :> System.IDisposable)) compute = - Generate openf compute (fun (s:'U) -> s.Dispose()) - - let EnumerateFromFunctions opener moveNext current = - Generate - opener - (fun x -> if moveNext x then Some(current x) else None) - (fun x -> match box(x) with :? System.IDisposable as id -> id.Dispose() | _ -> ()) - - // A family of enumerators that can have additional 'finally' actions added to the enumerator through - // the use of mutation. This is used to 'push' the disposal action for a 'use' into the next enumerator. - // For example, - // seq { use x = ... - // while ... } - // results in the 'while' loop giving an adjustable enumerator. This is then adjusted by adding the disposal action - // from the 'use' into the enumerator. This means that we avoid constructing a two-deep enumerator chain in this - // common case. - type IFinallyEnumerator = - abstract AppendFinallyAction : (unit -> unit) -> unit - - /// A concrete implementation of IEnumerable that adds the given compensation to the "Dispose" chain of any - /// enumerators returned by the enumerable. - [] - type FinallyEnumerable<'T>(compensation: unit -> unit, restf: unit -> seq<'T>) = - interface IEnumerable<'T> with - member x.GetEnumerator() = - try - let ie = restf().GetEnumerator() - match ie with - | :? IFinallyEnumerator as a -> - a.AppendFinallyAction(compensation) - ie - | _ -> - IEnumerator.EnumerateThenFinally compensation ie - with e -> - compensation() - reraise() - interface IEnumerable with - member x.GetEnumerator() = ((x :> IEnumerable<'T>).GetEnumerator() :> IEnumerator) - - /// An optimized object for concatenating a sequence of enumerables - [] - type ConcatEnumerator<'T,'U when 'U :> seq<'T>>(sources: seq<'U>) = - let mutable outerEnum = sources.GetEnumerator() - let mutable currInnerEnum = IEnumerator.Empty() - - let mutable started = false - let mutable finished = false - let mutable compensations = [] - - [] // false = unchecked - val mutable private currElement : 'T - - member x.Finish() = - finished <- true - try - match currInnerEnum with - | null -> () - | _ -> - try - currInnerEnum.Dispose() - finally - currInnerEnum <- null - finally - try - match outerEnum with - | null -> () - | _ -> - try - outerEnum.Dispose() - finally - outerEnum <- null - finally - let rec iter comps = - match comps with - | [] -> () - | h::t -> - try h() finally iter t - try - compensations |> List.rev |> iter - finally - compensations <- [] - - member x.GetCurrent() = - IEnumerator.check started - if finished then IEnumerator.alreadyFinished() else x.currElement - - interface IFinallyEnumerator with - member x.AppendFinallyAction(f) = - compensations <- f :: compensations - - interface IEnumerator<'T> with - member x.Current = x.GetCurrent() - - interface IEnumerator with - member x.Current = box (x.GetCurrent()) - - member x.MoveNext() = - if not started then (started <- true) - if finished then false - else - let rec takeInner () = - // check the inner list - if currInnerEnum.MoveNext() then - x.currElement <- currInnerEnum.Current - true - else - // check the outer list - let rec takeOuter() = - if outerEnum.MoveNext() then - let ie = outerEnum.Current - // Optimization to detect the statically-allocated empty IEnumerables - match box ie with - | :? EmptyEnumerable<'T> -> - // This one is empty, just skip, don't call GetEnumerator, try again - takeOuter() - | _ -> - // OK, this one may not be empty. - // Don't forget to dispose of the enumerator for the inner list now we're done with it - currInnerEnum.Dispose() - currInnerEnum <- ie.GetEnumerator() - takeInner () - else - // We're done - x.Finish() - false - takeOuter() - takeInner () - - member x.Reset() = IEnumerator.noReset() - - interface System.IDisposable with - member x.Dispose() = - if not finished then - x.Finish() - - let EnumerateUsing (resource : 'T :> System.IDisposable) (rest: 'T -> #seq<'U>) = - (FinallyEnumerable((fun () -> match box resource with null -> () | _ -> resource.Dispose()), - (fun () -> rest resource :> seq<_>)) :> seq<_>) - - let mkConcatSeq (sources: seq<'U :> seq<'T>>) = - mkSeq (fun () -> new ConcatEnumerator<_,_>(sources) :> IEnumerator<'T>) - - let EnumerateWhile (g : unit -> bool) (b: seq<'T>) : seq<'T> = - let started = ref false - let curr = ref None - let getCurr() = - IEnumerator.check !started - match !curr with None -> IEnumerator.alreadyFinished() | Some x -> x - let start() = if not !started then (started := true) - - let finish() = (curr := None) - mkConcatSeq - (mkSeq (fun () -> - { new IEnumerator<_> with - member x.Current = getCurr() - interface IEnumerator with - member x.Current = box (getCurr()) - member x.MoveNext() = - start() - let keepGoing = (try g() with e -> finish (); reraise ()) in - if keepGoing then - curr := Some(b); true - else - finish(); false - member x.Reset() = IEnumerator.noReset() - interface System.IDisposable with - member x.Dispose() = () })) - - let EnumerateThenFinally (rest : seq<'T>) (compensation : unit -> unit) = - (FinallyEnumerable(compensation, (fun () -> rest)) :> seq<_>) - - let CreateEvent (add : 'Delegate -> unit) (remove : 'Delegate -> unit) (create : (obj -> 'Args -> unit) -> 'Delegate ) :IEvent<'Delegate,'Args> = - // Note, we implement each interface explicitly: this works around a bug in the CLR - // implementation on CompactFramework 3.7, used on Windows Phone 7 - { new obj() with - member x.ToString() = "" - interface IEvent<'Delegate,'Args> - interface IDelegateEvent<'Delegate> with - member x.AddHandler(h) = add h - member x.RemoveHandler(h) = remove h - interface System.IObservable<'Args> with - member x.Subscribe(r:IObserver<'Args>) = - let h = create (fun _ args -> r.OnNext(args)) - add h - { new System.IDisposable with - member x.Dispose() = remove h } } - - - [] - type GeneratedSequenceBase<'T>() = - let mutable redirectTo : GeneratedSequenceBase<'T> = Unchecked.defaultof<_> - let mutable redirect : bool = false - - abstract GetFreshEnumerator : unit -> IEnumerator<'T> - abstract GenerateNext : next:byref> -> int // 0 = Stop, 1 = Yield, 2 = Goto - abstract Close: unit -> unit - abstract CheckClose: bool - abstract LastGenerated : 'T - - //[] - member x.MoveNextImpl() = - let active = - if redirect then redirectTo - else x - let mutable target = null - match active.GenerateNext(&target) with - | 1 -> - true - | 2 -> - match target.GetEnumerator() with - | :? GeneratedSequenceBase<'T> as g when not active.CheckClose -> - redirectTo <- g - | e -> - redirectTo <- - { new GeneratedSequenceBase<'T>() with - member x.GetFreshEnumerator() = e - member x.GenerateNext(_) = if e.MoveNext() then 1 else 0 - member x.Close() = try e.Dispose() finally active.Close() - member x.CheckClose = true - member x.LastGenerated = e.Current } - redirect <- true - x.MoveNextImpl() - | _ (* 0 *) -> - false - - interface IEnumerable<'T> with - member x.GetEnumerator() = x.GetFreshEnumerator() - interface IEnumerable with - member x.GetEnumerator() = (x.GetFreshEnumerator() :> IEnumerator) - interface IEnumerator<'T> with - member x.Current = if redirect then redirectTo.LastGenerated else x.LastGenerated - member x.Dispose() = if redirect then redirectTo.Close() else x.Close() - interface IEnumerator with - member x.Current = box (if redirect then redirectTo.LastGenerated else x.LastGenerated) - - //[] - member x.MoveNext() = x.MoveNextImpl() - - member x.Reset() = raise <| new System.NotSupportedException() - - namespace Microsoft.FSharp.Collections open System @@ -453,1290 +35,20 @@ namespace Microsoft.FSharp.Collections [] [] module Seq = - module Composer = - open IEnumerator - - module Internal = - type PipeIdx = int - type ``PipeIdx?`` = Nullable - let emptyPipeIdx = Nullable () - let inline getPipeIdx (maybePipeIdx:``PipeIdx?``) = if maybePipeIdx.HasValue then maybePipeIdx.Value else 1 - let inline makePipeIdx (pipeIdx:PipeIdx) = Nullable pipeIdx - - type ICompletionChaining = - abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit - - type IOutOfBand = - abstract StopFurtherProcessing : PipeIdx -> unit - - [] - type Consumer<'T,'U> () = - abstract ProcessNext : input:'T -> bool - - abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit - - default __.OnComplete _ = () - default __.OnDispose () = () - - interface ICompletionChaining with - member this.OnComplete terminatingIdx = - this.OnComplete terminatingIdx - - member this.OnDispose () = - try this.OnDispose () - finally () - - [] - 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 Folder<'T, 'U> = - inherit Consumer<'T,'T> - - val mutable Value : 'U - - new (init) = { - inherit Consumer<'T,'T>() - Value = init - } - - type ISeqFactory<'T,'U> = - abstract PipeIdx : PipeIdx - abstract Create<'V> : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> - - type ISeq<'T> = - inherit IEnumerable<'T> - abstract member Compose<'U> : (ISeqFactory<'T,'U>) -> ISeq<'U> - abstract member ForEach<'consumer when 'consumer :> Consumer<'T,'T>> : f:((unit->unit)->'consumer) -> 'consumer - - open Internal - - module Helpers = - // 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 avoidTailCall boolean = match boolean with true -> true | false -> false - - // 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 upcastSeq (t:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) - let inline upcastFactory (t:#ISeqFactory<'T,'U>) : ISeqFactory<'T,'U> = (# "" t : ISeqFactory<'T,'U> #) - let inline upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) - let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) - let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline upcastICompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) - - open Helpers - - type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = - new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) - - interface ISeqFactory<'T,'U> with - member __.PipeIdx = getPipeIdx pipeIdx - member __.Create<'V> (_:IOutOfBand) (_:``PipeIdx?``) (_:Consumer<'U,'V>) : Consumer<'T,'V> = failwith "library implementation error: Create on base factory should not be called" - - and ComposedFactory<'T,'U,'V> private (first:ISeqFactory<'T,'U>, second:ISeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = - inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) - - interface ISeqFactory<'T,'V> with - member this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = - first.Create outOfBand pipeIdx (second.Create outOfBand (makePipeIdx secondPipeIdx) next) - - static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = - ComposedFactory(first, second, first.PipeIdx+1) |> upcastFactory - - and ChooseFactory<'T,'U> (filter:'T->option<'U>) = - inherit SeqComponentFactory<'T,'U> () - interface ISeqFactory<'T,'U> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) - - and DistinctFactory<'T when 'T: equality> () = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) - - and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) - - and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) - - and FilterFactory<'T> (filter:'T->bool) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = - match next with - | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter - | _ -> upcast Filter (filter, next) - - and IdentityFactory<'T> () = - inherit SeqComponentFactory<'T,'T> () - static let singleton = IdentityFactory<'T>() - interface ISeqFactory<'T,'T> with - member __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next - static member Instance = singleton - - and MapFactory<'T,'U> (map:'T->'U) = - inherit SeqComponentFactory<'T,'U> () - interface ISeqFactory<'T,'U> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = - match next with - | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map - | _ -> upcast Map<_,_,_> (map, next) - - and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = - inherit SeqComponentFactory<'First,'U> () - interface ISeqFactory<'First,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, outOfBand, next, getPipeIdx pipeIdx) - - and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = - inherit SeqComponentFactory<'Second,'U> () - interface ISeqFactory<'Second,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, outOfBand, next, getPipeIdx pipeIdx) - - and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = - inherit SeqComponentFactory<'First,'U> () - interface ISeqFactory<'First,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, outOfBand, next, getPipeIdx pipeIdx) - - and MapiFactory<'T,'U> (mapi:int->'T->'U) = - inherit SeqComponentFactory<'T,'U> () - interface ISeqFactory<'T,'U> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) - - and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = - inherit SeqComponentFactory<'First,'U> () - interface ISeqFactory<'First,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, outOfBand, next, getPipeIdx pipeIdx) - - and PairwiseFactory<'T> () = - inherit SeqComponentFactory<'T,'T*'T> () - interface ISeqFactory<'T,'T*'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) - - and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = - inherit SeqComponentFactory<'T,'State> () - interface ISeqFactory<'T,'State> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) - - and SkipFactory<'T> (count:int) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) - - and SkipWhileFactory<'T> (predicate:'T->bool) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) - - and TakeWhileFactory<'T> (predicate:'T->bool) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, outOfBand, next, getPipeIdx pipeIdx) - - and TakeFactory<'T> (count:int) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, getPipeIdx pipeIdx) - - and TailFactory<'T> () = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) - - and TruncateFactory<'T> (count:int) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, getPipeIdx pipeIdx) - - and WindowedFactory<'T> (windowSize:int) = - inherit SeqComponentFactory<'T, 'T[]> () - interface ISeqFactory<'T, 'T[]> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T[],'V>) : Consumer<'T,'V> = upcast Windowed (windowSize, next) - - and [] SeqComponent<'T,'U> (next:ICompletionChaining) = - inherit Consumer<'T,'U>() - - // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip - // and it can only do it at the start of a sequence - abstract Skipping : unit -> bool - - abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> - abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> - - interface ICompletionChaining with - member this.OnComplete terminatingIdx = - this.OnComplete terminatingIdx - next.OnComplete terminatingIdx - member this.OnDispose () = - try this.OnDispose () - finally next.OnDispose () - - default __.Skipping () = false - - default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) - default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) - - and Choose<'T,'U,'V> (choose:'T->option<'U>, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - override __.ProcessNext (input:'T) : bool = - match choose input with - | Some value -> avoidTailCall (next.ProcessNext value) - | None -> false - - and Distinct<'T,'V when 'T: equality> (next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) - - override __.ProcessNext (input:'T) : bool = - if hashSet.Add input then - avoidTailCall (next.ProcessNext input) - else - false - - and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) - - override __.ProcessNext (input:'T) : bool = - if hashSet.Add(keyFunction input) then - avoidTailCall (next.ProcessNext input) - else - false - - and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) - - override __.ProcessNext (input:'T) : bool = - if cached.Value.Add input then - avoidTailCall (next.ProcessNext input) - else - false - - and Filter<'T,'V> (filter:'T->bool, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) - - override __.ProcessNext (input:'T) : bool = - if filter input then - avoidTailCall (next.ProcessNext input) - else - false - - and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - override __.ProcessNext (input:'T) : bool = - if filter input then - avoidTailCall (next.ProcessNext (map input)) - else - false - - and Map<'T,'U,'V> (map:'T->'U, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) - - override __.ProcessNext (input:'T) : bool = - avoidTailCall (next.ProcessNext (map input)) - - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(next) - - let input2 = enumerable2.GetEnumerator () - let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map - - override __.ProcessNext (input:'First) : bool = - if input2.MoveNext () then - avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - override __.OnDispose () = - input2.Dispose () - - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'Second,'V>(next) - - let input1 = enumerable1.GetEnumerator () - let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map - - override __.ProcessNext (input:'Second) : bool = - if input1.MoveNext () then - avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - override __.OnDispose () = - input1.Dispose () - - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(next) - - let input2 = enumerable2.GetEnumerator () - let input3 = enumerable3.GetEnumerator () - let map' = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt map - - override __.ProcessNext (input:'First) : bool = - if input2.MoveNext () && input3.MoveNext () then - avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - override __.OnDispose () = - try input2.Dispose () - finally input3.Dispose () - - and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - override __.ProcessNext (input:'T) : bool = - let u = map input - if filter u then - avoidTailCall (next.ProcessNext u) - else - false - - and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - let mutable idx = 0 - let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi - - override __.ProcessNext (input:'T) : bool = - idx <- idx + 1 - avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) - - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(next) - - let mutable idx = 0 - let input2 = enumerable2.GetEnumerator () - let mapi2' = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt map - - override __.ProcessNext (input:'First) : bool = - if input2.MoveNext () then - idx <- idx + 1 - avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - override __.OnDispose () = - input2.Dispose () - - and Pairwise<'T,'V> (next:Consumer<'T*'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let mutable isFirst = true - let mutable lastValue = Unchecked.defaultof<'T> - - override __.ProcessNext (input:'T) : bool = - if isFirst then - lastValue <- input - isFirst <- false - false - else - let currentPair = lastValue, input - lastValue <- input - avoidTailCall (next.ProcessNext currentPair) - - and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:Consumer<'State,'V>) = - inherit SeqComponent<'T,'V>(next) - - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - let mutable foldResult = initialState - - override __.ProcessNext (input:'T) : bool = - foldResult <- f.Invoke(foldResult, input) - avoidTailCall (next.ProcessNext foldResult) - - and Skip<'T,'V> (skipCount:int, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let mutable count = 0 - - override __.Skipping () = - if count < skipCount then - count <- count + 1 - true - else - false - - override __.ProcessNext (input:'T) : bool = - if count < skipCount then - count <- count + 1 - false - else - avoidTailCall (next.ProcessNext input) - - override __.OnComplete _ = - if count < skipCount then - let x = skipCount - count - invalidOpFmt "tried to skip {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - - and SkipWhile<'T,'V> (predicate:'T->bool, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let mutable skip = true - - override __.ProcessNext (input:'T) : bool = - if skip then - skip <- predicate input - if skip then - false - else - avoidTailCall (next.ProcessNext input) - else - avoidTailCall (next.ProcessNext input) - - and Take<'T,'V> (takeCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipelineIdx:int) = - inherit Truncate<'T, 'V>(takeCount, outOfBand, next, pipelineIdx) - - override this.OnComplete terminatingIdx = - if terminatingIdx < pipelineIdx && this.Count < takeCount then - let x = takeCount - this.Count - invalidOpFmt "tried to take {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - - and TakeWhile<'T,'V> (predicate:'T->bool, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = - inherit SeqComponent<'T,'V>(next) - - override __.ProcessNext (input:'T) : bool = - if predicate input then - avoidTailCall (next.ProcessNext input) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - and Tail<'T, 'V> (next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - let mutable first = true - - override __.ProcessNext (input:'T) : bool = - if first then - first <- false - false - else - avoidTailCall (next.ProcessNext input) - - override this.OnComplete _ = - if first then - invalidArg "source" (SR.GetString(SR.notEnoughElements)) - - and Truncate<'T,'V> (truncateCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = - inherit SeqComponent<'T,'V>(next) - - let mutable count = 0 - - member __.Count = count - - override __.ProcessNext (input:'T) : bool = - if count < truncateCount then - count <- count + 1 - if count = truncateCount then - outOfBand.StopFurtherProcessing pipeIdx - avoidTailCall (next.ProcessNext input) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - and Windowed<'T,'V> (windowSize: int, next:Consumer<'T[],'V>) = - inherit SeqComponent<'T,'V>(next) - - let circularBuffer = Array.zeroCreateUnchecked windowSize - let mutable idx = 0 - - let mutable priming = windowSize - 1 - - override __.ProcessNext (input:'T) : bool = - circularBuffer.[idx] <- input - - idx <- idx + 1 - if idx = windowSize then - idx <- 0 - - if priming > 0 then - priming <- priming - 1 - false - else - if windowSize < 32 then - let window = Array.init windowSize (fun i -> circularBuffer.[(idx+i) % windowSize]) - avoidTailCall (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) - avoidTailCall (next.ProcessNext window) - - type SeqProcessNextStates = - | InProcess = 0 - | NotStarted = 1 - | Finished = 2 - - type Result<'T>() = - let mutable haltedIdx = 0 - - member val Current = Unchecked.defaultof<'T> with get, set - member val SeqState = SeqProcessNextStates.NotStarted with get, set - member __.HaltedIdx = haltedIdx - - interface IOutOfBand with - member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx - - // SetResult<> is used at the end of the chain of SeqComponents to assign the final value - type SetResult<'T> (result:Result<'T>) = - inherit Consumer<'T,'T>() - - override __.ProcessNext (input:'T) : bool = - result.Current <- input - true - - type OutOfBand() = - let mutable haltedIdx = 0 - interface IOutOfBand with member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx - member __.HaltedIdx = haltedIdx - - module ForEach = - let enumerable (enumerable:IEnumerable<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = - use enumerator = enumerable.GetEnumerator () - while (outOfBand.HaltedIdx = 0) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - - let array (array:array<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = - let mutable idx = 0 - while (outOfBand.HaltedIdx = 0) && (idx < array.Length) do - consumer.ProcessNext array.[idx] |> ignore - idx <- idx + 1 - - let list (alist:list<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = - let rec iterate lst = - match outOfBand.HaltedIdx, lst with - | 0, hd :: tl -> - consumer.ProcessNext hd |> ignore - iterate tl - | _ -> () - iterate alist - - let unfold (generator:'S->option<'T*'S>) state (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = - let rec iterate current = - match outOfBand.HaltedIdx, generator current with - | 0, Some (item, next) -> - consumer.ProcessNext item |> ignore - iterate next - | _ -> () - - iterate state - - let makeIsSkipping (consumer:Consumer<'T,'U>) = - match consumer with - | :? SeqComponent<'T,'U> as c -> c.Skipping - | _ -> fun () -> false - - let init f (terminatingIdx:int) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = - let mutable idx = -1 - let isSkipping = makeIsSkipping consumer - let mutable maybeSkipping = true - while (outOfBand.HaltedIdx = 0) && (idx < terminatingIdx) do - if maybeSkipping then - maybeSkipping <- isSkipping () - - if (not maybeSkipping) then - consumer.ProcessNext (f (idx+1)) |> ignore - - idx <- idx + 1 - - let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:ISeqFactory<'T,'U>) executeOn = - let pipeline = OutOfBand() - let result = f (fun () -> (pipeline:>IOutOfBand).StopFurtherProcessing (current.PipeIdx+1)) - let consumer = current.Create pipeline emptyPipeIdx result - try - executeOn pipeline consumer - (upcastICompletionChaining consumer).OnComplete pipeline.HaltedIdx - result - finally - (upcastICompletionChaining consumer).OnDispose () - - 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>, seqComponent:ICompletionChaining) = - interface IDisposable with - member __.Dispose() : unit = - seqComponent.OnDispose () - - interface IEnumerator with - member this.Current : obj = box ((upcastEnumerator 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.Current - 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<'T> : (seq<'T>) -> IEnumerable<'T> - - default this.Append source = upcastEnumerable (AppendEnumerable [this; source]) - - interface IEnumerable with - member this.GetEnumerator () : IEnumerator = - let genericEnumerable = upcastEnumerable this - let genericEnumerator = genericEnumerable.GetEnumerator () - upcastEnumeratorNonGeneric genericEnumerator - - interface IEnumerable<'T> with - member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () - - interface ISeq<'T> with - member __.Compose _ = derivedClassShouldImplement () - member __.ForEach _ = derivedClassShouldImplement () - - and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, seqComponent) - - let rec moveNext () = - if (result.HaltedIdx = 0) && source.MoveNext () then - if seqComponent.ProcessNext source.Current then - true - else - moveNext () - else - result.SeqState <- SeqProcessNextStates.Finished - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () - - interface IDisposable with - member __.Dispose() = - try - source.Dispose () - finally - (upcastICompletionChaining seqComponent).OnDispose () - - and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:ISeqFactory<'T,'U>) = - inherit EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) - - interface ISeq<'U> with - member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.enumerable enumerable) - - 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 ((upcastEnumerator 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> = - upcastEnumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) - - override this.Append source = - upcastEnumerable (AppendEnumerable (source :: sources)) - - interface ISeq<'T> with - member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable<'T,'V>(this, next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.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> = - upcastEnumerator (new ConcatEnumerator<_,_> (sources)) - - interface ISeq<'T> with - member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable<'T,'V>(this, next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) - - let create enumerable current = - upcastSeq (Enumerable(enumerable, current)) - - 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 = - upcastEnumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) - - interface ISeq<'T> with - member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable.Enumerable<'T,'V>(this, next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) - - - - module Array = - type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) - - let mutable idx = 0 - let mutable array = Unchecked.defaultof<_> - - let mutable initMoveNext = Unchecked.defaultof<_> - do - initMoveNext <- - fun () -> - result.SeqState <- SeqProcessNextStates.InProcess - array <- delayedArray () - initMoveNext <- ignore - - let rec moveNext () = - if (result.HaltedIdx = 0) && idx < array.Length then - idx <- idx+1 - if seqComponent.ProcessNext array.[idx-1] then - true - else - moveNext () - else - result.SeqState <- SeqProcessNextStates.Finished - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - initMoveNext () - moveNext () - - type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:ISeqFactory<'T,'U>) = - inherit Enumerable.EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - - interface ISeq<'U> with - member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.array (delayedArray ())) - - let createDelayed (delayedArray:unit->array<'T>) (current:ISeqFactory<'T,'U>) = - upcastSeq (Enumerable(delayedArray, current)) - - let create (array:array<'T>) (current:ISeqFactory<'T,'U>) = - createDelayed (fun () -> array) current - - let createDelayedId (delayedArray:unit -> array<'T>) = - createDelayed delayedArray IdentityFactory.Instance - - let createId (array:array<'T>) = - create array IdentityFactory.Instance - - module List = - type Enumerator<'T,'U>(alist:list<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) - - let mutable list = alist - - let rec moveNext current = - match result.HaltedIdx, current with - | 0, head::tail -> - if seqComponent.ProcessNext head then - list <- tail - true - else - moveNext tail - | _ -> - result.SeqState <- SeqProcessNextStates.Finished - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext list - - type Enumerable<'T,'U>(alist:list<'T>, current:ISeqFactory<'T,'U>) = - inherit Enumerable.EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - - interface ISeq<'U> with - member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.list alist) - - let create alist current = - upcastSeq (Enumerable(alist, current)) - - module Unfold = - type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) - - let mutable current = state - - let rec moveNext () = - match result.HaltedIdx, generator current with - | 0, Some (item, nextState) -> - current <- nextState - if seqComponent.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, current:ISeqFactory<'T,'U>) = - inherit Enumerable.EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - - interface ISeq<'U> with - member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.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, seqComponent:Consumer<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) - - let isSkipping = - ForEach.makeIsSkipping seqComponent - - 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 seqComponent.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 - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext () - - type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:ISeqFactory<'T,'U>) = - inherit Enumerable.EnumerableBase<'U>() - - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) - - interface ISeq<'U> with - member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) - - member this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = - let terminatingIdx = getTerminatingIdx count - ForEach.execute createResult current (ForEach.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 self.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = () } - - type EnumerableDecider<'T>(count:Nullable, f:int->'T) = - 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.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable<'T,'V>(count, f, next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (upcastEnumerable this)) - - open RuntimeHelpers - - [] - let toComposer (source:seq<'T>) : ISeq<'T> = - checkNonNull "source" source - match source with - | :? ISeq<'T> as s -> s - | :? array<'T> as a -> upcastSeq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) - | :? list<'T> as a -> upcastSeq (List.Enumerable(a, IdentityFactory.Instance)) - | _ -> upcastSeq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) - - let inline foreach f (source:ISeq<_>) = - source.ForEach f - - let inline compose factory (source:ISeq<'T>) = - source.Compose factory - - [] - let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance - - [] - let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = - upcastSeq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) - - [] - let initInfinite<'T> (f:int->'T) : ISeq<'T> = - upcastSeq (new Init.EnumerableDecider<'T>(Nullable (), f)) - - [] - let init<'T> (count:int) (f:int->'T) : ISeq<'T> = - if count < 0 then invalidArgInputMustBeNonNegative "count" count - elif count = 0 then empty else - upcastSeq (new Init.EnumerableDecider<'T>(Nullable count, f)) - - [] - let iter f (source:ISeq<'T>) = - source - |> foreach (fun _ -> - { new Consumer<'T,'T> () with - override this.ProcessNext value = - f value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> ignore - - [] - let tryItem i (source:ISeq<'T>) = - if i < 0 then None else - source - |> foreach (fun halt -> - { new Folder<'T, Values>> (Values<_,_> (0, None)) with - override this.ProcessNext value = - if this.Value._1 = i then - this.Value._2 <- Some value - halt () - else - this.Value._1 <- this.Value._1 + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun item -> item.Value._2 - - [] - let iteri f (source:ISeq<'T>) = - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f - - source - |> foreach (fun _ -> - { new Folder<'T, int> (0) with - override this.ProcessNext value = - f.Invoke(this.Value, value) - this.Value <- this.Value + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> ignore - - [] - let exists f (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, bool> (false) with - override this.ProcessNext value = - if f value then - this.Value <- true - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun exists -> exists.Value - - [] - let inline contains element (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, bool> (false) with - override this.ProcessNext value = - if element = value then - this.Value <- true - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun contains -> contains.Value - - [] - let forall f (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, bool> (true) with - override this.ProcessNext value = - if not (f value) then - this.Value <- false - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun forall -> forall.Value - - [] - let filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source - |> compose (FilterFactory f) - - [] - let map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = - source - |> compose (MapFactory f) - - [] - let mapi f source = - source - |> compose (MapiFactory f) - - [] - let choose f source = - source - |> compose (ChooseFactory f) - - [] - let indexed source = - source - |> compose (MapiFactory (fun i x -> i,x)) - - [] - let tryPick f (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, Option<'U>> (None) with - override this.ProcessNext value = - match f value with - | (Some _) as some -> - this.Value <- some - halt () - | None -> () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun pick -> pick.Value - - [] - let tryFind f (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, Option<'T>> (None) with - override this.ProcessNext value = - if f value then - this.Value <- Some value - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun find -> find.Value - - #if FX_NO_ICLONEABLE open Microsoft.FSharp.Core.ICloneableExtensions #else #endif + let mkDelayedSeq (f: unit -> IEnumerable<'T>) = mkSeq (fun () -> f().GetEnumerator()) let inline indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) [] - let toComposer (source:seq<'T>): Composer.Internal.ISeq<'T> = - Composer.toComposer source + let toComposer (source:seq<'T>): Composer.Core.ISeq<'T> = + Composer.Seq.toComposer source let inline foreach f (source:seq<_>) = - Composer.foreach f (toComposer source) + Composer.Seq.foreach f (toComposer source) let inline foreach f (source:seq<_>) = Composer.Seq.foreach f (toComposer source) @@ -1754,7 +66,7 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : seq<'T> = - Composer.unfold generator state + Composer.Seq.unfold generator state |> Composer.Helpers.upcastEnumerable [] @@ -1762,17 +74,17 @@ namespace Microsoft.FSharp.Collections [] let initInfinite<'T> (f:int->'T) : IEnumerable<'T> = - Composer.initInfinite f + Composer.Seq.initInfinite f |> Composer.Helpers.upcastEnumerable [] let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> = - Composer.init count f + Composer.Seq.init count f |> Composer.Helpers.upcastEnumerable [] let iter f (source : seq<'T>) = - Composer.iter f (toComposer source) + Composer.Seq.iter f (toComposer source) [] let tryHead (source : seq<_>) = @@ -1789,7 +101,7 @@ namespace Microsoft.FSharp.Collections if i < 0 then invalidArgInputMustBeNonNegative "index" i else source |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values<_,_,_> (0, false, Unchecked.defaultof<'T>)) with + { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values<_,_,_> (0, false, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 = i then this.Value._2 <- true @@ -1809,26 +121,26 @@ namespace Microsoft.FSharp.Collections [] let tryItem i (source:seq<'T>) = - Composer.tryItem i (toComposer source) + Composer.Seq.tryItem i (toComposer source) [] let nth i (source : seq<'T>) = item i source [] let iteri f (source:seq<'T>) = - Composer.iteri f (toComposer source) + Composer.Seq.iteri f (toComposer source) [] let exists f (source:seq<'T>) = - Composer.exists f (toComposer source) + Composer.Seq.exists f (toComposer source) [] let inline contains element (source:seq<'T>) = - Composer.contains element (toComposer source) + Composer.Seq.contains element (toComposer source) [] let forall f (source:seq<'T>) = - Composer.forall f (toComposer source) + Composer.Seq.forall f (toComposer source) [] let iter2 f (source1 : seq<_>) (source2 : seq<_>) = @@ -1839,7 +151,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<_,_> () with + { new Composer.Core.Folder<_,_> () with override this.ProcessNext value = if (e2.MoveNext()) then f.Invoke(value, e2.Current) @@ -1857,7 +169,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<_,int> (0) with + { new Composer.Core.Folder<_,int> (0) with override this.ProcessNext value = if (e2.MoveNext()) then f.Invoke(this.Value, value, e2.Current) @@ -1877,14 +189,14 @@ namespace Microsoft.FSharp.Collections let private seqFactory createSeqComponent (source:seq<'T>) = checkNonNull "source" source match source with - | :? Composer.Internal.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose createSeqComponent) - | :? array<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.Array.create a createSeqComponent) - | :? list<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.List.create a createSeqComponent) - | _ -> Composer.Helpers.upcastEnumerable (Composer.Enumerable.create source createSeqComponent) + | :? Composer.Core.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose createSeqComponent) + | :? array<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.Seq.Array.create a createSeqComponent) + | :? list<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.Seq.List.create a createSeqComponent) + | _ -> Composer.Helpers.upcastEnumerable (Composer.Seq.Enumerable.create source createSeqComponent) [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = - Composer.filter f (toComposer source) + Composer.Seq.filter f (toComposer source) |> Composer.Helpers.upcastEnumerable [] @@ -1892,40 +204,40 @@ namespace Microsoft.FSharp.Collections [] let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> = - Composer.map f (toComposer source) + Composer.Seq.map f (toComposer source) |> Composer.Helpers.upcastEnumerable [] let mapi f source = - Composer.mapi f (toComposer source) + Composer.Seq.mapi f (toComposer source) |> Composer.Helpers.upcastEnumerable [] let mapi2 f source1 source2 = checkNonNull "source2" source2 - source1 |> seqFactory (Composer.Mapi2Factory (f, source2)) + source1 |> seqFactory (Composer.Seq.Mapi2Factory (f, source2)) [] let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = checkNonNull "source1" source1 match source1 with - | :? Composer.Internal.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose (Composer.Map2FirstFactory (f, source2))) - | _ -> source2 |> seqFactory (Composer.Map2SecondFactory (f, source1)) + | :? Composer.Core.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose (Composer.Seq.Map2FirstFactory (f, source2))) + | _ -> source2 |> seqFactory (Composer.Seq.Map2SecondFactory (f, source1)) [] let map3 f source1 source2 source3 = checkNonNull "source2" source2 checkNonNull "source3" source3 - source1 |> seqFactory (Composer.Map3Factory (f, source2, source3)) + source1 |> seqFactory (Composer.Seq.Map3Factory (f, source2, source3)) [] let choose f source = - Composer.choose f (toComposer source) + Composer.Seq.choose f (toComposer source) |> Composer.Helpers.upcastEnumerable [] let indexed source = - Composer.indexed (toComposer source) + Composer.Seq.indexed (toComposer source) |> Composer.Helpers.upcastEnumerable [] @@ -1943,7 +255,7 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source : seq<'T>) = - Composer.tryPick f (toComposer source) + Composer.Seq.tryPick f (toComposer source) [] let pick f source = @@ -1953,7 +265,7 @@ namespace Microsoft.FSharp.Collections [] let tryFind f (source : seq<'T>) = - Composer.tryFind f (toComposer source) + Composer.Seq.tryFind f (toComposer source) [] let find f source = @@ -1966,7 +278,7 @@ namespace Microsoft.FSharp.Collections if count < 0 then invalidArgInputMustBeNonNegative "count" count (* Note: don't create or dispose any IEnumerable if n = 0 *) if count = 0 then empty else - source |> seqFactory (Composer.TakeFactory count) + source |> seqFactory (Composer.Seq.TakeFactory count) [] let isEmpty (source : seq<'T>) = @@ -1982,7 +294,7 @@ namespace Microsoft.FSharp.Collections [] let concat (sources:seq<#seq<'T>>) : seq<'T> = checkNonNull "sources" sources - upcast Composer.Enumerable.ConcatEnumerable sources + upcast Composer.Seq.Enumerable.ConcatEnumerable sources [] let length (source : seq<'T>) = @@ -2004,7 +316,7 @@ namespace Microsoft.FSharp.Collections source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T,'State> (x) with + { new Composer.Core.Folder<'T,'State> (x) with override this.ProcessNext value = this.Value <- f.Invoke (this.Value, value) Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) @@ -2027,7 +339,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<_,'State> (state) with + { new Composer.Core.Folder<_,'State> (state) with override this.ProcessNext value = if (e2.MoveNext()) then this.Value <- f.Invoke(this.Value, value, e2.Current) @@ -2042,7 +354,7 @@ namespace Microsoft.FSharp.Collections source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values<_,_>(true, Unchecked.defaultof<'T>)) with + { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2072,8 +384,8 @@ namespace Microsoft.FSharp.Collections checkNonNull "source1" source1 checkNonNull "source2" source2 match source1 with - | :? Composer.Enumerable.EnumerableBase<'T> as s -> s.Append source2 - | _ -> Composer.Helpers.upcastEnumerable (new Composer.Enumerable.AppendEnumerable<_>([source2; source1])) + | :? Composer.Seq.Enumerable.EnumerableBase<'T> as s -> s.Append source2 + | _ -> Composer.Helpers.upcastEnumerable (new Composer.Seq.Enumerable.AppendEnumerable<_>([source2; source1])) [] @@ -2088,7 +400,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<'T,int> (0) with + { new Composer.Core.Folder<'T,int> (0) with override this.ProcessNext value = if not (e2.MoveNext()) then this.Value <- 1 @@ -2117,7 +429,7 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source : 'T array) = checkNonNull "source" source - Composer.Helpers.upcastEnumerable (Composer.Array.createId source) + Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createId source) [] let toArray (source : seq<'T>) = @@ -2171,17 +483,17 @@ namespace Microsoft.FSharp.Collections [] let truncate n (source: seq<'T>) = if n <= 0 then empty else - source |> seqFactory (Composer.TruncateFactory n) + source |> seqFactory (Composer.Seq.TruncateFactory n) [] let pairwise<'T> (source:seq<'T>) : seq<'T*'T> = - source |> seqFactory (Composer.PairwiseFactory ()) + source |> seqFactory (Composer.Seq.PairwiseFactory ()) [] let scan<'T,'State> f (z:'State) (source : seq<'T>): seq<'State> = let first = [|z|] :> IEnumerable<'State> - let rest = source |> seqFactory (Composer.ScanFactory (f, z)) - upcast Composer.Enumerable.ConcatEnumerable [|first; rest;|] + let rest = source |> seqFactory (Composer.Seq.ScanFactory (f, z)) + upcast Composer.Seq.Enumerable.ConcatEnumerable [|first; rest;|] [] let tryFindBack f (source : seq<'T>) = @@ -2205,7 +517,7 @@ namespace Microsoft.FSharp.Collections let tryFindIndex p (source:seq<_>) = source |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Composer.Internal.Values, int>> (Composer.Internal.Values<_,_>(None, 0)) with + { new Composer.Core.Folder<'T, Composer.Core.Values, int>> (Composer.Core.Values<_,_>(None, 0)) with override this.ProcessNext value = if p value then this.Value._1 <- Some(this.Value._2) @@ -2236,7 +548,7 @@ namespace Microsoft.FSharp.Collections let windowed windowSize (source: seq<_>) = if windowSize <= 0 then invalidArgFmt "windowSize" "{0}\nwindowSize = {1}" [|SR.GetString SR.inputMustBePositive; windowSize|] - source |> seqFactory (Composer.WindowedFactory (windowSize)) + source |> seqFactory (Composer.Seq.WindowedFactory (windowSize)) [] let cache (source : seq<'T>) = @@ -2354,11 +666,11 @@ namespace Microsoft.FSharp.Collections [] let distinct source = - source |> seqFactory (Composer.DistinctFactory ()) + source |> seqFactory (Composer.Seq.DistinctFactory ()) [] let distinctBy keyf source = - source |> seqFactory (Composer.DistinctByFactory keyf) + source |> seqFactory (Composer.Seq.DistinctByFactory keyf) [] let sortBy keyf source = @@ -2367,7 +679,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceBy keyf array array - Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedSort) + Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedSort) [] let sort source = @@ -2376,7 +688,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlace array array - Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedSort) + Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedSort) [] let sortWith f source = @@ -2385,7 +697,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceWith f array array - Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedSort) + Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedSort) [] let inline sortByDescending keyf source = @@ -2436,7 +748,7 @@ namespace Microsoft.FSharp.Collections let inline sum (source:seq<'a>) : 'a = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'a,'a> (LanguagePrimitives.GenericZero) with + { new Composer.Core.Folder<'a,'a> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value value Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) @@ -2446,7 +758,7 @@ namespace Microsoft.FSharp.Collections let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + { new Composer.Core.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = this.Value <- Checked.(+) this.Value (f value) Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) @@ -2456,7 +768,7 @@ namespace Microsoft.FSharp.Collections let inline average (source: seq< ^a>) : ^a = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'a, Composer.Internal.Values<'a, int>> (Composer.Internal.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + { new Composer.Core.Folder<'a, Composer.Core.Values<'a, int>> (Composer.Core.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 value this.Value._2 <- this.Value._2 + 1 @@ -2471,7 +783,7 @@ namespace Microsoft.FSharp.Collections let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T,Composer.Internal.Values<'U, int>> (Composer.Internal.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + { new Composer.Core.Folder<'T,Composer.Core.Values<'U, int>> (Composer.Core.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 (f value) this.Value._2 <- this.Value._2 + 1 @@ -2491,7 +803,7 @@ namespace Microsoft.FSharp.Collections let inline min (source: seq<_>) = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_>(true, Unchecked.defaultof<'T>)) with + { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2510,7 +822,7 @@ namespace Microsoft.FSharp.Collections let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with override this.ProcessNext value = match this.Value._1, f value with | true, valueU -> @@ -2549,7 +861,7 @@ namespace Microsoft.FSharp.Collections let inline max (source: seq<_>) = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_>(true, Unchecked.defaultof<'T>)) with + { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2568,7 +880,7 @@ namespace Microsoft.FSharp.Collections let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T,Composer.Internal.Values> (Composer.Internal.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with override this.ProcessNext value = match this.Value._1, f value with | true, valueU -> @@ -2606,15 +918,15 @@ namespace Microsoft.FSharp.Collections *) [] let takeWhile p (source: seq<_>) = - source |> seqFactory (Composer.TakeWhileFactory p) + source |> seqFactory (Composer.Seq.TakeWhileFactory p) [] let skip count (source: seq<_>) = - source |> seqFactory (Composer.SkipFactory count) + source |> seqFactory (Composer.Seq.SkipFactory count) [] let skipWhile p (source: seq<_>) = - source |> seqFactory (Composer.SkipWhileFactory p) + source |> seqFactory (Composer.Seq.SkipWhileFactory p) [] let forall2 p (source1: seq<_>) (source2: seq<_>) = @@ -2625,7 +937,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<_,bool> (true) with + { new Composer.Core.Folder<_,bool> (true) with override this.ProcessNext value = if (e2.MoveNext()) then if not (p.Invoke(value, e2.Current)) then @@ -2645,7 +957,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Internal.Folder<_,bool> (false) with + { new Composer.Core.Folder<_,bool> (false) with override this.ProcessNext value = if (e2.MoveNext()) then if p.Invoke(value, e2.Current) then @@ -2660,7 +972,7 @@ namespace Microsoft.FSharp.Collections let tryHead (source : seq<_>) = source |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Option<'T>> (None) with + { new Composer.Core.Folder<'T, Option<'T>> (None) with override this.ProcessNext value = this.Value <- Some value halt () @@ -2688,13 +1000,13 @@ namespace Microsoft.FSharp.Collections [] let tail (source: seq<'T>) = - source |> seqFactory (Composer.TailFactory ()) + source |> seqFactory (Composer.Seq.TailFactory ()) [] let tryLast (source : seq<_>) = source |> foreach (fun _ -> - { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values(true, Unchecked.defaultof<'T>)) with + { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2716,7 +1028,7 @@ namespace Microsoft.FSharp.Collections let exactlyOne (source : seq<_>) = source |> foreach (fun halt -> - { new Composer.Internal.Folder<'T, Composer.Internal.Values> (Composer.Internal.Values(true, Unchecked.defaultof<'T>, false)) with + { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values(true, Unchecked.defaultof<'T>, false)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -2747,7 +1059,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.Reverse array array - Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedReverse) + Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedReverse) [] let permute f (source:seq<_>) = @@ -2756,7 +1068,7 @@ namespace Microsoft.FSharp.Collections source |> toArray |> Array.permute f - Composer.Helpers.upcastEnumerable (Composer.Array.createDelayedId delayedPermute) + Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedPermute) [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = @@ -2774,7 +1086,7 @@ namespace Microsoft.FSharp.Collections [] let except (itemsToExclude: seq<'T>) (source: seq<'T>) = checkNonNull "itemsToExclude" itemsToExclude - source |> seqFactory (Composer.ExceptFactory itemsToExclude) + source |> seqFactory (Composer.Seq.ExceptFactory itemsToExclude) [] let chunkBySize chunkSize (source : seq<_>) = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index a84a71fc037..f06c676e4de 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -13,75 +13,6 @@ namespace Microsoft.FSharp.Collections [] [] module Seq = - module Composer = - module Internal = - /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the - /// source of the chain. - type PipeIdx = int - type ``PipeIdx?`` = Nullable - - /// ICompletionChaining is used to correctly handle cleaning up of the pipeline. A - /// base implementation is provided in Consumer, and should not be overwritten. Consumer - /// provides it's own OnComplete and OnDispose function which should be used to handle - /// a particular consumers cleanup. - type ICompletionChaining = - /// OnComplete is used to determine if the object has been processed correctly, - /// and possibly throw exceptions to denote incorrect application (i.e. such as a Take - /// operation which didn't have a source at least as large as was required). It is - /// not called in the case of an exception being thrown whilst the stream is still - /// being processed. - abstract OnComplete : PipeIdx -> unit - /// OnDispose is used to cleanup the stream. It is always called at the last operation - /// after the enumeration has completed. - abstract OnDispose : unit -> unit - - type IOutOfBand = - abstract StopFurtherProcessing : PipeIdx -> unit - - /// Consumer is the base class of all elements within the pipeline - [] - type Consumer<'T,'U> = - interface ICompletionChaining - new : unit -> Consumer<'T,'U> - abstract member ProcessNext : input:'T -> bool - abstract member OnComplete : PipeIdx -> unit - abstract member OnDispose : unit -> unit - - /// 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 - - /// 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 ForEach function. - [] - type Folder<'T,'U> = - inherit Consumer<'T,'T> - new : init:'U -> Folder<'T,'U> - val mutable Value: 'U - - type ISeqFactory<'T,'U> = - abstract member Create : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> - abstract member PipeIdx : PipeIdx - - type ISeq<'T> = - inherit System.Collections.Generic.IEnumerable<'T> - abstract member Compose : ISeqFactory<'T,'U> -> ISeq<'U> - abstract member ForEach : f:((unit -> unit) -> 'a) -> 'a when 'a :> Consumer<'T,'T> - /// Returns a new sequence that contains the cartesian product of the two input sequences. /// The first sequence. /// The second sequence. @@ -1273,7 +1204,7 @@ namespace Microsoft.FSharp.Collections /// /// Thrown when the input sequence is null. [] - val toComposer : source:seq<'T> -> Composer.Internal.ISeq<'T> + val toComposer : source:seq<'T> -> Composer.Core.ISeq<'T> /// Builds a list from the given collection. /// @@ -1419,4 +1350,4 @@ namespace Microsoft.FSharp.Collections /// /// Thrown when any of the input sequences is null. [] - val zip3: source1:seq<'T1> -> source2:seq<'T2> -> source3:seq<'T3> -> seq<'T1 * 'T2 * 'T3> + val zip3: source1:seq<'T1> -> source2:seq<'T2> -> source3:seq<'T3> -> seq<'T1 * 'T2 * 'T3> \ No newline at end of file diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 6ebe4e26cf8..3f36e2c1469 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -14,17 +14,21 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Control open Microsoft.FSharp.Collections open Microsoft.FSharp.Primitives.Basics - + [] module Composer = open IEnumerator module Core = - type PipeIdx = int + type PipeIdx = int + type ``PipeIdx?`` = Nullable + let emptyPipeIdx = Nullable () + let inline getPipeIdx (maybePipeIdx:``PipeIdx?``) = if maybePipeIdx.HasValue then maybePipeIdx.Value else 1 + let inline makePipeIdx (pipeIdx:PipeIdx) = Nullable pipeIdx type ICompletionChaining = - abstract OnComplete : stopTailCall:byref * PipeIdx -> unit - abstract OnDispose : stopTailCall:byref -> unit + abstract OnComplete : PipeIdx -> unit + abstract OnDispose : unit -> unit type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit @@ -34,16 +38,16 @@ namespace Microsoft.FSharp.Collections abstract ProcessNext : input:'T -> bool abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit + abstract OnDispose : unit -> unit default __.OnComplete _ = () default __.OnDispose () = () interface ICompletionChaining with - member this.OnComplete (_, terminatingIdx) = + member this.OnComplete terminatingIdx = this.OnComplete terminatingIdx - member this.OnDispose _ = + member this.OnDispose () = try this.OnDispose () finally () @@ -80,209 +84,266 @@ namespace Microsoft.FSharp.Collections Value = init } - [] - type SeqFactory<'T,'U> () = + type ISeqFactory<'T,'U> = abstract PipeIdx : PipeIdx - abstract Create<'V> : IOutOfBand -> PipeIdx -> Consumer<'U,'V> -> Consumer<'T,'V> - - default __.PipeIdx = 1 - - member this.Build outOfBand next = this.Create outOfBand 1 next + abstract Create<'V> : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> type ISeq<'T> = inherit IEnumerable<'T> - abstract member Compose<'U> : (SeqFactory<'T,'U>) -> ISeq<'U> + abstract member Compose<'U> : (ISeqFactory<'T,'U>) -> ISeq<'U> abstract member ForEach<'consumer when 'consumer :> Consumer<'T,'T>> : f:((unit->unit)->'consumer) -> 'consumer open Core - module internal TailCall = + module internal Helpers = // 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 + let inline avoidTailCall 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:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) - let inline enumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) - let inline enumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) - let inline enumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline iCompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) + let inline upcastSeq (t:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) + let inline upcastFactory (t:#ISeqFactory<'T,'U>) : ISeqFactory<'T,'U> = (# "" t : ISeqFactory<'T,'U> #) + let inline upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) + let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) + let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) + let inline upcastICompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) + + open Helpers module internal Seq = - type ComposedFactory<'T,'U,'V> private (first:SeqFactory<'T,'U>, second:SeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = - inherit SeqFactory<'T,'V>() + type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = + new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) + + interface ISeqFactory<'T,'U> with + member __.PipeIdx = getPipeIdx pipeIdx + member __.Create<'V> (_:IOutOfBand) (_:``PipeIdx?``) (_:Consumer<'U,'V>) : Consumer<'T,'V> = failwith "library implementation error: Create on base factory should not be called" - override __.PipeIdx = - secondPipeIdx + and ComposedFactory<'T,'U,'V> private (first:ISeqFactory<'T,'U>, second:ISeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = + inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) - override this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'V,'W>) : Consumer<'T,'W> = - first.Create outOfBand pipeIdx (second.Create outOfBand secondPipeIdx next) + interface ISeqFactory<'T,'V> with + member this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = + first.Create outOfBand pipeIdx (second.Create outOfBand (makePipeIdx secondPipeIdx) next) - static member Combine (first:SeqFactory<'T,'U>) (second:SeqFactory<'U,'V>) : SeqFactory<'T,'V> = - upcast ComposedFactory(first, second, first.PipeIdx+1) + static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = + ComposedFactory(first, second, first.PipeIdx+1) |> upcastFactory and ChooseFactory<'T,'U> (filter:'T->option<'U>) = - inherit SeqFactory<'T,'U> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) + inherit SeqComponentFactory<'T,'U> () + interface ISeqFactory<'T,'U> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) and DistinctFactory<'T when 'T: equality> () = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) + + and FilterFactory<'T> (filter:'T->bool) = + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = + match next with + | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter + | _ -> upcast Filter (filter, next) and IdentityFactory<'T> () = - inherit SeqFactory<'T,'T> () - static let singleton : SeqFactory<'T,'T> = upcast (IdentityFactory<'T>()) - override __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next + inherit SeqComponentFactory<'T,'T> () + static let singleton = IdentityFactory<'T>() + interface ISeqFactory<'T,'T> with + member __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next static member Instance = singleton + and MapFactory<'T,'U> (map:'T->'U) = + inherit SeqComponentFactory<'T,'U> () + interface ISeqFactory<'T,'U> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = + match next with + | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map + | _ -> upcast Map<_,_,_> (map, next) + and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = - inherit SeqFactory<'First,'U> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, outOfBand, next, pipeIdx) + inherit SeqComponentFactory<'First,'U> () + interface ISeqFactory<'First,'U> with + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, outOfBand, next, getPipeIdx pipeIdx) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = - inherit SeqFactory<'Second,'U> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, outOfBand, next, pipeIdx) + inherit SeqComponentFactory<'Second,'U> () + interface ISeqFactory<'Second,'U> with + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, outOfBand, next, getPipeIdx pipeIdx) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = - inherit SeqFactory<'First,'U> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, outOfBand, next, pipeIdx) + inherit SeqComponentFactory<'First,'U> () + interface ISeqFactory<'First,'U> with + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, outOfBand, next, getPipeIdx pipeIdx) + + and MapiFactory<'T,'U> (mapi:int->'T->'U) = + inherit SeqComponentFactory<'T,'U> () + interface ISeqFactory<'T,'U> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = - inherit SeqFactory<'First,'U> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, outOfBand, next, pipeIdx) + inherit SeqComponentFactory<'First,'U> () + interface ISeqFactory<'First,'U> with + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, outOfBand, next, getPipeIdx pipeIdx) and PairwiseFactory<'T> () = - inherit SeqFactory<'T,'T*'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) + inherit SeqComponentFactory<'T,'T*'T> () + interface ISeqFactory<'T,'T*'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = - inherit SeqFactory<'T,'State> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) + inherit SeqComponentFactory<'T,'State> () + interface ISeqFactory<'T,'State> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) - and SkipFactory<'T> (count:int, onNotEnoughElements) = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, onNotEnoughElements, next) + and SkipFactory<'T> (count:int) = + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) and SkipWhileFactory<'T> (predicate:'T->bool) = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, outOfBand, next, pipeIdx) + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, outOfBand, next, getPipeIdx pipeIdx) and TakeFactory<'T> (count:int) = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, pipeIdx) + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, getPipeIdx pipeIdx) and TailFactory<'T> () = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, pipeIdx) + inherit SeqComponentFactory<'T,'T> () + interface ISeqFactory<'T,'T> with + member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, getPipeIdx pipeIdx) and WindowedFactory<'T> (windowSize:int) = - inherit SeqFactory<'T, 'T[]> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T[],'V>) : Consumer<'T,'V> = upcast Windowed (windowSize, next) + inherit SeqComponentFactory<'T, 'T[]> () + interface ISeqFactory<'T, 'T[]> with + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T[],'V>) : Consumer<'T,'V> = upcast Windowed (windowSize, next) + + and [] SeqComponent<'T,'U> (next:ICompletionChaining) = + inherit Consumer<'T,'U>() - and ISkipping = // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip // and it can only do it at the start of a sequence abstract Skipping : unit -> bool - and [] SeqComponentSimple<'T,'U> (next:ICompletionChaining) = - inherit Consumer<'T,'U>() + abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> + abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> interface ICompletionChaining with - member this.OnComplete (stopTailCall, terminatingIdx) = - next.OnComplete (&stopTailCall, terminatingIdx) - member this.OnDispose stopTailCall = - next.OnDispose (&stopTailCall) - - and [] SeqComponentSimpleValue<'T,'U,'Value> = - inherit SeqComponentSimple<'T,'U> - - val mutable Value : 'Value - - new (next, init) = { - inherit SeqComponentSimple<'T,'U>(next) - Value = init - } - - and [] SeqComponent<'T,'U> (next:ICompletionChaining) = - inherit Consumer<'T,'U>() - - interface ICompletionChaining with - member this.OnComplete (stopTailCall, terminatingIdx) = + member this.OnComplete terminatingIdx = this.OnComplete terminatingIdx - next.OnComplete (&stopTailCall, terminatingIdx) - member this.OnDispose stopTailCall = + next.OnComplete terminatingIdx + member this.OnDispose () = try this.OnDispose () - finally next.OnDispose (&stopTailCall) + finally next.OnDispose () + + default __.Skipping () = false + + default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) + default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) and Choose<'T,'U,'V> (choose:'T->option<'U>, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) + inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = match choose input with - | Some value -> TailCall.avoid (next.ProcessNext value) + | Some value -> avoidTailCall (next.ProcessNext value) | None -> false and Distinct<'T,'V when 'T: equality> (next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) + inherit SeqComponent<'T,'V>(next) let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) override __.ProcessNext (input:'T) : bool = if hashSet.Add input then - TailCall.avoid (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else false and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) + inherit SeqComponent<'T,'V>(next) let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) override __.ProcessNext (input:'T) : bool = if hashSet.Add(keyFunction input) then - TailCall.avoid (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else false and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) + inherit SeqComponent<'T,'V>(next) let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) override __.ProcessNext (input:'T) : bool = if cached.Value.Add input then - TailCall.avoid (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else false + and Filter<'T,'V> (filter:'T->bool, next:Consumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) + + override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) + + override __.ProcessNext (input:'T) : bool = + if filter input then + avoidTailCall (next.ProcessNext input) + else + false + + and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:Consumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) + + override __.ProcessNext (input:'T) : bool = + if filter input then + avoidTailCall (next.ProcessNext (map input)) + else + false + + and Map<'T,'U,'V> (map:'T->'U, next:Consumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) + + override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) + + override __.ProcessNext (input:'T) : bool = + avoidTailCall (next.ProcessNext (map input)) + and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(Upcast.iCompletionChaining next) + inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map override __.ProcessNext (input:'First) : bool = if input2.MoveNext () then - TailCall.avoid (next.ProcessNext (map'.Invoke (input, input2.Current))) + avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -291,14 +352,14 @@ namespace Microsoft.FSharp.Collections input2.Dispose () and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'Second,'V>(Upcast.iCompletionChaining next) + inherit SeqComponent<'Second,'V>(next) let input1 = enumerable1.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map override __.ProcessNext (input:'Second) : bool = if input1.MoveNext () then - TailCall.avoid (next.ProcessNext (map'.Invoke (input1.Current, input))) + avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -307,7 +368,7 @@ namespace Microsoft.FSharp.Collections input1.Dispose () and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(Upcast.iCompletionChaining next) + inherit SeqComponent<'First,'V>(next) let input2 = enumerable2.GetEnumerator () let input3 = enumerable3.GetEnumerator () @@ -315,7 +376,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'First) : bool = if input2.MoveNext () && input3.MoveNext () then - TailCall.avoid (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) + avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -324,8 +385,28 @@ namespace Microsoft.FSharp.Collections try input2.Dispose () finally input3.Dispose () + and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:Consumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) + + override __.ProcessNext (input:'T) : bool = + let u = map input + if filter u then + avoidTailCall (next.ProcessNext u) + else + false + + and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:Consumer<'U,'V>) = + inherit SeqComponent<'T,'V>(next) + + let mutable idx = 0 + let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi + + override __.ProcessNext (input:'T) : bool = + idx <- idx + 1 + avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) + and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(Upcast.iCompletionChaining next) + inherit SeqComponent<'First,'V>(next) let mutable idx = 0 let input2 = enumerable2.GetEnumerator () @@ -334,7 +415,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'First) : bool = if input2.MoveNext () then idx <- idx + 1 - TailCall.avoid (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) + avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -343,7 +424,7 @@ namespace Microsoft.FSharp.Collections input2.Dispose () and Pairwise<'T,'V> (next:Consumer<'T*'T,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) + inherit SeqComponent<'T,'V>(next) let mutable isFirst = true let mutable lastValue = Unchecked.defaultof<'T> @@ -356,46 +437,45 @@ namespace Microsoft.FSharp.Collections else let currentPair = lastValue, input lastValue <- input - TailCall.avoid (next.ProcessNext currentPair) + avoidTailCall (next.ProcessNext currentPair) and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:Consumer<'State,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) + inherit SeqComponent<'T,'V>(next) let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let mutable foldResult = initialState override __.ProcessNext (input:'T) : bool = foldResult <- f.Invoke(foldResult, input) - TailCall.avoid (next.ProcessNext foldResult) + avoidTailCall (next.ProcessNext foldResult) - and Skip<'T,'V> (skipCount:int, notEnoughElements:string->array->unit, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) + and Skip<'T,'V> (skipCount:int, next:Consumer<'T,'V>) = + inherit SeqComponent<'T,'V>(next) let mutable count = 0 - interface ISkipping with - member __.Skipping () = - if count < skipCount then - count <- count + 1 - true - else - false + override __.Skipping () = + if count < skipCount then + count <- count + 1 + true + else + false override __.ProcessNext (input:'T) : bool = if count < skipCount then count <- count + 1 false else - TailCall.avoid (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) override __.OnComplete _ = if count < skipCount then let x = skipCount - count - notEnoughElements "{0}\ntried to skip {1} {2} past the end of the seq" + invalidOpFmt "tried to skip {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] and SkipWhile<'T,'V> (predicate:'T->bool, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) + inherit SeqComponent<'T,'V>(next) let mutable skip = true @@ -405,9 +485,9 @@ namespace Microsoft.FSharp.Collections if skip then false else - TailCall.avoid (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else - TailCall.avoid (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) and Take<'T,'V> (takeCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipelineIdx:int) = inherit Truncate<'T, 'V>(takeCount, outOfBand, next, pipelineIdx) @@ -419,17 +499,17 @@ namespace Microsoft.FSharp.Collections [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] and TakeWhile<'T,'V> (predicate:'T->bool, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) + inherit SeqComponent<'T,'V>(next) override __.ProcessNext (input:'T) : bool = if predicate input then - TailCall.avoid (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else outOfBand.StopFurtherProcessing pipeIdx false and Tail<'T, 'V> (next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) + inherit SeqComponent<'T,'V>(next) let mutable first = true @@ -438,14 +518,14 @@ namespace Microsoft.FSharp.Collections first <- false false else - TailCall.avoid (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) override this.OnComplete _ = if first then invalidArg "source" (SR.GetString(SR.notEnoughElements)) and Truncate<'T,'V> (truncateCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) + inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -456,13 +536,13 @@ namespace Microsoft.FSharp.Collections count <- count + 1 if count = truncateCount then outOfBand.StopFurtherProcessing pipeIdx - TailCall.avoid (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) else outOfBand.StopFurtherProcessing pipeIdx false and Windowed<'T,'V> (windowSize: int, next:Consumer<'T[],'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) + inherit SeqComponent<'T,'V>(next) let circularBuffer = Array.zeroCreateUnchecked windowSize let mutable idx = 0 @@ -482,12 +562,12 @@ namespace Microsoft.FSharp.Collections else if windowSize < 32 then let window = Array.init windowSize (fun i -> circularBuffer.[(idx+i) % windowSize]) - TailCall.avoid (next.ProcessNext window) + avoidTailCall (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) + avoidTailCall (next.ProcessNext window) type SeqProcessNextStates = | InProcess = 0 @@ -549,8 +629,8 @@ namespace Microsoft.FSharp.Collections iterate state let makeIsSkipping (consumer:Consumer<'T,'U>) = - match box consumer with - | :? ISkipping as skip -> skip.Skipping + match consumer with + | :? SeqComponent<'T,'U> as c -> c.Skipping | _ -> fun () -> false let init f (terminatingIdx:int) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = @@ -561,23 +641,21 @@ namespace Microsoft.FSharp.Collections if maybeSkipping then maybeSkipping <- isSkipping () - if not maybeSkipping then + if (not maybeSkipping) then consumer.ProcessNext (f (idx+1)) |> ignore idx <- idx + 1 - let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:SeqFactory<'T,'U>) executeOn = + let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:ISeqFactory<'T,'U>) executeOn = let pipeline = OutOfBand() let result = f (fun () -> (pipeline:>IOutOfBand).StopFurtherProcessing (current.PipeIdx+1)) - let consumer = current.Build pipeline result + let consumer = current.Create pipeline emptyPipeIdx result try executeOn pipeline consumer - let mutable stopTailCall = () - (Upcast.iCompletionChaining consumer).OnComplete (&stopTailCall, pipeline.HaltedIdx) + (upcastICompletionChaining consumer).OnComplete pipeline.HaltedIdx result finally - let mutable stopTailCall = () - (Upcast.iCompletionChaining consumer).OnDispose (&stopTailCall) + (upcastICompletionChaining consumer).OnDispose () module Enumerable = type Empty<'T>() = @@ -599,11 +677,10 @@ namespace Microsoft.FSharp.Collections type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ICompletionChaining) = interface IDisposable with member __.Dispose() : unit = - let mutable stopTailCall = () - seqComponent.OnDispose (&stopTailCall) + seqComponent.OnDispose () interface IEnumerator with - member this.Current : obj = box ((Upcast.enumerator this)).Current + member this.Current : obj = box ((upcastEnumerator this)).Current member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)" member __.Reset () : unit = noReset () @@ -622,13 +699,13 @@ namespace Microsoft.FSharp.Collections abstract member Append : (seq<'T>) -> IEnumerable<'T> - default this.Append source = Upcast.enumerable (AppendEnumerable [this; source]) + default this.Append source = upcastEnumerable (AppendEnumerable [this; source]) interface IEnumerable with member this.GetEnumerator () : IEnumerator = - let genericEnumerable = Upcast.enumerable this + let genericEnumerable = upcastEnumerable this let genericEnumerator = genericEnumerable.GetEnumerator () - Upcast.enumeratorNonGeneric genericEnumerator + upcastEnumeratorNonGeneric genericEnumerator interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () @@ -648,8 +725,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - let mutable stopTailCall = () - (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -662,20 +738,19 @@ namespace Microsoft.FSharp.Collections try source.Dispose () finally - let mutable stopTailCall = () - (Upcast.iCompletionChaining seqComponent).OnDispose (&stopTailCall) + (upcastICompletionChaining seqComponent).OnDispose () - and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqFactory<'T,'U>) = + and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:ISeqFactory<'T,'U>) = inherit EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Build result (SetResult<'U> result), result)) + upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with - member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) + member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + upcastSeq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.enumerable enumerable) @@ -707,7 +782,7 @@ namespace Microsoft.FSharp.Collections | _ -> failwith "library implementation error: all states should have been handled" interface IEnumerator with - member this.Current = box ((Upcast.enumerator this)).Current + member this.Current = box ((upcastEnumerator this)).Current member __.MoveNext () = state <- SeqProcessNextStates.InProcess moveNext () @@ -723,14 +798,14 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - Upcast.enumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) + upcastEnumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) override this.Append source = - Upcast.enumerable (AppendEnumerable (source :: sources)) + upcastEnumerable (AppendEnumerable (source :: sources)) interface ISeq<'T> with - member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable<'T,'V>(this, next)) + member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + upcastSeq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) @@ -740,17 +815,17 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - Upcast.enumerator (new ConcatEnumerator<_,_> (sources)) + upcastEnumerator (new ConcatEnumerator<_,_> (sources)) interface ISeq<'T> with - member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable<'T,'V>(this, next)) + member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + upcastSeq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) let create enumerable current = - Upcast.seq (Enumerable(enumerable, current)) + upcastSeq (Enumerable(enumerable, current)) module EmptyEnumerable = type Enumerable<'T> () = @@ -763,11 +838,11 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () : IEnumerator<'T> = IEnumerator.Empty<'T>() override this.Append source = - Upcast.enumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) + upcastEnumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) interface ISeq<'T> with - member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable.Enumerable<'T,'V>(this, next)) + member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + upcastSeq (Enumerable.Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) @@ -798,8 +873,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - let mutable stopTailCall = () - (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -807,25 +881,25 @@ namespace Microsoft.FSharp.Collections initMoveNext () moveNext () - type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqFactory<'T,'U>) = + type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:ISeqFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Build result (SetResult<'U> result), result)) + upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with - member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) + member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + upcastSeq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.array (delayedArray ())) - let createDelayed (delayedArray:unit->array<'T>) (current:SeqFactory<'T,'U>) = - Upcast.seq (Enumerable(delayedArray, current)) + let createDelayed (delayedArray:unit->array<'T>) (current:ISeqFactory<'T,'U>) = + upcastSeq (Enumerable(delayedArray, current)) - let create (array:array<'T>) (current:SeqFactory<'T,'U>) = + let create (array:array<'T>) (current:ISeqFactory<'T,'U>) = createDelayed (fun () -> array) current let createDelayedId (delayedArray:unit -> array<'T>) = @@ -850,8 +924,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - let mutable stopTailCall = () - (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -859,23 +932,23 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext list - type Enumerable<'T,'U>(alist:list<'T>, current:SeqFactory<'T,'U>) = + type Enumerable<'T,'U>(alist:list<'T>, current:ISeqFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Build result (SetResult<'U> result), result)) + upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with - member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) + member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + upcastSeq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.list alist) let create alist current = - Upcast.seq (Enumerable(alist, current)) + upcastSeq (Enumerable(alist, current)) module Unfold = type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, result:Result<'U>) = @@ -898,17 +971,17 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:SeqFactory<'T,'U>) = + type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:ISeqFactory<'T,'U>) = 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, current.Build result (SetResult<'U> result), result)) + upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with - member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) + member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + upcastSeq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.unfold generator state) @@ -964,8 +1037,7 @@ namespace Microsoft.FSharp.Collections raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else result.SeqState <- SeqProcessNextStates.Finished - let mutable stopTailCall = () - (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) + (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -973,17 +1045,17 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqFactory<'T,'U>) = + type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:ISeqFactory<'T,'U>) = 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, current.Build result (SetResult<'U> result), result)) + upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with - member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) + member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + upcastSeq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) member this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = let terminatingIdx = getTerminatingIdx count @@ -1050,25 +1122,25 @@ namespace Microsoft.FSharp.Collections upto (if count.HasValue then Some (count.Value-1) else None) f interface ISeq<'T> with - member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable<'T,'V>(count, f, next)) + member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + upcastSeq (Enumerable<'T,'V>(count, f, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (Upcast.enumerable this)) + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (upcastEnumerable this)) [] let toComposer (source:seq<'T>) : ISeq<'T> = + checkNonNull "source" source match source with | :? ISeq<'T> as s -> s - | :? array<'T> as a -> Upcast.seq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) - | :? list<'T> as a -> Upcast.seq (List.Enumerable(a, IdentityFactory.Instance)) - | null -> nullArg "source" - | _ -> Upcast.seq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) + | :? array<'T> as a -> upcastSeq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) + | :? list<'T> as a -> upcastSeq (List.Enumerable(a, IdentityFactory.Instance)) + | _ -> upcastSeq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) let inline foreach f (source:ISeq<_>) = source.ForEach f - let inline compose (factory:#SeqFactory<_,_>) (source:ISeq<'T>) = + let inline compose factory (source:ISeq<'T>) = source.Compose factory [] @@ -1076,17 +1148,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)) + upcastSeq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) [] let initInfinite<'T> (f:int->'T) : ISeq<'T> = - Upcast.seq (new Init.EnumerableDecider<'T>(Nullable (), f)) + upcastSeq (new Init.EnumerableDecider<'T>(Nullable (), f)) [] 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)) + upcastSeq (new Init.EnumerableDecider<'T>(Nullable count, f)) [] let iter f (source:ISeq<'T>) = @@ -1098,22 +1170,20 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore - [] - let tryHead (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, Option<'T>> (None) with - override this.ProcessNext value = - this.Value <- Some value - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun head -> head.Value - [] let tryItem i (source:ISeq<'T>) = if i < 0 then None else - source.Compose (SkipFactory(i, fun _ _ -> ())) - |> tryHead + source + |> foreach (fun halt -> + { new Folder<'T, Values>> (Values<_,_> (0, None)) with + override this.ProcessNext value = + if this.Value._1 = i then + this.Value._2 <- Some value + halt () + else + this.Value._1 <- this.Value._1 + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun item -> item.Value._2 [] let iteri f (source:ISeq<'T>) = @@ -1163,40 +1233,21 @@ namespace Microsoft.FSharp.Collections halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun forall -> forall.Value - + [] - let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source |> compose { new SeqFactory<'T,'T>() with - member __.Create _ _ next = - upcast { new SeqComponentSimple<'T,'V>(Upcast.iCompletionChaining next) with - member __.ProcessNext input = - if f input then TailCall.avoid (next.ProcessNext input) - else false } } + let filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = + source + |> compose (FilterFactory f) [] - let inline map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = - source |> compose { new SeqFactory<'T,'U>() with - member __.Create _ _ next = - upcast { new SeqComponentSimple<'T,'V>(Upcast.iCompletionChaining next) with - member __.ProcessNext input = - TailCall.avoid (next.ProcessNext (f input)) } } + let map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = + source + |> compose (MapFactory f) [] - let inline mapi f source = - source |> compose { new SeqFactory<'T,'U>() with - member __.Create _ _ next = - upcast { new SeqComponentSimpleValue<'T,'V,int>(Upcast.iCompletionChaining next, -1) with - override this.ProcessNext (input:'T) : bool = - this.Value <- this.Value + 1 - TailCall.avoid (next.ProcessNext (f this.Value input)) } } - - let mapi_adapt (f:OptimizedClosures.FSharpFunc<_,_,_>) source = - source |> compose { new SeqFactory<'T,'U>() with - member __.Create _ _ next = - upcast { new SeqComponentSimpleValue<'T,'V,int>(Upcast.iCompletionChaining next, -1) with - override this.ProcessNext (input:'T) : bool = - this.Value <- this.Value + 1 - TailCall.avoid (next.ProcessNext (f.Invoke (this.Value, input))) } } + let mapi f source = + source + |> compose (MapiFactory f) [] let choose f source = @@ -1204,8 +1255,9 @@ namespace Microsoft.FSharp.Collections |> compose (ChooseFactory f) [] - let inline indexed source = - mapi (fun i x -> i,x) source + let indexed source = + source + |> compose (MapiFactory (fun i x -> i,x)) [] let tryPick f (source:ISeq<'T>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index c9bdf2fdb3e..838cee6da37 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -14,6 +14,7 @@ namespace Microsoft.FSharp.Collections /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the /// source of the chain. type PipeIdx = int + type ``PipeIdx?`` = Nullable /// ICompletionChaining is used to correctly handle cleaning up of the pipeline. A /// base implementation is provided in Consumer, and should not be overwritten. Consumer @@ -25,10 +26,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 OnComplete : stopTailCall:byref*PipeIdx -> unit + abstract OnComplete : PipeIdx -> unit /// OnDispose is used to cleanup the stream. It is always called at the last operation /// after the enumeration has completed. - abstract OnDispose : stopTailCall:byref -> unit + abstract OnDispose : unit -> unit type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit @@ -70,160 +71,204 @@ namespace Microsoft.FSharp.Collections new : init:'U -> Folder<'T,'U> val mutable Value: 'U - [] - type SeqFactory<'T,'U> = - new : unit -> SeqFactory<'T,'U> - abstract PipeIdx : PipeIdx - abstract member Create : IOutOfBand -> PipeIdx -> Consumer<'U,'V> -> Consumer<'T,'V> + type ISeqFactory<'T,'U> = + abstract member Create : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> + abstract member PipeIdx : PipeIdx type ISeq<'T> = inherit System.Collections.Generic.IEnumerable<'T> - abstract member Compose : SeqFactory<'T,'U> -> ISeq<'U> + abstract member Compose : ISeqFactory<'T,'U> -> ISeq<'U> abstract member ForEach : f:((unit -> unit) -> 'a) -> 'a when 'a :> Consumer<'T,'T> open Core + module internal Helpers = + val inline avoidTailCall : boolean:bool -> bool + val inline upcastSeq : t: #ISeq<'T> -> ISeq<'T> + val inline upcastFactory : + t: #ISeqFactory<'T,'U> -> ISeqFactory<'T,'U> + val inline upcastEnumerable : t:#IEnumerable<'T> -> IEnumerable<'T> + val inline upcastEnumerator : t:#IEnumerator<'T> ->IEnumerator<'T> + val inline upcastEnumeratorNonGeneric : + t:#IEnumerator -> IEnumerator + val inline upcastICompletionChaining : + t: #ICompletionChaining -> ICompletionChaining + module internal Seq = - type ComposedFactory<'T,'U,'V> = + [] + type SeqComponentFactory<'T,'U> = class - inherit SeqFactory<'T,'V> - private new : first: SeqFactory<'T,'U> * - second: SeqFactory<'U,'V> * + interface ISeqFactory<'T,'U> + new : unit -> SeqComponentFactory<'T,'U> + new : pipeIdx: ``PipeIdx?`` -> + SeqComponentFactory<'T,'U> + end + and ComposedFactory<'T,'U,'V> = + class + inherit SeqComponentFactory<'T,'V> + interface ISeqFactory<'T,'V> + private new : first: ISeqFactory<'T,'U> * + second: ISeqFactory<'U,'V> * secondPipeIdx: PipeIdx -> ComposedFactory<'T,'U,'V> static member - Combine : first: SeqFactory<'T,'U> -> - second: SeqFactory<'U,'V> -> - SeqFactory<'T,'V> + Combine : first: ISeqFactory<'T,'U> -> + second: ISeqFactory<'U,'V> -> + ISeqFactory<'T,'V> end and ChooseFactory<'T,'U> = class - inherit SeqFactory<'T,'U> + inherit SeqComponentFactory<'T,'U> + interface ISeqFactory<'T,'U> new : filter:('T -> 'U option) -> ChooseFactory<'T,'U> end and DistinctFactory<'T when 'T : equality> = class - inherit SeqFactory<'T,'T> + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> new : unit -> DistinctFactory<'T> end and DistinctByFactory<'T,'Key when 'Key : equality> = class - inherit SeqFactory<'T,'T> + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> new : keyFunction:('T -> 'Key) -> DistinctByFactory<'T,'Key> end and ExceptFactory<'T when 'T : equality> = class - inherit SeqFactory<'T,'T> + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> new : itemsToExclude:seq<'T> -> ExceptFactory<'T> end + and FilterFactory<'T> = + class + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> + new : filter:('T -> bool) -> FilterFactory<'T> + end and IdentityFactory<'T> = class - inherit SeqFactory<'T,'T> + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> new : unit -> IdentityFactory<'T> - static member Instance : SeqFactory<'T,'T> + static member Instance : IdentityFactory<'T> + end + and MapFactory<'T,'U> = + class + inherit SeqComponentFactory<'T,'U> + interface ISeqFactory<'T,'U> + new : map:('T -> 'U) -> MapFactory<'T,'U> end and Map2FirstFactory<'First,'Second,'U> = class - inherit SeqFactory<'First,'U> + inherit SeqComponentFactory<'First,'U> + interface ISeqFactory<'First,'U> new : map:('First -> 'Second -> 'U) * input2:IEnumerable<'Second> -> Map2FirstFactory<'First,'Second,'U> end and Map2SecondFactory<'First,'Second,'U> = class - inherit SeqFactory<'Second,'U> + inherit SeqComponentFactory<'Second,'U> + interface ISeqFactory<'Second,'U> new : map:('First -> 'Second -> 'U) * input1:IEnumerable<'First> -> Map2SecondFactory<'First,'Second,'U> end and Map3Factory<'First,'Second,'Third,'U> = class - inherit SeqFactory<'First,'U> + inherit SeqComponentFactory<'First,'U> + interface ISeqFactory<'First,'U> new : map:('First -> 'Second -> 'Third -> 'U) * input2:IEnumerable<'Second> * input3:IEnumerable<'Third> -> Map3Factory<'First,'Second,'Third,'U> end + and MapiFactory<'T,'U> = + class + inherit SeqComponentFactory<'T,'U> + interface ISeqFactory<'T,'U> + new : mapi:(int -> 'T -> 'U) -> MapiFactory<'T,'U> + end and Mapi2Factory<'First,'Second,'U> = class - inherit SeqFactory<'First,'U> + inherit SeqComponentFactory<'First,'U> + interface ISeqFactory<'First,'U> new : map:(int -> 'First -> 'Second -> 'U) * input2:IEnumerable<'Second> -> Mapi2Factory<'First,'Second,'U> end and PairwiseFactory<'T> = class - inherit SeqFactory<'T,('T * 'T)> + inherit SeqComponentFactory<'T,('T * 'T)> + interface ISeqFactory<'T,('T * 'T)> new : unit -> PairwiseFactory<'T> end and ScanFactory<'T,'State> = class - inherit SeqFactory<'T,'State> + inherit SeqComponentFactory<'T,'State> + interface ISeqFactory<'T,'State> new : folder:('State -> 'T -> 'State) * initialState:'State -> ScanFactory<'T,'State> end and SkipFactory<'T> = class - inherit SeqFactory<'T,'T> - new : count:int * notEnoughElements:(string->array->unit) -> SkipFactory<'T> + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> + new : count:int -> SkipFactory<'T> end and SkipWhileFactory<'T> = class - inherit SeqFactory<'T,'T> + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> new : predicate:('T -> bool) -> SkipWhileFactory<'T> end and TakeWhileFactory<'T> = class - inherit SeqFactory<'T,'T> + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> new : predicate:('T -> bool) -> TakeWhileFactory<'T> end and TakeFactory<'T> = class - inherit SeqFactory<'T,'T> + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> new : count:int -> TakeFactory<'T> end and TailFactory<'T> = class - inherit SeqFactory<'T,'T> + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> new : unit -> TailFactory<'T> end and TruncateFactory<'T> = class - inherit SeqFactory<'T,'T> + inherit SeqComponentFactory<'T,'T> + interface ISeqFactory<'T,'T> new : count:int -> TruncateFactory<'T> end and WindowedFactory<'T> = class - inherit SeqFactory<'T,'T []> + inherit SeqComponentFactory<'T,'T []> + interface ISeqFactory<'T,'T []> new : windowSize:int -> WindowedFactory<'T> end - and ISkipping = - interface - abstract member Skipping : unit -> bool - end - - and [] SeqComponentSimple<'T,'U> = - class - inherit Consumer<'T,'U> - interface ICompletionChaining - new : next:ICompletionChaining -> SeqComponentSimple<'T,'U> - end - - and [] SeqComponentSimpleValue<'T,'U,'Value> = - class - inherit SeqComponentSimple<'T,'U> - val mutable Value : 'Value - new : next:ICompletionChaining*value:'Value -> SeqComponentSimpleValue<'T,'U,'Value> - end - and [] SeqComponent<'T,'U> = class - inherit Consumer<'T,'U> - interface ICompletionChaining - new : next:ICompletionChaining -> - SeqComponent<'T,'U> + inherit Consumer<'T,'U> + interface ICompletionChaining + new : next: ICompletionChaining -> + SeqComponent<'T,'U> + abstract member + CreateFilter : filter:('T -> bool) -> SeqComponent<'T,'U> + abstract member + CreateMap : map:('S -> 'T) -> SeqComponent<'S,'U> + abstract member Skipping : unit -> bool + override + CreateFilter : filter:('T -> bool) -> SeqComponent<'T,'U> + override CreateMap : map:('S -> 'T) -> SeqComponent<'S,'U> + override Skipping : unit -> bool end - and Choose<'T,'U,'V> = class inherit SeqComponent<'T,'V> @@ -251,6 +296,31 @@ namespace Microsoft.FSharp.Collections Except<'T,'V> override ProcessNext : input:'T -> bool end + and Filter<'T,'V> = + class + inherit SeqComponent<'T,'V> + new : filter:('T -> bool) * next: Consumer<'T,'V> -> + Filter<'T,'V> + override CreateMap : map:('S -> 'T) -> SeqComponent<'S,'V> + override ProcessNext : input:'T -> bool + end + and FilterThenMap<'T,'U,'V> = + class + inherit SeqComponent<'T,'V> + new : filter:('T -> bool) * map:('T -> 'U) * + next: Consumer<'U,'V> -> + FilterThenMap<'T,'U,'V> + override ProcessNext : input:'T -> bool + end + and Map<'T,'U,'V> = + class + inherit SeqComponent<'T,'V> + new : map:('T -> 'U) * next: Consumer<'U,'V> -> + Map<'T,'U,'V> + override + CreateFilter : filter:('T -> bool) -> SeqComponent<'T,'V> + override ProcessNext : input:'T -> bool + end and Map2First<'First,'Second,'U,'V> = class inherit SeqComponent<'First,'V> @@ -285,6 +355,21 @@ namespace Microsoft.FSharp.Collections override OnDispose : unit -> unit override ProcessNext : input:'First -> bool end + and MapThenFilter<'T,'U,'V> = + class + inherit SeqComponent<'T,'V> + new : map:('T -> 'U) * filter:('U -> bool) * + next: Consumer<'U,'V> -> + MapThenFilter<'T,'U,'V> + override ProcessNext : input:'T -> bool + end + and Mapi<'T,'U,'V> = + class + inherit SeqComponent<'T,'V> + new : mapi:(int -> 'T -> 'U) * next: Consumer<'U,'V> -> + Mapi<'T,'U,'V> + override ProcessNext : input:'T -> bool + end and Mapi2<'First,'Second,'U,'V> = class inherit SeqComponent<'First,'V> @@ -314,11 +399,11 @@ namespace Microsoft.FSharp.Collections and Skip<'T,'V> = class inherit SeqComponent<'T,'V> - interface ISkipping - new : skipCount:int * exceptionOnNotEnoughElements:(string->array->unit) * next: Consumer<'T,'V> -> + new : skipCount:int * next: Consumer<'T,'V> -> Skip<'T,'V> override OnComplete : PipeIdx -> unit override ProcessNext : input:'T -> bool + override Skipping : unit -> bool end and SkipWhile<'T,'V> = class @@ -419,7 +504,7 @@ namespace Microsoft.FSharp.Collections consumer: Consumer<'T,'U> -> unit val execute : f:((unit -> unit) -> 'a) -> - current: SeqFactory<'T,'U> -> + current: ISeqFactory<'T,'U> -> executeOn:( OutOfBand -> Consumer<'T,'U> -> unit) -> 'a when 'a :> Consumer<'U,'U> end @@ -473,7 +558,7 @@ namespace Microsoft.FSharp.Collections interface ISeq<'U> interface IEnumerable<'U> new : enumerable:IEnumerable<'T> * - current: SeqFactory<'T,'U> -> + current: ISeqFactory<'T,'U> -> Enumerable<'T,'U> end and ConcatEnumerator<'T,'Collection when 'Collection :> seq<'T>> = @@ -504,7 +589,7 @@ namespace Microsoft.FSharp.Collections end val create : enumerable:IEnumerable<'a> -> - current: SeqFactory<'a,'b> -> ISeq<'b> + current: ISeqFactory<'a,'b> -> ISeq<'b> end module EmptyEnumerable = begin type Enumerable<'T> = @@ -533,15 +618,15 @@ namespace Microsoft.FSharp.Collections interface ISeq<'U> interface IEnumerable<'U> new : delayedArray:(unit -> 'T array) * - current: SeqFactory<'T,'U> -> + current: ISeqFactory<'T,'U> -> Enumerable<'T,'U> end val createDelayed : delayedArray:(unit -> 'T array) -> - current: SeqFactory<'T,'U> -> ISeq<'U> + current: ISeqFactory<'T,'U> -> ISeq<'U> val create : array:'T array -> - current: SeqFactory<'T,'U> -> ISeq<'U> + current: ISeqFactory<'T,'U> -> ISeq<'U> val createDelayedId : delayedArray:(unit -> 'T array) -> ISeq<'T> val createId : array:'T array -> ISeq<'T> @@ -559,12 +644,12 @@ namespace Microsoft.FSharp.Collections inherit Enumerable.EnumerableBase<'U> interface ISeq<'U> interface IEnumerable<'U> - new : alist:'T list * current: SeqFactory<'T,'U> -> + new : alist:'T list * current: ISeqFactory<'T,'U> -> Enumerable<'T,'U> end val create : alist:'a list -> - current: SeqFactory<'a,'b> -> ISeq<'b> + current: ISeqFactory<'a,'b> -> ISeq<'b> end module Unfold = begin type Enumerator<'T,'U,'State> = @@ -582,7 +667,7 @@ namespace Microsoft.FSharp.Collections interface ISeq<'U> interface IEnumerable<'U> new : generator:('GeneratorState -> ('T * 'GeneratorState) option) * - state:'GeneratorState * current: SeqFactory<'T,'U> -> + state:'GeneratorState * current: ISeqFactory<'T,'U> -> Enumerable<'T,'U,'GeneratorState> end end @@ -602,7 +687,7 @@ namespace Microsoft.FSharp.Collections interface ISeq<'U> interface IEnumerable<'U> new : count:Nullable * f:(int -> 'T) * - current: SeqFactory<'T,'U> -> + current: ISeqFactory<'T,'U> -> Enumerable<'T,'U> end val upto : @@ -622,6 +707,9 @@ namespace Microsoft.FSharp.Collections val inline foreach : f:((unit -> unit) -> 'a) -> source: ISeq<'b> -> 'a when 'a :> Consumer<'b,'b> + val inline compose : + factory: ISeqFactory<'T,'a> -> + source: ISeq<'T> -> ISeq<'a> [] val empty<'T> : ISeq<'T> [] @@ -634,8 +722,6 @@ namespace Microsoft.FSharp.Collections val init : count:int -> f:(int -> 'T) -> ISeq<'T> [] val iter : f:('T -> unit) -> source: ISeq<'T> -> unit - [] - val tryHead : source: ISeq<'T> -> 'T option [] val tryItem : i:int -> source: ISeq<'T> -> 'T option [] @@ -647,24 +733,22 @@ namespace Microsoft.FSharp.Collections element:'T -> source: ISeq<'T> -> bool when 'T : equality [] val forall : f:('T -> bool) -> source: ISeq<'T> -> bool - - [] - val inline filter : f:('T -> bool) -> source: ISeq<'T> -> ISeq<'T> - - [] - val inline map : f:('T -> 'U) -> source: ISeq<'T> -> ISeq<'U> - + [] + val filter : + f:('T -> bool) -> source: ISeq<'T> -> ISeq<'T> + [] + val map : + f:('T -> 'U) -> source: ISeq<'T> -> ISeq<'U> [] - val inline mapi : f:(int->'a->'b) -> source: ISeq<'a> -> ISeq<'b> - - val mapi_adapt : f:OptimizedClosures.FSharpFunc -> source: ISeq<'a> -> ISeq<'b> - + val mapi : + f:(int -> 'a -> 'b) -> + source: ISeq<'a> -> ISeq<'b> [] - val choose : f:('a->option<'b>) -> source: ISeq<'a> -> ISeq<'b> - + val choose : + f:('a -> 'b option) -> + source: ISeq<'a> -> ISeq<'b> [] - val inline indexed : source: ISeq<'a> -> ISeq - + val indexed : source: ISeq<'a> -> ISeq [] val tryPick : f:('T -> 'U option) -> source: ISeq<'T> -> Option<'U> From 9d7529387f2060989f6eae540beea9651dd45c55 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 5 Nov 2016 10:59:20 +1100 Subject: [PATCH 209/286] Remove Helper from signature file Probably shouldn't be exposed in that manor in the first place, but secondly they caused a error in ci_part1. Used this as a chance to rename the module as well. --- src/fsharp/FSharp.Core/seq.fs | 41 ++++--- src/fsharp/FSharp.Core/seqcomposer.fs | 149 ++++++++++++------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 12 -- 3 files changed, 94 insertions(+), 108 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index daafe8076c0..db102da73a1 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -39,7 +39,6 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Core.ICloneableExtensions #else #endif - let mkDelayedSeq (f: unit -> IEnumerable<'T>) = mkSeq (fun () -> f().GetEnumerator()) let inline indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) @@ -67,7 +66,7 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : seq<'T> = Composer.Seq.unfold generator state - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let empty<'T> = (EmptyEnumerable :> seq<'T>) @@ -75,12 +74,12 @@ namespace Microsoft.FSharp.Collections [] let initInfinite<'T> (f:int->'T) : IEnumerable<'T> = Composer.Seq.initInfinite f - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> = Composer.Seq.init count f - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let iter f (source : seq<'T>) = @@ -189,15 +188,15 @@ namespace Microsoft.FSharp.Collections let private seqFactory createSeqComponent (source:seq<'T>) = checkNonNull "source" source match source with - | :? Composer.Core.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose createSeqComponent) - | :? array<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.Seq.Array.create a createSeqComponent) - | :? list<'T> as a -> Composer.Helpers.upcastEnumerable (Composer.Seq.List.create a createSeqComponent) - | _ -> Composer.Helpers.upcastEnumerable (Composer.Seq.Enumerable.create source createSeqComponent) + | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose createSeqComponent) + | :? array<'T> as a -> Upcast.enumerable (Composer.Seq.Array.create a createSeqComponent) + | :? list<'T> as a -> Upcast.enumerable (Composer.Seq.List.create a createSeqComponent) + | _ -> Upcast.enumerable (Composer.Seq.Enumerable.create source createSeqComponent) [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = Composer.Seq.filter f (toComposer source) - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let where f source = filter f source @@ -205,12 +204,12 @@ namespace Microsoft.FSharp.Collections [] let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> = Composer.Seq.map f (toComposer source) - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let mapi f source = Composer.Seq.mapi f (toComposer source) - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let mapi2 f source1 source2 = @@ -221,7 +220,7 @@ namespace Microsoft.FSharp.Collections let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = checkNonNull "source1" source1 match source1 with - | :? Composer.Core.ISeq<'T> as s -> Composer.Helpers.upcastEnumerable (s.Compose (Composer.Seq.Map2FirstFactory (f, source2))) + | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose (Composer.Seq.Map2FirstFactory (f, source2))) | _ -> source2 |> seqFactory (Composer.Seq.Map2SecondFactory (f, source1)) [] @@ -233,12 +232,12 @@ namespace Microsoft.FSharp.Collections [] let choose f source = Composer.Seq.choose f (toComposer source) - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let indexed source = Composer.Seq.indexed (toComposer source) - |> Composer.Helpers.upcastEnumerable + |> Upcast.enumerable [] let zip source1 source2 = @@ -385,7 +384,7 @@ namespace Microsoft.FSharp.Collections checkNonNull "source2" source2 match source1 with | :? Composer.Seq.Enumerable.EnumerableBase<'T> as s -> s.Append source2 - | _ -> Composer.Helpers.upcastEnumerable (new Composer.Seq.Enumerable.AppendEnumerable<_>([source2; source1])) + | _ -> Upcast.enumerable (new Composer.Seq.Enumerable.AppendEnumerable<_>([source2; source1])) [] @@ -429,7 +428,7 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source : 'T array) = checkNonNull "source" source - Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createId source) + Upcast.enumerable (Composer.Seq.Array.createId source) [] let toArray (source : seq<'T>) = @@ -679,7 +678,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceBy keyf array array - Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedSort) + Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedSort) [] let sort source = @@ -688,7 +687,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlace array array - Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedSort) + Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedSort) [] let sortWith f source = @@ -697,7 +696,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceWith f array array - Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedSort) + Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedSort) [] let inline sortByDescending keyf source = @@ -1059,7 +1058,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.Reverse array array - Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedReverse) + Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedReverse) [] let permute f (source:seq<_>) = @@ -1068,7 +1067,7 @@ namespace Microsoft.FSharp.Collections source |> toArray |> Array.permute f - Composer.Helpers.upcastEnumerable (Composer.Seq.Array.createDelayedId delayedPermute) + Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedPermute) [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 3f36e2c1469..6e007722a86 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -14,7 +14,7 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Control open Microsoft.FSharp.Collections open Microsoft.FSharp.Primitives.Basics - + [] module Composer = open IEnumerator @@ -95,22 +95,21 @@ namespace Microsoft.FSharp.Collections open Core - module internal Helpers = + 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 avoidTailCall boolean = match boolean with true -> true | false -> false + 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 upcastSeq (t:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) - let inline upcastFactory (t:#ISeqFactory<'T,'U>) : ISeqFactory<'T,'U> = (# "" t : ISeqFactory<'T,'U> #) - let inline upcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) - let inline upcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) - let inline upcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline upcastICompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) - - open Helpers + let inline seq (t:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) + let inline factory (t:#ISeqFactory<'T,'U>) : ISeqFactory<'T,'U> = (# "" t : ISeqFactory<'T,'U> #) + let inline enumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) + let inline enumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) + let inline enumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) + let inline iCompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) module internal Seq = type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = @@ -128,7 +127,7 @@ namespace Microsoft.FSharp.Collections first.Create outOfBand pipeIdx (second.Create outOfBand (makePipeIdx secondPipeIdx) next) static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = - ComposedFactory(first, second, first.PipeIdx+1) |> upcastFactory + ComposedFactory(first, second, first.PipeIdx+1) |> Upcast.factory and ChooseFactory<'T,'U> (filter:'T->option<'U>) = inherit SeqComponentFactory<'T,'U> () @@ -271,7 +270,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = match choose input with - | Some value -> avoidTailCall (next.ProcessNext value) + | Some value -> TailCall.avoid (next.ProcessNext value) | None -> false and Distinct<'T,'V when 'T: equality> (next:Consumer<'T,'V>) = @@ -281,7 +280,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if hashSet.Add input then - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) else false @@ -292,7 +291,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if hashSet.Add(keyFunction input) then - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) else false @@ -303,7 +302,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if cached.Value.Add input then - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) else false @@ -314,7 +313,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if filter input then - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) else false @@ -323,7 +322,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if filter input then - avoidTailCall (next.ProcessNext (map input)) + TailCall.avoid (next.ProcessNext (map input)) else false @@ -333,7 +332,7 @@ namespace Microsoft.FSharp.Collections override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) override __.ProcessNext (input:'T) : bool = - avoidTailCall (next.ProcessNext (map input)) + TailCall.avoid (next.ProcessNext (map input)) and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) @@ -343,7 +342,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'First) : bool = if input2.MoveNext () then - avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current))) + TailCall.avoid (next.ProcessNext (map'.Invoke (input, input2.Current))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -359,7 +358,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'Second) : bool = if input1.MoveNext () then - avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input))) + TailCall.avoid (next.ProcessNext (map'.Invoke (input1.Current, input))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -376,7 +375,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'First) : bool = if input2.MoveNext () && input3.MoveNext () then - avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) + TailCall.avoid (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -391,7 +390,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = let u = map input if filter u then - avoidTailCall (next.ProcessNext u) + TailCall.avoid (next.ProcessNext u) else false @@ -403,7 +402,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = idx <- idx + 1 - avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input))) + TailCall.avoid (next.ProcessNext (mapi'.Invoke (idx-1, input))) and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(next) @@ -415,7 +414,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'First) : bool = if input2.MoveNext () then idx <- idx + 1 - avoidTailCall (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) + TailCall.avoid (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) else outOfBand.StopFurtherProcessing pipeIdx false @@ -437,7 +436,7 @@ namespace Microsoft.FSharp.Collections else let currentPair = lastValue, input lastValue <- input - avoidTailCall (next.ProcessNext currentPair) + TailCall.avoid (next.ProcessNext currentPair) and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:Consumer<'State,'V>) = inherit SeqComponent<'T,'V>(next) @@ -447,7 +446,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = foldResult <- f.Invoke(foldResult, input) - avoidTailCall (next.ProcessNext foldResult) + TailCall.avoid (next.ProcessNext foldResult) and Skip<'T,'V> (skipCount:int, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) @@ -466,7 +465,7 @@ namespace Microsoft.FSharp.Collections count <- count + 1 false else - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) override __.OnComplete _ = if count < skipCount then @@ -485,9 +484,9 @@ namespace Microsoft.FSharp.Collections if skip then false else - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) else - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) and Take<'T,'V> (takeCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipelineIdx:int) = inherit Truncate<'T, 'V>(takeCount, outOfBand, next, pipelineIdx) @@ -503,7 +502,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = if predicate input then - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) else outOfBand.StopFurtherProcessing pipeIdx false @@ -518,7 +517,7 @@ namespace Microsoft.FSharp.Collections first <- false false else - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) override this.OnComplete _ = if first then @@ -536,7 +535,7 @@ namespace Microsoft.FSharp.Collections count <- count + 1 if count = truncateCount then outOfBand.StopFurtherProcessing pipeIdx - avoidTailCall (next.ProcessNext input) + TailCall.avoid (next.ProcessNext input) else outOfBand.StopFurtherProcessing pipeIdx false @@ -562,12 +561,12 @@ namespace Microsoft.FSharp.Collections else if windowSize < 32 then let window = Array.init windowSize (fun i -> circularBuffer.[(idx+i) % windowSize]) - avoidTailCall (next.ProcessNext window) + 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) - avoidTailCall (next.ProcessNext window) + TailCall.avoid (next.ProcessNext window) type SeqProcessNextStates = | InProcess = 0 @@ -652,10 +651,10 @@ namespace Microsoft.FSharp.Collections let consumer = current.Create pipeline emptyPipeIdx result try executeOn pipeline consumer - (upcastICompletionChaining consumer).OnComplete pipeline.HaltedIdx + (Upcast.iCompletionChaining consumer).OnComplete pipeline.HaltedIdx result finally - (upcastICompletionChaining consumer).OnDispose () + (Upcast.iCompletionChaining consumer).OnDispose () module Enumerable = type Empty<'T>() = @@ -680,7 +679,7 @@ namespace Microsoft.FSharp.Collections seqComponent.OnDispose () interface IEnumerator with - member this.Current : obj = box ((upcastEnumerator this)).Current + 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 () @@ -699,13 +698,13 @@ namespace Microsoft.FSharp.Collections abstract member Append : (seq<'T>) -> IEnumerable<'T> - default this.Append source = upcastEnumerable (AppendEnumerable [this; source]) + default this.Append source = Upcast.enumerable (AppendEnumerable [this; source]) interface IEnumerable with member this.GetEnumerator () : IEnumerator = - let genericEnumerable = upcastEnumerable this + let genericEnumerable = Upcast.enumerable this let genericEnumerator = genericEnumerable.GetEnumerator () - upcastEnumeratorNonGeneric genericEnumerator + Upcast.enumeratorNonGeneric genericEnumerator interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () @@ -725,7 +724,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -738,7 +737,7 @@ namespace Microsoft.FSharp.Collections try source.Dispose () finally - (upcastICompletionChaining seqComponent).OnDispose () + (Upcast.iCompletionChaining seqComponent).OnDispose () and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:ISeqFactory<'T,'U>) = inherit EnumerableBase<'U>() @@ -746,11 +745,11 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) + Upcast.seq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.enumerable enumerable) @@ -782,7 +781,7 @@ namespace Microsoft.FSharp.Collections | _ -> failwith "library implementation error: all states should have been handled" interface IEnumerator with - member this.Current = box ((upcastEnumerator this)).Current + member this.Current = box ((Upcast.enumerator this)).Current member __.MoveNext () = state <- SeqProcessNextStates.InProcess moveNext () @@ -798,14 +797,14 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - upcastEnumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) + Upcast.enumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) override this.Append source = - upcastEnumerable (AppendEnumerable (source :: sources)) + Upcast.enumerable (AppendEnumerable (source :: sources)) interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable<'T,'V>(this, next)) + Upcast.seq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) @@ -815,17 +814,17 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'T> with member this.GetEnumerator () : IEnumerator<'T> = - upcastEnumerator (new ConcatEnumerator<_,_> (sources)) + Upcast.enumerator (new ConcatEnumerator<_,_> (sources)) interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable<'T,'V>(this, next)) + Upcast.seq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) let create enumerable current = - upcastSeq (Enumerable(enumerable, current)) + Upcast.seq (Enumerable(enumerable, current)) module EmptyEnumerable = type Enumerable<'T> () = @@ -838,11 +837,11 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () : IEnumerator<'T> = IEnumerator.Empty<'T>() override this.Append source = - upcastEnumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) + Upcast.enumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable.Enumerable<'T,'V>(this, next)) + Upcast.seq (Enumerable.Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) @@ -873,7 +872,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -887,17 +886,17 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) + Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:ISeqFactory<'T,'U>) = - upcastSeq (Enumerable(delayedArray, current)) + Upcast.seq (Enumerable(delayedArray, current)) let create (array:array<'T>) (current:ISeqFactory<'T,'U>) = createDelayed (fun () -> array) current @@ -924,7 +923,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -938,17 +937,17 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) + Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.list alist) let create alist current = - upcastSeq (Enumerable(alist, current)) + Upcast.seq (Enumerable(alist, current)) module Unfold = type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, result:Result<'U>) = @@ -977,11 +976,11 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) + Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.unfold generator state) @@ -1037,7 +1036,7 @@ namespace Microsoft.FSharp.Collections raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else result.SeqState <- SeqProcessNextStates.Finished - (upcastICompletionChaining seqComponent).OnComplete result.HaltedIdx + (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx false interface IEnumerator with @@ -1051,11 +1050,11 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - upcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(count, f, current.Create result emptyPipeIdx (SetResult<'U> result), result)) interface ISeq<'U> with member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = - upcastSeq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) + Upcast.seq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) member this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = let terminatingIdx = getTerminatingIdx count @@ -1123,19 +1122,19 @@ namespace Microsoft.FSharp.Collections interface ISeq<'T> with member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = - upcastSeq (Enumerable<'T,'V>(count, f, next)) + Upcast.seq (Enumerable<'T,'V>(count, f, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (upcastEnumerable this)) + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (Upcast.enumerable this)) [] let toComposer (source:seq<'T>) : ISeq<'T> = checkNonNull "source" source match source with | :? ISeq<'T> as s -> s - | :? array<'T> as a -> upcastSeq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) - | :? list<'T> as a -> upcastSeq (List.Enumerable(a, IdentityFactory.Instance)) - | _ -> upcastSeq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) + | :? array<'T> as a -> Upcast.seq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) + | :? list<'T> as a -> Upcast.seq (List.Enumerable(a, IdentityFactory.Instance)) + | _ -> Upcast.seq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) let inline foreach f (source:ISeq<_>) = source.ForEach f @@ -1148,17 +1147,17 @@ namespace Microsoft.FSharp.Collections [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = - upcastSeq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) + Upcast.seq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) [] let initInfinite<'T> (f:int->'T) : ISeq<'T> = - upcastSeq (new Init.EnumerableDecider<'T>(Nullable (), f)) + Upcast.seq (new Init.EnumerableDecider<'T>(Nullable (), f)) [] let init<'T> (count:int) (f:int->'T) : ISeq<'T> = if count < 0 then invalidArgInputMustBeNonNegative "count" count elif count = 0 then empty else - upcastSeq (new Init.EnumerableDecider<'T>(Nullable count, f)) + Upcast.seq (new Init.EnumerableDecider<'T>(Nullable count, f)) [] let iter f (source:ISeq<'T>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 838cee6da37..522f35b06da 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -82,18 +82,6 @@ namespace Microsoft.FSharp.Collections open Core - module internal Helpers = - val inline avoidTailCall : boolean:bool -> bool - val inline upcastSeq : t: #ISeq<'T> -> ISeq<'T> - val inline upcastFactory : - t: #ISeqFactory<'T,'U> -> ISeqFactory<'T,'U> - val inline upcastEnumerable : t:#IEnumerable<'T> -> IEnumerable<'T> - val inline upcastEnumerator : t:#IEnumerator<'T> ->IEnumerator<'T> - val inline upcastEnumeratorNonGeneric : - t:#IEnumerator -> IEnumerator - val inline upcastICompletionChaining : - t: #ICompletionChaining -> ICompletionChaining - module internal Seq = [] type SeqComponentFactory<'T,'U> = From 8ff87eb5a4fe4ee64bd5c8c1dd2ccb83a1e026af Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 5 Nov 2016 15:37:03 +1100 Subject: [PATCH 210/286] Modified item/tryItem to use skip Unit tests check that the item call object the lazy nature of the Seq.init --- src/fsharp/FSharp.Core/seq.fs | 53 ++++---------------------- src/fsharp/FSharp.Core/seqcomposer.fs | 34 +++++++++-------- src/fsharp/FSharp.Core/seqcomposer.fsi | 6 ++- 3 files changed, 29 insertions(+), 64 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index db102da73a1..1900e68c49d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -45,19 +45,16 @@ namespace Microsoft.FSharp.Collections [] let toComposer (source:seq<'T>): Composer.Core.ISeq<'T> = Composer.Seq.toComposer source - - let inline foreach f (source:seq<_>) = - Composer.Seq.foreach f (toComposer source) let inline foreach f (source:seq<_>) = Composer.Seq.foreach f (toComposer source) let private seqFactory createSeqComponent (source:seq<'T>) = + checkNonNull "source" source match source with | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose createSeqComponent) | :? array<'T> as a -> Upcast.enumerable (Composer.Seq.Array.create a createSeqComponent) | :? list<'T> as a -> Upcast.enumerable (Composer.Seq.List.create a createSeqComponent) - | null -> nullArg "source" | _ -> Upcast.enumerable (Composer.Seq.Enumerable.create source createSeqComponent) [] @@ -98,25 +95,12 @@ namespace Microsoft.FSharp.Collections [] let item i (source : seq<'T>) = if i < 0 then invalidArgInputMustBeNonNegative "index" i else - source - |> foreach (fun halt -> - { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values<_,_,_> (0, false, Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - if this.Value._1 = i then - this.Value._2 <- true - this.Value._3 <- value - halt () - else - this.Value._1 <- this.Value._1 + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - override this.OnComplete _ = - if not this.Value._2 then - let index = i - this.Value._1 + 1 - invalidArgFmt "index" - "{0}\nseq was short by {1} {2}" - [|SR.GetString SR.notEnoughElements; index; (if index=1 then "element" else "elements")|] - }) - |> fun item -> item.Value._3 + source + |> seqFactory (Composer.Seq.SkipFactory (i, invalidArgumnetIndex)) + |> tryHead + |> function + | None -> invalidArgFmt "index" "{0}\nseq was short by 1 element" [|SR.GetString SR.notEnoughElements|] + | Some value -> value [] let tryItem i (source:seq<'T>) = @@ -185,14 +169,6 @@ namespace Microsoft.FSharp.Collections let revamp3 f (ie1 : seq<_>) (source2 : seq<_>) (source3 : seq<_>) = mkSeq (fun () -> f (ie1.GetEnumerator()) (source2.GetEnumerator()) (source3.GetEnumerator())) - let private seqFactory createSeqComponent (source:seq<'T>) = - checkNonNull "source" source - match source with - | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose createSeqComponent) - | :? array<'T> as a -> Upcast.enumerable (Composer.Seq.Array.create a createSeqComponent) - | :? list<'T> as a -> Upcast.enumerable (Composer.Seq.List.create a createSeqComponent) - | _ -> Upcast.enumerable (Composer.Seq.Enumerable.create source createSeqComponent) - [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = Composer.Seq.filter f (toComposer source) @@ -919,10 +895,6 @@ namespace Microsoft.FSharp.Collections let takeWhile p (source: seq<_>) = source |> seqFactory (Composer.Seq.TakeWhileFactory p) - [] - let skip count (source: seq<_>) = - source |> seqFactory (Composer.Seq.SkipFactory count) - [] let skipWhile p (source: seq<_>) = source |> seqFactory (Composer.Seq.SkipWhileFactory p) @@ -967,17 +939,6 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun exists -> exists.Value - [] - let tryHead (source : seq<_>) = - source - |> foreach (fun halt -> - { new Composer.Core.Folder<'T, Option<'T>> (None) with - override this.ProcessNext value = - this.Value <- Some value - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun head -> head.Value - source1 |> foreach (fun halt -> { new Composer.Core.Folder<_,bool> (false) with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 6e007722a86..f5324016f7f 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -207,10 +207,10 @@ namespace Microsoft.FSharp.Collections interface ISeqFactory<'T,'State> with member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) - and SkipFactory<'T> (count:int) = + and SkipFactory<'T> (count:int, onNotEnoughElements) = inherit SeqComponentFactory<'T,'T> () interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, next) + member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, onNotEnoughElements, next) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqComponentFactory<'T,'T> () @@ -448,7 +448,7 @@ namespace Microsoft.FSharp.Collections foldResult <- f.Invoke(foldResult, input) TailCall.avoid (next.ProcessNext foldResult) - and Skip<'T,'V> (skipCount:int, next:Consumer<'T,'V>) = + and Skip<'T,'V> (skipCount:int, notEnoughElements:string->array->unit, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(next) let mutable count = 0 @@ -470,7 +470,7 @@ namespace Microsoft.FSharp.Collections override __.OnComplete _ = if count < skipCount then let x = skipCount - count - invalidOpFmt "tried to skip {0} {1} past the end of the seq" + notEnoughElements "{0}\ntried to skip {1} {2} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] and SkipWhile<'T,'V> (predicate:'T->bool, next:Consumer<'T,'V>) = @@ -640,7 +640,7 @@ namespace Microsoft.FSharp.Collections if maybeSkipping then maybeSkipping <- isSkipping () - if (not maybeSkipping) then + if not maybeSkipping then consumer.ProcessNext (f (idx+1)) |> ignore idx <- idx + 1 @@ -1169,20 +1169,22 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore - [] - let tryItem i (source:ISeq<'T>) = - if i < 0 then None else - source + [] + let tryHead (source:ISeq<'T>) = + source |> foreach (fun halt -> - { new Folder<'T, Values>> (Values<_,_> (0, None)) with + { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = - if this.Value._1 = i then - this.Value._2 <- Some value - halt () - else - this.Value._1 <- this.Value._1 + 1 + this.Value <- Some value + halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun item -> item.Value._2 + |> fun head -> head.Value + + [] + let tryItem i (source:ISeq<'T>) = + if i < 0 then None else + source.Compose (SkipFactory(i, fun _ _ -> ())) + |> tryHead [] let iteri f (source:ISeq<'T>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 522f35b06da..e0c19da96bc 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -203,7 +203,7 @@ namespace Microsoft.FSharp.Collections class inherit SeqComponentFactory<'T,'T> interface ISeqFactory<'T,'T> - new : count:int -> SkipFactory<'T> + new : count:int * notEnoughElements:(string->array->unit) -> SkipFactory<'T> end and SkipWhileFactory<'T> = class @@ -387,7 +387,7 @@ namespace Microsoft.FSharp.Collections and Skip<'T,'V> = class inherit SeqComponent<'T,'V> - new : skipCount:int * next: Consumer<'T,'V> -> + new : skipCount:int * exceptionOnNotEnoughElements:(string->array->unit) * next: Consumer<'T,'V> -> Skip<'T,'V> override OnComplete : PipeIdx -> unit override ProcessNext : input:'T -> bool @@ -710,6 +710,8 @@ namespace Microsoft.FSharp.Collections val init : count:int -> f:(int -> 'T) -> ISeq<'T> [] val iter : f:('T -> unit) -> source: ISeq<'T> -> unit + [] + val tryHead : source: ISeq<'T> -> 'T option [] val tryItem : i:int -> source: ISeq<'T> -> 'T option [] From f8c96ad16b96a199f74c3205f7e845755d63883d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 13 Nov 2016 19:23:54 +1100 Subject: [PATCH 211/286] Starting the exposure of the inlinable Composer - Still hidden via internal module - simplified PipeIdx, no need for optional now - Made ISeqFactory an abstract class instead of interface so as not to require a stub implementation of PipeIdx in every object expression (or alternatively if the abstract class was used with the interface, then explicit declaration of the interface as well) - filter and map changed to inline versions --- src/fsharp/FSharp.Core/seq.fs | 2 +- src/fsharp/FSharp.Core/seqcomposer.fs | 330 ++++++++++--------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 204 +++++---------- 3 files changed, 197 insertions(+), 339 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 1900e68c49d..22ae6034471 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -50,11 +50,11 @@ namespace Microsoft.FSharp.Collections Composer.Seq.foreach f (toComposer source) let private seqFactory createSeqComponent (source:seq<'T>) = - checkNonNull "source" source match source with | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose createSeqComponent) | :? array<'T> as a -> Upcast.enumerable (Composer.Seq.Array.create a createSeqComponent) | :? list<'T> as a -> Upcast.enumerable (Composer.Seq.List.create a createSeqComponent) + | null -> nullArg "source" | _ -> Upcast.enumerable (Composer.Seq.Enumerable.create source createSeqComponent) [] diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index f5324016f7f..1b5340e3576 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -21,10 +21,6 @@ namespace Microsoft.FSharp.Collections module Core = type PipeIdx = int - type ``PipeIdx?`` = Nullable - let emptyPipeIdx = Nullable () - let inline getPipeIdx (maybePipeIdx:``PipeIdx?``) = if maybePipeIdx.HasValue then maybePipeIdx.Value else 1 - let inline makePipeIdx (pipeIdx:PipeIdx) = Nullable pipeIdx type ICompletionChaining = abstract OnComplete : PipeIdx -> unit @@ -84,13 +80,16 @@ namespace Microsoft.FSharp.Collections Value = init } - type ISeqFactory<'T,'U> = + [] + type SeqFactory<'T,'U> () = abstract PipeIdx : PipeIdx - abstract Create<'V> : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> + abstract Create<'V> : IOutOfBand -> PipeIdx -> Consumer<'U,'V> -> Consumer<'T,'V> + + default __.PipeIdx = 1 type ISeq<'T> = inherit IEnumerable<'T> - abstract member Compose<'U> : (ISeqFactory<'T,'U>) -> ISeq<'U> + abstract member Compose<'U> : (SeqFactory<'T,'U>) -> ISeq<'U> abstract member ForEach<'consumer when 'consumer :> Consumer<'T,'T>> : f:((unit->unit)->'consumer) -> 'consumer open Core @@ -105,152 +104,118 @@ 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:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) - let inline factory (t:#ISeqFactory<'T,'U>) : ISeqFactory<'T,'U> = (# "" t : ISeqFactory<'T,'U> #) let inline enumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) let inline enumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline enumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline iCompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) module internal Seq = - type [] SeqComponentFactory<'T,'U> (pipeIdx:``PipeIdx?``) = - new() = SeqComponentFactory<'T,'U> (emptyPipeIdx) - - interface ISeqFactory<'T,'U> with - member __.PipeIdx = getPipeIdx pipeIdx - member __.Create<'V> (_:IOutOfBand) (_:``PipeIdx?``) (_:Consumer<'U,'V>) : Consumer<'T,'V> = failwith "library implementation error: Create on base factory should not be called" + type ComposedFactory<'T,'U,'V> private (first:SeqFactory<'T,'U>, second:SeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = + inherit SeqFactory<'T,'V>() - and ComposedFactory<'T,'U,'V> private (first:ISeqFactory<'T,'U>, second:ISeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = - inherit SeqComponentFactory<'T,'V> (makePipeIdx secondPipeIdx) + override __.PipeIdx = + secondPipeIdx - interface ISeqFactory<'T,'V> with - member this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'V,'W>) : Consumer<'T,'W> = - first.Create outOfBand pipeIdx (second.Create outOfBand (makePipeIdx secondPipeIdx) next) + override this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'V,'W>) : Consumer<'T,'W> = + first.Create outOfBand pipeIdx (second.Create outOfBand secondPipeIdx next) - static member Combine (first:ISeqFactory<'T,'U>) (second:ISeqFactory<'U,'V>) : ISeqFactory<'T,'V> = - ComposedFactory(first, second, first.PipeIdx+1) |> Upcast.factory + static member Combine (first:SeqFactory<'T,'U>) (second:SeqFactory<'U,'V>) : SeqFactory<'T,'V> = + upcast ComposedFactory(first, second, first.PipeIdx+1) and ChooseFactory<'T,'U> (filter:'T->option<'U>) = - inherit SeqComponentFactory<'T,'U> () - interface ISeqFactory<'T,'U> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) + inherit SeqFactory<'T,'U> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) and DistinctFactory<'T when 'T: equality> () = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) - - and FilterFactory<'T> (filter:'T->bool) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = - match next with - | :? SeqComponent<'T,'V> as next -> upcast next.CreateFilter filter - | _ -> upcast Filter (filter, next) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) and IdentityFactory<'T> () = - inherit SeqComponentFactory<'T,'T> () - static let singleton = IdentityFactory<'T>() - interface ISeqFactory<'T,'T> with - member __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next + inherit SeqFactory<'T,'T> () + static let singleton : SeqFactory<'T,'T> = upcast (IdentityFactory<'T>()) + override __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next static member Instance = singleton - and MapFactory<'T,'U> (map:'T->'U) = - inherit SeqComponentFactory<'T,'U> () - interface ISeqFactory<'T,'U> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = - match next with - | :? SeqComponent<'U,'V> as next -> upcast next.CreateMap map - | _ -> upcast Map<_,_,_> (map, next) - and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = - inherit SeqComponentFactory<'First,'U> () - interface ISeqFactory<'First,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, outOfBand, next, getPipeIdx pipeIdx) + inherit SeqFactory<'First,'U> () + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, outOfBand, next, pipeIdx) and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = - inherit SeqComponentFactory<'Second,'U> () - interface ISeqFactory<'Second,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, outOfBand, next, getPipeIdx pipeIdx) + inherit SeqFactory<'Second,'U> () + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, outOfBand, next, pipeIdx) and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = - inherit SeqComponentFactory<'First,'U> () - interface ISeqFactory<'First,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, outOfBand, next, getPipeIdx pipeIdx) + inherit SeqFactory<'First,'U> () + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, outOfBand, next, pipeIdx) and MapiFactory<'T,'U> (mapi:int->'T->'U) = - inherit SeqComponentFactory<'T,'U> () - interface ISeqFactory<'T,'U> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) + inherit SeqFactory<'T,'U> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = - inherit SeqComponentFactory<'First,'U> () - interface ISeqFactory<'First,'U> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, outOfBand, next, getPipeIdx pipeIdx) + inherit SeqFactory<'First,'U> () + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, outOfBand, next, pipeIdx) and PairwiseFactory<'T> () = - inherit SeqComponentFactory<'T,'T*'T> () - interface ISeqFactory<'T,'T*'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) + inherit SeqFactory<'T,'T*'T> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = - inherit SeqComponentFactory<'T,'State> () - interface ISeqFactory<'T,'State> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) + inherit SeqFactory<'T,'State> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) and SkipFactory<'T> (count:int, onNotEnoughElements) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, onNotEnoughElements, next) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, onNotEnoughElements, next) and SkipWhileFactory<'T> (predicate:'T->bool) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, outOfBand, next, getPipeIdx pipeIdx) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, outOfBand, next, pipeIdx) and TakeFactory<'T> (count:int) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, getPipeIdx pipeIdx) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, pipeIdx) and TailFactory<'T> () = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = - inherit SeqComponentFactory<'T,'T> () - interface ISeqFactory<'T,'T> with - member this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:``PipeIdx?``) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, getPipeIdx pipeIdx) + inherit SeqFactory<'T,'T> () + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, pipeIdx) and WindowedFactory<'T> (windowSize:int) = - inherit SeqComponentFactory<'T, 'T[]> () - interface ISeqFactory<'T, 'T[]> with - member this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:``PipeIdx?``) (next:Consumer<'T[],'V>) : Consumer<'T,'V> = upcast Windowed (windowSize, next) - - and [] SeqComponent<'T,'U> (next:ICompletionChaining) = - inherit Consumer<'T,'U>() + inherit SeqFactory<'T, 'T[]> () + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T[],'V>) : Consumer<'T,'V> = upcast Windowed (windowSize, next) + and ISkipping = // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip // and it can only do it at the start of a sequence abstract Skipping : unit -> bool - abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U> - abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U> + and [] SeqComponentSimple<'T,'U> (next:ICompletionChaining) = + inherit Consumer<'T,'U>() + + interface ICompletionChaining with + member this.OnComplete terminatingIdx = + next.OnComplete terminatingIdx + member this.OnDispose () = + next.OnDispose () + + and [] SeqComponent<'T,'U> (next:ICompletionChaining) = + inherit Consumer<'T,'U>() interface ICompletionChaining with member this.OnComplete terminatingIdx = @@ -260,13 +225,8 @@ namespace Microsoft.FSharp.Collections try this.OnDispose () finally next.OnDispose () - default __.Skipping () = false - - default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this) - default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this) - and Choose<'T,'U,'V> (choose:'T->option<'U>, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) override __.ProcessNext (input:'T) : bool = match choose input with @@ -274,7 +234,7 @@ namespace Microsoft.FSharp.Collections | None -> false and Distinct<'T,'V when 'T: equality> (next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) @@ -285,7 +245,7 @@ namespace Microsoft.FSharp.Collections false and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) @@ -296,7 +256,7 @@ namespace Microsoft.FSharp.Collections false and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) @@ -306,36 +266,8 @@ namespace Microsoft.FSharp.Collections else false - and Filter<'T,'V> (filter:'T->bool, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) - - override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next) - - override __.ProcessNext (input:'T) : bool = - if filter input then - TailCall.avoid (next.ProcessNext input) - else - false - - and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - override __.ProcessNext (input:'T) : bool = - if filter input then - TailCall.avoid (next.ProcessNext (map input)) - else - false - - and Map<'T,'U,'V> (map:'T->'U, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next) - - override __.ProcessNext (input:'T) : bool = - TailCall.avoid (next.ProcessNext (map input)) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(next) + inherit SeqComponent<'First,'V>(Upcast.iCompletionChaining next) let input2 = enumerable2.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -351,7 +283,7 @@ namespace Microsoft.FSharp.Collections input2.Dispose () and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'Second,'V>(next) + inherit SeqComponent<'Second,'V>(Upcast.iCompletionChaining next) let input1 = enumerable1.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -367,7 +299,7 @@ namespace Microsoft.FSharp.Collections input1.Dispose () and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(next) + inherit SeqComponent<'First,'V>(Upcast.iCompletionChaining next) let input2 = enumerable2.GetEnumerator () let input3 = enumerable3.GetEnumerator () @@ -384,18 +316,8 @@ namespace Microsoft.FSharp.Collections try input2.Dispose () finally input3.Dispose () - and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) - - override __.ProcessNext (input:'T) : bool = - let u = map input - if filter u then - TailCall.avoid (next.ProcessNext u) - else - false - and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let mutable idx = 0 let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi @@ -405,7 +327,7 @@ namespace Microsoft.FSharp.Collections TailCall.avoid (next.ProcessNext (mapi'.Invoke (idx-1, input))) and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(next) + inherit SeqComponent<'First,'V>(Upcast.iCompletionChaining next) let mutable idx = 0 let input2 = enumerable2.GetEnumerator () @@ -423,7 +345,7 @@ namespace Microsoft.FSharp.Collections input2.Dispose () and Pairwise<'T,'V> (next:Consumer<'T*'T,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let mutable isFirst = true let mutable lastValue = Unchecked.defaultof<'T> @@ -439,7 +361,7 @@ namespace Microsoft.FSharp.Collections TailCall.avoid (next.ProcessNext currentPair) and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:Consumer<'State,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder let mutable foldResult = initialState @@ -449,16 +371,17 @@ namespace Microsoft.FSharp.Collections TailCall.avoid (next.ProcessNext foldResult) and Skip<'T,'V> (skipCount:int, notEnoughElements:string->array->unit, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let mutable count = 0 - override __.Skipping () = - if count < skipCount then - count <- count + 1 - true - else - false + interface ISkipping with + member __.Skipping () = + if count < skipCount then + count <- count + 1 + true + else + false override __.ProcessNext (input:'T) : bool = if count < skipCount then @@ -474,7 +397,7 @@ namespace Microsoft.FSharp.Collections [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] and SkipWhile<'T,'V> (predicate:'T->bool, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let mutable skip = true @@ -498,7 +421,7 @@ namespace Microsoft.FSharp.Collections [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] and TakeWhile<'T,'V> (predicate:'T->bool, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) override __.ProcessNext (input:'T) : bool = if predicate input then @@ -508,7 +431,7 @@ namespace Microsoft.FSharp.Collections false and Tail<'T, 'V> (next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let mutable first = true @@ -524,7 +447,7 @@ namespace Microsoft.FSharp.Collections invalidArg "source" (SR.GetString(SR.notEnoughElements)) and Truncate<'T,'V> (truncateCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let mutable count = 0 @@ -541,7 +464,7 @@ namespace Microsoft.FSharp.Collections false and Windowed<'T,'V> (windowSize: int, next:Consumer<'T[],'V>) = - inherit SeqComponent<'T,'V>(next) + inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let circularBuffer = Array.zeroCreateUnchecked windowSize let mutable idx = 0 @@ -628,8 +551,8 @@ namespace Microsoft.FSharp.Collections iterate state let makeIsSkipping (consumer:Consumer<'T,'U>) = - match consumer with - | :? SeqComponent<'T,'U> as c -> c.Skipping + match box consumer with + | :? ISkipping as skip -> skip.Skipping | _ -> fun () -> false let init f (terminatingIdx:int) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = @@ -645,10 +568,10 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 - let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:ISeqFactory<'T,'U>) executeOn = + let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:SeqFactory<'T,'U>) executeOn = let pipeline = OutOfBand() let result = f (fun () -> (pipeline:>IOutOfBand).StopFurtherProcessing (current.PipeIdx+1)) - let consumer = current.Create pipeline emptyPipeIdx result + let consumer = current.Create pipeline 0 result try executeOn pipeline consumer (Upcast.iCompletionChaining consumer).OnComplete pipeline.HaltedIdx @@ -739,16 +662,16 @@ namespace Microsoft.FSharp.Collections finally (Upcast.iCompletionChaining seqComponent).OnDispose () - and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:ISeqFactory<'T,'U>) = + and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqFactory<'T,'U>) = inherit EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result 0 (SetResult<'U> result), result)) interface ISeq<'U> with - member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = @@ -803,7 +726,7 @@ namespace Microsoft.FSharp.Collections Upcast.enumerable (AppendEnumerable (source :: sources)) interface ISeq<'T> with - member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = @@ -817,7 +740,7 @@ namespace Microsoft.FSharp.Collections Upcast.enumerator (new ConcatEnumerator<_,_> (sources)) interface ISeq<'T> with - member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = @@ -840,7 +763,7 @@ namespace Microsoft.FSharp.Collections Upcast.enumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) interface ISeq<'T> with - member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable.Enumerable<'T,'V>(this, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = @@ -880,25 +803,25 @@ namespace Microsoft.FSharp.Collections initMoveNext () moveNext () - type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:ISeqFactory<'T,'U>) = + type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Create result 0 (SetResult<'U> result), result)) interface ISeq<'U> with - member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = ForEach.execute f current (ForEach.array (delayedArray ())) - let createDelayed (delayedArray:unit->array<'T>) (current:ISeqFactory<'T,'U>) = + let createDelayed (delayedArray:unit->array<'T>) (current:SeqFactory<'T,'U>) = Upcast.seq (Enumerable(delayedArray, current)) - let create (array:array<'T>) (current:ISeqFactory<'T,'U>) = + let create (array:array<'T>) (current:SeqFactory<'T,'U>) = createDelayed (fun () -> array) current let createDelayedId (delayedArray:unit -> array<'T>) = @@ -931,16 +854,16 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext list - type Enumerable<'T,'U>(alist:list<'T>, current:ISeqFactory<'T,'U>) = + type Enumerable<'T,'U>(alist:list<'T>, current:SeqFactory<'T,'U>) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Create result 0 (SetResult<'U> result), result)) interface ISeq<'U> with - member __.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = @@ -970,16 +893,16 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:ISeqFactory<'T,'U>) = + type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:SeqFactory<'T,'U>) = 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, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result 0 (SetResult<'U> result), result)) interface ISeq<'U> with - member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = @@ -1044,16 +967,16 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:ISeqFactory<'T,'U>) = + type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqFactory<'T,'U>) = 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, current.Create result emptyPipeIdx (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(count, f, current.Create result 0 (SetResult<'U> result), result)) interface ISeq<'U> with - member this.Compose (next:ISeqFactory<'U,'V>) : ISeq<'V> = + member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) member this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = @@ -1121,7 +1044,7 @@ namespace Microsoft.FSharp.Collections upto (if count.HasValue then Some (count.Value-1) else None) f interface ISeq<'T> with - member this.Compose (next:ISeqFactory<'T,'U>) : ISeq<'U> = + member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable<'T,'V>(count, f, next)) member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = @@ -1129,17 +1052,17 @@ namespace Microsoft.FSharp.Collections [] let toComposer (source:seq<'T>) : ISeq<'T> = - checkNonNull "source" source match source with | :? ISeq<'T> as s -> s | :? array<'T> as a -> Upcast.seq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) | :? list<'T> as a -> Upcast.seq (List.Enumerable(a, IdentityFactory.Instance)) + | null -> nullArg "source" | _ -> Upcast.seq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) let inline foreach f (source:ISeq<_>) = source.ForEach f - let inline compose factory (source:ISeq<'T>) = + let inline compose (factory:#SeqFactory<_,_>) (source:ISeq<'T>) = source.Compose factory [] @@ -1234,16 +1157,23 @@ namespace Microsoft.FSharp.Collections halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun forall -> forall.Value - + [] - let filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source - |> compose (FilterFactory f) + let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { new SeqComponentSimple<'T,'V>(Upcast.iCompletionChaining next) with + member __.ProcessNext input = + if f input then TailCall.avoid (next.ProcessNext input) + else false } } [] - let map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = - source - |> compose (MapFactory f) + let inline map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = + source |> compose { new SeqFactory<'T,'U>() with + member __.Create _ _ next = + upcast { new SeqComponentSimple<'T,'V>(Upcast.iCompletionChaining next) with + member __.ProcessNext input = + TailCall.avoid (next.ProcessNext (f input)) } } [] let mapi f source = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index e0c19da96bc..b09338141b0 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -14,7 +14,6 @@ namespace Microsoft.FSharp.Collections /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the /// source of the chain. type PipeIdx = int - type ``PipeIdx?`` = Nullable /// ICompletionChaining is used to correctly handle cleaning up of the pipeline. A /// base implementation is provided in Consumer, and should not be overwritten. Consumer @@ -71,102 +70,75 @@ namespace Microsoft.FSharp.Collections new : init:'U -> Folder<'T,'U> val mutable Value: 'U - type ISeqFactory<'T,'U> = - abstract member Create : IOutOfBand -> ``PipeIdx?`` -> Consumer<'U,'V> -> Consumer<'T,'V> - abstract member PipeIdx : PipeIdx + [] + type SeqFactory<'T,'U> = + new : unit -> SeqFactory<'T,'U> + abstract PipeIdx : PipeIdx + abstract member Create : IOutOfBand -> PipeIdx -> Consumer<'U,'V> -> Consumer<'T,'V> type ISeq<'T> = inherit System.Collections.Generic.IEnumerable<'T> - abstract member Compose : ISeqFactory<'T,'U> -> ISeq<'U> + abstract member Compose : SeqFactory<'T,'U> -> ISeq<'U> abstract member ForEach : f:((unit -> unit) -> 'a) -> 'a when 'a :> Consumer<'T,'T> open Core module internal Seq = - [] - type SeqComponentFactory<'T,'U> = - class - interface ISeqFactory<'T,'U> - new : unit -> SeqComponentFactory<'T,'U> - new : pipeIdx: ``PipeIdx?`` -> - SeqComponentFactory<'T,'U> - end - and ComposedFactory<'T,'U,'V> = + type ComposedFactory<'T,'U,'V> = class - inherit SeqComponentFactory<'T,'V> - interface ISeqFactory<'T,'V> - private new : first: ISeqFactory<'T,'U> * - second: ISeqFactory<'U,'V> * + inherit SeqFactory<'T,'V> + private new : first: SeqFactory<'T,'U> * + second: SeqFactory<'U,'V> * secondPipeIdx: PipeIdx -> ComposedFactory<'T,'U,'V> static member - Combine : first: ISeqFactory<'T,'U> -> - second: ISeqFactory<'U,'V> -> - ISeqFactory<'T,'V> + Combine : first: SeqFactory<'T,'U> -> + second: SeqFactory<'U,'V> -> + SeqFactory<'T,'V> end and ChooseFactory<'T,'U> = class - inherit SeqComponentFactory<'T,'U> - interface ISeqFactory<'T,'U> + inherit SeqFactory<'T,'U> new : filter:('T -> 'U option) -> ChooseFactory<'T,'U> end and DistinctFactory<'T when 'T : equality> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : unit -> DistinctFactory<'T> end and DistinctByFactory<'T,'Key when 'Key : equality> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : keyFunction:('T -> 'Key) -> DistinctByFactory<'T,'Key> end and ExceptFactory<'T when 'T : equality> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : itemsToExclude:seq<'T> -> ExceptFactory<'T> end - and FilterFactory<'T> = - class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> - new : filter:('T -> bool) -> FilterFactory<'T> - end and IdentityFactory<'T> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : unit -> IdentityFactory<'T> - static member Instance : IdentityFactory<'T> - end - and MapFactory<'T,'U> = - class - inherit SeqComponentFactory<'T,'U> - interface ISeqFactory<'T,'U> - new : map:('T -> 'U) -> MapFactory<'T,'U> + static member Instance : SeqFactory<'T,'T> end and Map2FirstFactory<'First,'Second,'U> = class - inherit SeqComponentFactory<'First,'U> - interface ISeqFactory<'First,'U> + inherit SeqFactory<'First,'U> new : map:('First -> 'Second -> 'U) * input2:IEnumerable<'Second> -> Map2FirstFactory<'First,'Second,'U> end and Map2SecondFactory<'First,'Second,'U> = class - inherit SeqComponentFactory<'Second,'U> - interface ISeqFactory<'Second,'U> + inherit SeqFactory<'Second,'U> new : map:('First -> 'Second -> 'U) * input1:IEnumerable<'First> -> Map2SecondFactory<'First,'Second,'U> end and Map3Factory<'First,'Second,'Third,'U> = class - inherit SeqComponentFactory<'First,'U> - interface ISeqFactory<'First,'U> + inherit SeqFactory<'First,'U> new : map:('First -> 'Second -> 'Third -> 'U) * input2:IEnumerable<'Second> * input3:IEnumerable<'Third> -> @@ -174,88 +146,79 @@ namespace Microsoft.FSharp.Collections end and MapiFactory<'T,'U> = class - inherit SeqComponentFactory<'T,'U> - interface ISeqFactory<'T,'U> + inherit SeqFactory<'T,'U> new : mapi:(int -> 'T -> 'U) -> MapiFactory<'T,'U> end and Mapi2Factory<'First,'Second,'U> = class - inherit SeqComponentFactory<'First,'U> - interface ISeqFactory<'First,'U> + inherit SeqFactory<'First,'U> new : map:(int -> 'First -> 'Second -> 'U) * input2:IEnumerable<'Second> -> Mapi2Factory<'First,'Second,'U> end and PairwiseFactory<'T> = class - inherit SeqComponentFactory<'T,('T * 'T)> - interface ISeqFactory<'T,('T * 'T)> + inherit SeqFactory<'T,('T * 'T)> new : unit -> PairwiseFactory<'T> end and ScanFactory<'T,'State> = class - inherit SeqComponentFactory<'T,'State> - interface ISeqFactory<'T,'State> + inherit SeqFactory<'T,'State> new : folder:('State -> 'T -> 'State) * initialState:'State -> ScanFactory<'T,'State> end and SkipFactory<'T> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : count:int * notEnoughElements:(string->array->unit) -> SkipFactory<'T> end and SkipWhileFactory<'T> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : predicate:('T -> bool) -> SkipWhileFactory<'T> end and TakeWhileFactory<'T> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : predicate:('T -> bool) -> TakeWhileFactory<'T> end and TakeFactory<'T> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : count:int -> TakeFactory<'T> end and TailFactory<'T> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : unit -> TailFactory<'T> end and TruncateFactory<'T> = class - inherit SeqComponentFactory<'T,'T> - interface ISeqFactory<'T,'T> + inherit SeqFactory<'T,'T> new : count:int -> TruncateFactory<'T> end and WindowedFactory<'T> = class - inherit SeqComponentFactory<'T,'T []> - interface ISeqFactory<'T,'T []> + inherit SeqFactory<'T,'T []> new : windowSize:int -> WindowedFactory<'T> end + and ISkipping = + interface + abstract member Skipping : unit -> bool + end + and [] SeqComponentSimple<'T,'U> = + class + inherit Consumer<'T,'U> + interface ICompletionChaining + new : next:ICompletionChaining -> + SeqComponentSimple<'T,'U> + end and [] SeqComponent<'T,'U> = class - inherit Consumer<'T,'U> - interface ICompletionChaining - new : next: ICompletionChaining -> - SeqComponent<'T,'U> - abstract member - CreateFilter : filter:('T -> bool) -> SeqComponent<'T,'U> - abstract member - CreateMap : map:('S -> 'T) -> SeqComponent<'S,'U> - abstract member Skipping : unit -> bool - override - CreateFilter : filter:('T -> bool) -> SeqComponent<'T,'U> - override CreateMap : map:('S -> 'T) -> SeqComponent<'S,'U> - override Skipping : unit -> bool + inherit Consumer<'T,'U> + interface ICompletionChaining + new : next:ICompletionChaining -> + SeqComponent<'T,'U> end and Choose<'T,'U,'V> = class @@ -284,31 +247,6 @@ namespace Microsoft.FSharp.Collections Except<'T,'V> override ProcessNext : input:'T -> bool end - and Filter<'T,'V> = - class - inherit SeqComponent<'T,'V> - new : filter:('T -> bool) * next: Consumer<'T,'V> -> - Filter<'T,'V> - override CreateMap : map:('S -> 'T) -> SeqComponent<'S,'V> - override ProcessNext : input:'T -> bool - end - and FilterThenMap<'T,'U,'V> = - class - inherit SeqComponent<'T,'V> - new : filter:('T -> bool) * map:('T -> 'U) * - next: Consumer<'U,'V> -> - FilterThenMap<'T,'U,'V> - override ProcessNext : input:'T -> bool - end - and Map<'T,'U,'V> = - class - inherit SeqComponent<'T,'V> - new : map:('T -> 'U) * next: Consumer<'U,'V> -> - Map<'T,'U,'V> - override - CreateFilter : filter:('T -> bool) -> SeqComponent<'T,'V> - override ProcessNext : input:'T -> bool - end and Map2First<'First,'Second,'U,'V> = class inherit SeqComponent<'First,'V> @@ -343,14 +281,6 @@ namespace Microsoft.FSharp.Collections override OnDispose : unit -> unit override ProcessNext : input:'First -> bool end - and MapThenFilter<'T,'U,'V> = - class - inherit SeqComponent<'T,'V> - new : map:('T -> 'U) * filter:('U -> bool) * - next: Consumer<'U,'V> -> - MapThenFilter<'T,'U,'V> - override ProcessNext : input:'T -> bool - end and Mapi<'T,'U,'V> = class inherit SeqComponent<'T,'V> @@ -387,11 +317,11 @@ namespace Microsoft.FSharp.Collections and Skip<'T,'V> = class inherit SeqComponent<'T,'V> + interface ISkipping new : skipCount:int * exceptionOnNotEnoughElements:(string->array->unit) * next: Consumer<'T,'V> -> Skip<'T,'V> override OnComplete : PipeIdx -> unit override ProcessNext : input:'T -> bool - override Skipping : unit -> bool end and SkipWhile<'T,'V> = class @@ -492,7 +422,7 @@ namespace Microsoft.FSharp.Collections consumer: Consumer<'T,'U> -> unit val execute : f:((unit -> unit) -> 'a) -> - current: ISeqFactory<'T,'U> -> + current: SeqFactory<'T,'U> -> executeOn:( OutOfBand -> Consumer<'T,'U> -> unit) -> 'a when 'a :> Consumer<'U,'U> end @@ -546,7 +476,7 @@ namespace Microsoft.FSharp.Collections interface ISeq<'U> interface IEnumerable<'U> new : enumerable:IEnumerable<'T> * - current: ISeqFactory<'T,'U> -> + current: SeqFactory<'T,'U> -> Enumerable<'T,'U> end and ConcatEnumerator<'T,'Collection when 'Collection :> seq<'T>> = @@ -577,7 +507,7 @@ namespace Microsoft.FSharp.Collections end val create : enumerable:IEnumerable<'a> -> - current: ISeqFactory<'a,'b> -> ISeq<'b> + current: SeqFactory<'a,'b> -> ISeq<'b> end module EmptyEnumerable = begin type Enumerable<'T> = @@ -606,15 +536,15 @@ namespace Microsoft.FSharp.Collections interface ISeq<'U> interface IEnumerable<'U> new : delayedArray:(unit -> 'T array) * - current: ISeqFactory<'T,'U> -> + current: SeqFactory<'T,'U> -> Enumerable<'T,'U> end val createDelayed : delayedArray:(unit -> 'T array) -> - current: ISeqFactory<'T,'U> -> ISeq<'U> + current: SeqFactory<'T,'U> -> ISeq<'U> val create : array:'T array -> - current: ISeqFactory<'T,'U> -> ISeq<'U> + current: SeqFactory<'T,'U> -> ISeq<'U> val createDelayedId : delayedArray:(unit -> 'T array) -> ISeq<'T> val createId : array:'T array -> ISeq<'T> @@ -632,12 +562,12 @@ namespace Microsoft.FSharp.Collections inherit Enumerable.EnumerableBase<'U> interface ISeq<'U> interface IEnumerable<'U> - new : alist:'T list * current: ISeqFactory<'T,'U> -> + new : alist:'T list * current: SeqFactory<'T,'U> -> Enumerable<'T,'U> end val create : alist:'a list -> - current: ISeqFactory<'a,'b> -> ISeq<'b> + current: SeqFactory<'a,'b> -> ISeq<'b> end module Unfold = begin type Enumerator<'T,'U,'State> = @@ -655,7 +585,7 @@ namespace Microsoft.FSharp.Collections interface ISeq<'U> interface IEnumerable<'U> new : generator:('GeneratorState -> ('T * 'GeneratorState) option) * - state:'GeneratorState * current: ISeqFactory<'T,'U> -> + state:'GeneratorState * current: SeqFactory<'T,'U> -> Enumerable<'T,'U,'GeneratorState> end end @@ -675,7 +605,7 @@ namespace Microsoft.FSharp.Collections interface ISeq<'U> interface IEnumerable<'U> new : count:Nullable * f:(int -> 'T) * - current: ISeqFactory<'T,'U> -> + current: SeqFactory<'T,'U> -> Enumerable<'T,'U> end val upto : @@ -695,9 +625,6 @@ namespace Microsoft.FSharp.Collections val inline foreach : f:((unit -> unit) -> 'a) -> source: ISeq<'b> -> 'a when 'a :> Consumer<'b,'b> - val inline compose : - factory: ISeqFactory<'T,'a> -> - source: ISeq<'T> -> ISeq<'a> [] val empty<'T> : ISeq<'T> [] @@ -723,12 +650,13 @@ namespace Microsoft.FSharp.Collections element:'T -> source: ISeq<'T> -> bool when 'T : equality [] val forall : f:('T -> bool) -> source: ISeq<'T> -> bool - [] - val filter : - f:('T -> bool) -> source: ISeq<'T> -> ISeq<'T> - [] - val map : - f:('T -> 'U) -> source: ISeq<'T> -> ISeq<'U> + + [] + val inline filter : f:('T -> bool) -> source: ISeq<'T> -> ISeq<'T> + + [] + val inline map : f:('T -> 'U) -> source: ISeq<'T> -> ISeq<'U> + [] val mapi : f:(int -> 'a -> 'b) -> From b2acf147a4816009b1ebf557b096122c4753ab91 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 16 Nov 2016 19:54:50 +1100 Subject: [PATCH 212/286] Fix incorrect pipeIdx --- src/fsharp/FSharp.Core/seqcomposer.fs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 1b5340e3576..5ce74e73f5e 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -87,6 +87,8 @@ namespace Microsoft.FSharp.Collections default __.PipeIdx = 1 + member this.Build outOfBand next = this.Create outOfBand 1 next + type ISeq<'T> = inherit IEnumerable<'T> abstract member Compose<'U> : (SeqFactory<'T,'U>) -> ISeq<'U> @@ -571,7 +573,7 @@ namespace Microsoft.FSharp.Collections let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:SeqFactory<'T,'U>) executeOn = let pipeline = OutOfBand() let result = f (fun () -> (pipeline:>IOutOfBand).StopFurtherProcessing (current.PipeIdx+1)) - let consumer = current.Create pipeline 0 result + let consumer = current.Build pipeline result try executeOn pipeline consumer (Upcast.iCompletionChaining consumer).OnComplete pipeline.HaltedIdx @@ -668,7 +670,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result 0 (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Build result (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -809,7 +811,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Create result 0 (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Build result (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -860,7 +862,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Create result 0 (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Build result (SetResult<'U> result), result)) interface ISeq<'U> with member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -899,7 +901,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Create result 0 (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Build result (SetResult<'U> result), result)) interface ISeq<'U> with member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -973,7 +975,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(count, f, current.Create result 0 (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(count, f, current.Build result (SetResult<'U> result), result)) interface ISeq<'U> with member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = From c7eeb801e71f724608c8532e38417c94a9539f94 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 17 Nov 2016 19:50:07 +1100 Subject: [PATCH 213/286] Hack to stop tail calls on ICompletionChaining passing a reference as an argument in a funciton stops the F# compiler from outputting a tail instruction for that function. None of these functions will be significantly deep as to warrant the need for a tail call. --- src/fsharp/FSharp.Core/seqcomposer.fs | 48 +++++++++++++++----------- src/fsharp/FSharp.Core/seqcomposer.fsi | 4 +-- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 5ce74e73f5e..205c2b90fe1 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -23,8 +23,8 @@ namespace Microsoft.FSharp.Collections type PipeIdx = int type ICompletionChaining = - abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit + abstract OnComplete : stopTailCall:byref*PipeIdx -> unit + abstract OnDispose : stopTailCall:byref -> unit type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit @@ -40,10 +40,10 @@ namespace Microsoft.FSharp.Collections default __.OnDispose () = () interface ICompletionChaining with - member this.OnComplete terminatingIdx = + member this.OnComplete (_, terminatingIdx) = this.OnComplete terminatingIdx - member this.OnDispose () = + member this.OnDispose _ = try this.OnDispose () finally () @@ -211,21 +211,21 @@ namespace Microsoft.FSharp.Collections inherit Consumer<'T,'U>() interface ICompletionChaining with - member this.OnComplete terminatingIdx = - next.OnComplete terminatingIdx - member this.OnDispose () = - next.OnDispose () + member this.OnComplete (stopTailCall, terminatingIdx) = + next.OnComplete (&stopTailCall, terminatingIdx) + member this.OnDispose stopTailCall = + next.OnDispose (&stopTailCall) and [] SeqComponent<'T,'U> (next:ICompletionChaining) = inherit Consumer<'T,'U>() interface ICompletionChaining with - member this.OnComplete terminatingIdx = + member this.OnComplete (stopTailCall, terminatingIdx) = this.OnComplete terminatingIdx - next.OnComplete terminatingIdx - member this.OnDispose () = + next.OnComplete (&stopTailCall, terminatingIdx) + member this.OnDispose stopTailCall = try this.OnDispose () - finally next.OnDispose () + finally next.OnDispose (&stopTailCall) and Choose<'T,'U,'V> (choose:'T->option<'U>, next:Consumer<'U,'V>) = inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) @@ -576,10 +576,12 @@ namespace Microsoft.FSharp.Collections let consumer = current.Build pipeline result try executeOn pipeline consumer - (Upcast.iCompletionChaining consumer).OnComplete pipeline.HaltedIdx + let mutable stopTailCall = () + (Upcast.iCompletionChaining consumer).OnComplete (&stopTailCall, pipeline.HaltedIdx) result finally - (Upcast.iCompletionChaining consumer).OnDispose () + let mutable stopTailCall = () + (Upcast.iCompletionChaining consumer).OnDispose (&stopTailCall) module Enumerable = type Empty<'T>() = @@ -601,7 +603,8 @@ namespace Microsoft.FSharp.Collections type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ICompletionChaining) = interface IDisposable with member __.Dispose() : unit = - seqComponent.OnDispose () + let mutable stopTailCall = () + seqComponent.OnDispose (&stopTailCall) interface IEnumerator with member this.Current : obj = box ((Upcast.enumerator this)).Current @@ -649,7 +652,8 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx + let mutable stopTailCall = () + (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -662,7 +666,8 @@ namespace Microsoft.FSharp.Collections try source.Dispose () finally - (Upcast.iCompletionChaining seqComponent).OnDispose () + let mutable stopTailCall = () + (Upcast.iCompletionChaining seqComponent).OnDispose (&stopTailCall) and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqFactory<'T,'U>) = inherit EnumerableBase<'U>() @@ -797,7 +802,8 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx + let mutable stopTailCall = () + (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -848,7 +854,8 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx + let mutable stopTailCall = () + (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -961,7 +968,8 @@ namespace Microsoft.FSharp.Collections raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else result.SeqState <- SeqProcessNextStates.Finished - (Upcast.iCompletionChaining seqComponent).OnComplete result.HaltedIdx + let mutable stopTailCall = () + (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index b09338141b0..b90d832e01d 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -25,10 +25,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 OnComplete : PipeIdx -> unit + abstract OnComplete : stopTail:byref*PipeIdx -> unit /// OnDispose is used to cleanup the stream. It is always called at the last operation /// after the enumeration has completed. - abstract OnDispose : unit -> unit + abstract OnDispose : stopTail:byref -> unit type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit From 52dd69cf763d80173125f181143b5a224b4a9983 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 21 Nov 2016 19:50:23 +1100 Subject: [PATCH 214/286] mapi to inline version - added a mapi_adapt version for non-inlined --- src/fsharp/FSharp.Core/seq.fs | 5 ++- src/fsharp/FSharp.Core/seqcomposer.fs | 55 +++++++++++++++----------- src/fsharp/FSharp.Core/seqcomposer.fsi | 44 ++++++++++----------- 3 files changed, 55 insertions(+), 49 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 22ae6034471..138191226d5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -183,8 +183,9 @@ namespace Microsoft.FSharp.Collections |> Upcast.enumerable [] - let mapi f source = - Composer.Seq.mapi f (toComposer source) + let mapi f source = + let f' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f + Composer.Seq.mapi_adapt f' (toComposer source) |> Upcast.enumerable [] diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 205c2b90fe1..6ebe4e26cf8 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -20,11 +20,11 @@ namespace Microsoft.FSharp.Collections open IEnumerator module Core = - type PipeIdx = int + type PipeIdx = int type ICompletionChaining = - abstract OnComplete : stopTailCall:byref*PipeIdx -> unit - abstract OnDispose : stopTailCall:byref -> unit + abstract OnComplete : stopTailCall:byref * PipeIdx -> unit + abstract OnDispose : stopTailCall:byref -> unit type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit @@ -34,7 +34,7 @@ namespace Microsoft.FSharp.Collections abstract ProcessNext : input:'T -> bool abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit + abstract OnDispose : unit -> unit default __.OnComplete _ = () default __.OnDispose () = () @@ -158,10 +158,6 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'First,'U> () override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, outOfBand, next, pipeIdx) - and MapiFactory<'T,'U> (mapi:int->'T->'U) = - inherit SeqFactory<'T,'U> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Mapi (mapi, next) - and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = inherit SeqFactory<'First,'U> () override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, outOfBand, next, pipeIdx) @@ -216,6 +212,16 @@ namespace Microsoft.FSharp.Collections member this.OnDispose stopTailCall = next.OnDispose (&stopTailCall) + and [] SeqComponentSimpleValue<'T,'U,'Value> = + inherit SeqComponentSimple<'T,'U> + + val mutable Value : 'Value + + new (next, init) = { + inherit SeqComponentSimple<'T,'U>(next) + Value = init + } + and [] SeqComponent<'T,'U> (next:ICompletionChaining) = inherit Consumer<'T,'U>() @@ -318,16 +324,6 @@ namespace Microsoft.FSharp.Collections try input2.Dispose () finally input3.Dispose () - and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) - - let mutable idx = 0 - let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi - - override __.ProcessNext (input:'T) : bool = - idx <- idx + 1 - TailCall.avoid (next.ProcessNext (mapi'.Invoke (idx-1, input))) - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(Upcast.iCompletionChaining next) @@ -1186,9 +1182,21 @@ namespace Microsoft.FSharp.Collections TailCall.avoid (next.ProcessNext (f input)) } } [] - let mapi f source = - source - |> compose (MapiFactory f) + let inline mapi f source = + source |> compose { new SeqFactory<'T,'U>() with + member __.Create _ _ next = + upcast { new SeqComponentSimpleValue<'T,'V,int>(Upcast.iCompletionChaining next, -1) with + override this.ProcessNext (input:'T) : bool = + this.Value <- this.Value + 1 + TailCall.avoid (next.ProcessNext (f this.Value input)) } } + + let mapi_adapt (f:OptimizedClosures.FSharpFunc<_,_,_>) source = + source |> compose { new SeqFactory<'T,'U>() with + member __.Create _ _ next = + upcast { new SeqComponentSimpleValue<'T,'V,int>(Upcast.iCompletionChaining next, -1) with + override this.ProcessNext (input:'T) : bool = + this.Value <- this.Value + 1 + TailCall.avoid (next.ProcessNext (f.Invoke (this.Value, input))) } } [] let choose f source = @@ -1196,9 +1204,8 @@ namespace Microsoft.FSharp.Collections |> compose (ChooseFactory f) [] - let indexed source = - source - |> compose (MapiFactory (fun i x -> i,x)) + let inline indexed source = + mapi (fun i x -> i,x) source [] let tryPick f (source:ISeq<'T>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index b90d832e01d..c9bdf2fdb3e 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -25,10 +25,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 OnComplete : stopTail:byref*PipeIdx -> unit + abstract OnComplete : 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 OnDispose : stopTail:byref -> unit + abstract OnDispose : stopTailCall:byref -> unit type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit @@ -144,11 +144,6 @@ namespace Microsoft.FSharp.Collections input3:IEnumerable<'Third> -> Map3Factory<'First,'Second,'Third,'U> end - and MapiFactory<'T,'U> = - class - inherit SeqFactory<'T,'U> - new : mapi:(int -> 'T -> 'U) -> MapiFactory<'T,'U> - end and Mapi2Factory<'First,'Second,'U> = class inherit SeqFactory<'First,'U> @@ -206,13 +201,21 @@ namespace Microsoft.FSharp.Collections interface abstract member Skipping : unit -> bool end + and [] SeqComponentSimple<'T,'U> = class inherit Consumer<'T,'U> interface ICompletionChaining - new : next:ICompletionChaining -> - SeqComponentSimple<'T,'U> + new : next:ICompletionChaining -> SeqComponentSimple<'T,'U> end + + and [] SeqComponentSimpleValue<'T,'U,'Value> = + class + inherit SeqComponentSimple<'T,'U> + val mutable Value : 'Value + new : next:ICompletionChaining*value:'Value -> SeqComponentSimpleValue<'T,'U,'Value> + end + and [] SeqComponent<'T,'U> = class inherit Consumer<'T,'U> @@ -220,6 +223,7 @@ namespace Microsoft.FSharp.Collections new : next:ICompletionChaining -> SeqComponent<'T,'U> end + and Choose<'T,'U,'V> = class inherit SeqComponent<'T,'V> @@ -281,13 +285,6 @@ namespace Microsoft.FSharp.Collections override OnDispose : unit -> unit override ProcessNext : input:'First -> bool end - and Mapi<'T,'U,'V> = - class - inherit SeqComponent<'T,'V> - new : mapi:(int -> 'T -> 'U) * next: Consumer<'U,'V> -> - Mapi<'T,'U,'V> - override ProcessNext : input:'T -> bool - end and Mapi2<'First,'Second,'U,'V> = class inherit SeqComponent<'First,'V> @@ -658,15 +655,16 @@ namespace Microsoft.FSharp.Collections val inline map : f:('T -> 'U) -> source: ISeq<'T> -> ISeq<'U> [] - val mapi : - f:(int -> 'a -> 'b) -> - source: ISeq<'a> -> ISeq<'b> + val inline mapi : f:(int->'a->'b) -> source: ISeq<'a> -> ISeq<'b> + + val mapi_adapt : f:OptimizedClosures.FSharpFunc -> source: ISeq<'a> -> ISeq<'b> + [] - val choose : - f:('a -> 'b option) -> - source: ISeq<'a> -> ISeq<'b> + val choose : f:('a->option<'b>) -> source: ISeq<'a> -> ISeq<'b> + [] - val indexed : source: ISeq<'a> -> ISeq + val inline indexed : source: ISeq<'a> -> ISeq + [] val tryPick : f:('T -> 'U option) -> source: ISeq<'T> -> Option<'U> From dac06f83ed1f1833effe5fce51be847b42444391 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 6 Dec 2016 21:55:38 -0500 Subject: [PATCH 215/286] inline choose --- src/fsharp/FSharp.Core/seqcomposer.fs | 101 ++++++++++++------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 21 +---- 2 files changed, 52 insertions(+), 70 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 6ebe4e26cf8..854270f94d5 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -43,7 +43,7 @@ namespace Microsoft.FSharp.Collections member this.OnComplete (_, terminatingIdx) = this.OnComplete terminatingIdx - member this.OnDispose _ = + member this.OnDispose _ = try this.OnDispose () finally () @@ -94,7 +94,7 @@ namespace Microsoft.FSharp.Collections abstract member Compose<'U> : (SeqFactory<'T,'U>) -> ISeq<'U> abstract member ForEach<'consumer when 'consumer :> Consumer<'T,'T>> : f:((unit->unit)->'consumer) -> 'consumer - open Core + open Core module internal TailCall = // used for performance reasons; these are not recursive calls, so should be safe @@ -124,21 +124,17 @@ namespace Microsoft.FSharp.Collections static member Combine (first:SeqFactory<'T,'U>) (second:SeqFactory<'U,'V>) : SeqFactory<'T,'V> = upcast ComposedFactory(first, second, first.PipeIdx+1) - and ChooseFactory<'T,'U> (filter:'T->option<'U>) = - inherit SeqFactory<'T,'U> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'T,'V> = upcast Choose (filter, next) - and DistinctFactory<'T when 'T: equality> () = inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) - + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) + and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) and IdentityFactory<'T> () = inherit SeqFactory<'T,'T> () @@ -172,31 +168,31 @@ namespace Microsoft.FSharp.Collections and SkipFactory<'T> (count:int, onNotEnoughElements) = inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, onNotEnoughElements, next) + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, onNotEnoughElements, next) and SkipWhileFactory<'T> (predicate:'T->bool) = inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqFactory<'T,'T> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, outOfBand, next, pipeIdx) + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, outOfBand, next, pipeIdx) and TakeFactory<'T> (count:int) = inherit SeqFactory<'T,'T> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, pipeIdx) - + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, pipeIdx) + and TailFactory<'T> () = inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) and TruncateFactory<'T> (count:int) = inherit SeqFactory<'T,'T> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, pipeIdx) - + override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, pipeIdx) + and WindowedFactory<'T> (windowSize:int) = inherit SeqFactory<'T, 'T[]> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T[],'V>) : Consumer<'T,'V> = upcast Windowed (windowSize, next) + override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T[],'V>) : Consumer<'T,'V> = upcast Windowed (windowSize, next) and ISkipping = // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip @@ -233,20 +229,13 @@ namespace Microsoft.FSharp.Collections try this.OnDispose () finally next.OnDispose (&stopTailCall) - and Choose<'T,'U,'V> (choose:'T->option<'U>, next:Consumer<'U,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) - - override __.ProcessNext (input:'T) : bool = - match choose input with - | Some value -> TailCall.avoid (next.ProcessNext value) - | None -> false and Distinct<'T,'V when 'T: equality> (next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) - override __.ProcessNext (input:'T) : bool = + override __.ProcessNext (input:'T) : bool = if hashSet.Add input then TailCall.avoid (next.ProcessNext input) else @@ -257,7 +246,7 @@ namespace Microsoft.FSharp.Collections let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) - override __.ProcessNext (input:'T) : bool = + override __.ProcessNext (input:'T) : bool = if hashSet.Add(keyFunction input) then TailCall.avoid (next.ProcessNext input) else @@ -268,7 +257,7 @@ namespace Microsoft.FSharp.Collections let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) - override __.ProcessNext (input:'T) : bool = + override __.ProcessNext (input:'T) : bool = if cached.Value.Add input then TailCall.avoid (next.ProcessNext input) else @@ -348,7 +337,7 @@ namespace Microsoft.FSharp.Collections let mutable isFirst = true let mutable lastValue = Unchecked.defaultof<'T> - override __.ProcessNext (input:'T) : bool = + override __.ProcessNext (input:'T) : bool = if isFirst then lastValue <- input isFirst <- false @@ -381,7 +370,7 @@ namespace Microsoft.FSharp.Collections else false - override __.ProcessNext (input:'T) : bool = + override __.ProcessNext (input:'T) : bool = if count < skipCount then count <- count + 1 false @@ -399,7 +388,7 @@ namespace Microsoft.FSharp.Collections let mutable skip = true - override __.ProcessNext (input:'T) : bool = + override __.ProcessNext (input:'T) : bool = if skip then skip <- predicate input if skip then @@ -421,7 +410,7 @@ namespace Microsoft.FSharp.Collections and TakeWhile<'T,'V> (predicate:'T->bool, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) - override __.ProcessNext (input:'T) : bool = + override __.ProcessNext (input:'T) : bool = if predicate input then TailCall.avoid (next.ProcessNext input) else @@ -451,7 +440,7 @@ namespace Microsoft.FSharp.Collections member __.Count = count - override __.ProcessNext (input:'T) : bool = + override __.ProcessNext (input:'T) : bool = if count < truncateCount then count <- count + 1 if count = truncateCount then @@ -471,7 +460,7 @@ namespace Microsoft.FSharp.Collections override __.ProcessNext (input:'T) : bool = circularBuffer.[idx] <- input - + idx <- idx + 1 if idx = windowSize then idx <- 0 @@ -484,7 +473,7 @@ namespace Microsoft.FSharp.Collections let window = Array.init windowSize (fun i -> circularBuffer.[(idx+i) % windowSize]) TailCall.avoid (next.ProcessNext window) else - let window = Array.zeroCreateUnchecked windowSize + 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) @@ -496,7 +485,7 @@ namespace Microsoft.FSharp.Collections type Result<'T>() = let mutable haltedIdx = 0 - + member val Current = Unchecked.defaultof<'T> with get, set member val SeqState = SeqProcessNextStates.NotStarted with get, set member __.HaltedIdx = haltedIdx @@ -538,14 +527,14 @@ namespace Microsoft.FSharp.Collections | _ -> () iterate alist - let unfold (generator:'S->option<'T*'S>) state (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + let unfold (generator:'S->option<'T*'S>) state (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = let rec iterate current = match outOfBand.HaltedIdx, generator current with | 0, Some (item, next) -> consumer.ProcessNext item |> ignore iterate next | _ -> () - + iterate state let makeIsSkipping (consumer:Consumer<'T,'U>) = @@ -591,7 +580,7 @@ namespace Microsoft.FSharp.Collections interface IDisposable with member __.Dispose () = () - type EmptyEnumerators<'T>() = + type EmptyEnumerators<'T>() = static let element : IEnumerator<'T> = upcast (new Empty<'T> ()) static member Element = element @@ -842,7 +831,7 @@ namespace Microsoft.FSharp.Collections let rec moveNext current = match result.HaltedIdx, current with - | 0, head::tail -> + | 0, head::tail -> if seqComponent.ProcessNext head then list <- tail true @@ -953,7 +942,7 @@ namespace Microsoft.FSharp.Collections // 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 seqComponent.ProcessNext (f idx) then @@ -1057,7 +1046,7 @@ namespace Microsoft.FSharp.Collections ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (Upcast.enumerable this)) [] - let toComposer (source:seq<'T>) : ISeq<'T> = + let toComposer (source:seq<'T>) : ISeq<'T> = match source with | :? ISeq<'T> as s -> s | :? array<'T> as a -> Upcast.seq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) @@ -1113,7 +1102,7 @@ namespace Microsoft.FSharp.Collections let tryItem i (source:ISeq<'T>) = if i < 0 then None else source.Compose (SkipFactory(i, fun _ _ -> ())) - |> tryHead + |> tryHead [] let iteri f (source:ISeq<'T>) = @@ -1163,13 +1152,13 @@ namespace Microsoft.FSharp.Collections halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun forall -> forall.Value - + [] let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = upcast { new SeqComponentSimple<'T,'V>(Upcast.iCompletionChaining next) with - member __.ProcessNext input = + member __.ProcessNext input = if f input then TailCall.avoid (next.ProcessNext input) else false } } @@ -1178,7 +1167,7 @@ namespace Microsoft.FSharp.Collections source |> compose { new SeqFactory<'T,'U>() with member __.Create _ _ next = upcast { new SeqComponentSimple<'T,'V>(Upcast.iCompletionChaining next) with - member __.ProcessNext input = + member __.ProcessNext input = TailCall.avoid (next.ProcessNext (f input)) } } [] @@ -1186,7 +1175,7 @@ namespace Microsoft.FSharp.Collections source |> compose { new SeqFactory<'T,'U>() with member __.Create _ _ next = upcast { new SeqComponentSimpleValue<'T,'V,int>(Upcast.iCompletionChaining next, -1) with - override this.ProcessNext (input:'T) : bool = + override this.ProcessNext (input:'T) : bool = this.Value <- this.Value + 1 TailCall.avoid (next.ProcessNext (f this.Value input)) } } @@ -1194,14 +1183,20 @@ namespace Microsoft.FSharp.Collections source |> compose { new SeqFactory<'T,'U>() with member __.Create _ _ next = upcast { new SeqComponentSimpleValue<'T,'V,int>(Upcast.iCompletionChaining next, -1) with - override this.ProcessNext (input:'T) : bool = + override this.ProcessNext (input:'T) : bool = this.Value <- this.Value + 1 TailCall.avoid (next.ProcessNext (f.Invoke (this.Value, input))) } } [] - let choose f source = - source - |> compose (ChooseFactory f) + let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = + source |> compose { new SeqFactory<'T,'U>() with + member __.Create _ _ next = + upcast { new SeqComponentSimple<'T,'V>(Upcast.iCompletionChaining next) with + member __.ProcessNext input = + match f input with + | Some value -> TailCall.avoid (next.ProcessNext value) + | None -> false } } + [] let inline indexed source = @@ -1223,7 +1218,7 @@ namespace Microsoft.FSharp.Collections [] let tryFind f (source:ISeq<'T>) = - source + source |> foreach (fun halt -> { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index c9bdf2fdb3e..8b80ef4ab22 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -10,7 +10,7 @@ namespace Microsoft.FSharp.Collections [] module Composer = - module Core = + module Core = /// PipeIdx denotes the index of the element within the pipeline. 0 denotes the /// source of the chain. type PipeIdx = int @@ -20,7 +20,7 @@ namespace Microsoft.FSharp.Collections /// provides it's own OnComplete and OnDispose function which should be used to handle /// a particular consumers cleanup. type ICompletionChaining = - /// 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 @@ -96,11 +96,6 @@ namespace Microsoft.FSharp.Collections second: SeqFactory<'U,'V> -> SeqFactory<'T,'V> end - and ChooseFactory<'T,'U> = - class - inherit SeqFactory<'T,'U> - new : filter:('T -> 'U option) -> ChooseFactory<'T,'U> - end and DistinctFactory<'T when 'T : equality> = class inherit SeqFactory<'T,'T> @@ -223,14 +218,6 @@ namespace Microsoft.FSharp.Collections new : next:ICompletionChaining -> SeqComponent<'T,'U> end - - and Choose<'T,'U,'V> = - class - inherit SeqComponent<'T,'V> - new : choose:('T -> 'U option) * next: Consumer<'U,'V> -> - Choose<'T,'U,'V> - override ProcessNext : input:'T -> bool - end and Distinct<'T,'V when 'T : equality> = class inherit SeqComponent<'T,'V> @@ -647,13 +634,13 @@ namespace Microsoft.FSharp.Collections element:'T -> source: ISeq<'T> -> bool when 'T : equality [] val forall : f:('T -> bool) -> source: ISeq<'T> -> 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> From baada875d7ffa1b1361280e22ea3cb10a82a903b Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 6 Dec 2016 23:09:58 -0500 Subject: [PATCH 216/286] convert distinct --- src/fsharp/FSharp.Core/seq.fs | 53 ++++--- src/fsharp/FSharp.Core/seq.fsi | 190 ++++++++++++------------- src/fsharp/FSharp.Core/seqcomposer.fs | 15 -- src/fsharp/FSharp.Core/seqcomposer.fsi | 26 ++-- 4 files changed, 140 insertions(+), 144 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 138191226d5..157c50d75c2 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -13,6 +13,9 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Core.CompilerServices open Microsoft.FSharp.Control open Microsoft.FSharp.Collections + open Microsoft.FSharp.Collections.Composer + open Microsoft.FSharp.Collections.Composer.Core + open Microsoft.FSharp.Collections.Composer.Seq open Microsoft.FSharp.Primitives.Basics open Microsoft.FSharp.Collections.IEnumerator @@ -41,22 +44,22 @@ namespace Microsoft.FSharp.Collections #endif let mkDelayedSeq (f: unit -> IEnumerable<'T>) = mkSeq (fun () -> f().GetEnumerator()) let inline indexNotFound() = raise (new System.Collections.Generic.KeyNotFoundException(SR.GetString(SR.keyNotFoundAlt))) - + [] - let toComposer (source:seq<'T>): Composer.Core.ISeq<'T> = + let toComposer (source:seq<'T>): Composer.Core.ISeq<'T> = Composer.Seq.toComposer source let inline foreach f (source:seq<_>) = Composer.Seq.foreach f (toComposer source) - let private seqFactory createSeqComponent (source:seq<'T>) = + let inline seqFactory (createSeqComponent:#SeqFactory<_,_>) (source:seq<'T>) = match source with | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose createSeqComponent) | :? array<'T> as a -> Upcast.enumerable (Composer.Seq.Array.create a createSeqComponent) | :? list<'T> as a -> Upcast.enumerable (Composer.Seq.List.create a createSeqComponent) | null -> nullArg "source" | _ -> Upcast.enumerable (Composer.Seq.Enumerable.create source createSeqComponent) - + [] let delay f = mkDelayedSeq f @@ -339,7 +342,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- f.Invoke (this.Value._2, value) Unchecked.defaultof<_> (* return value unsed in ForEach context *) - member this.OnComplete _ = + member this.OnComplete _ = if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) @@ -387,7 +390,7 @@ namespace Microsoft.FSharp.Collections this.Value <- c halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) - member this.OnComplete _ = + member this.OnComplete _ = if this.Value = 0 && e2.MoveNext() then this.Value <- -1 }) |> fun compare -> compare.Value @@ -524,7 +527,7 @@ namespace Microsoft.FSharp.Collections let windowed windowSize (source: seq<_>) = if windowSize <= 0 then invalidArgFmt "windowSize" "{0}\nwindowSize = {1}" [|SR.GetString SR.inputMustBePositive; windowSize|] - source |> seqFactory (Composer.Seq.WindowedFactory (windowSize)) + source |> seqFactory (Composer.Seq.WindowedFactory (windowSize)) [] let cache (source : seq<'T>) = @@ -642,7 +645,13 @@ namespace Microsoft.FSharp.Collections [] let distinct source = - source |> seqFactory (Composer.Seq.DistinctFactory ()) + source |> seqFactory { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { new SeqComponentSimpleValue<'T,'V,HashSet<'T>> + (Upcast.iCompletionChaining next,(HashSet<'T>(HashIdentity.Structural<'T>))) with + override this.ProcessNext (input:'T) : bool = + if this.Value.Add input then TailCall.avoid (next.ProcessNext input) + else false } } [] let distinctBy keyf source = @@ -719,7 +728,7 @@ namespace Microsoft.FSharp.Collections #endif then mkDelayedSeq (fun () -> countByValueType keyf source) else mkDelayedSeq (fun () -> countByRefType keyf source) - + [] let inline sum (source:seq<'a>) : 'a = source @@ -750,7 +759,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- this.Value._2 + 1 Unchecked.defaultof<_> (* return value unsed in ForEach context *) - member this.OnComplete _ = + member this.OnComplete _ = if this.Value._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun total -> LanguagePrimitives.DivideByInt< ^a> total.Value._1 total.Value._2 @@ -765,7 +774,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- this.Value._2 + 1 Unchecked.defaultof<_> (* return value unsed in ForEach context *) - member this.OnComplete _ = + member this.OnComplete _ = if this.Value._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.Value._1 total.Value._2 @@ -788,7 +797,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value Unchecked.defaultof<_> (* return value unsed in ForEach context *) - member this.OnComplete _ = + member this.OnComplete _ = if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) @@ -811,7 +820,7 @@ namespace Microsoft.FSharp.Collections | _ -> () Unchecked.defaultof<_> (* return value unsed in ForEach context *) - member this.OnComplete _ = + member this.OnComplete _ = if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) @@ -846,7 +855,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- value Unchecked.defaultof<_> (* return value unsed in ForEach context *) - member this.OnComplete _ = + member this.OnComplete _ = if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) @@ -869,7 +878,7 @@ namespace Microsoft.FSharp.Collections | _ -> () Unchecked.defaultof<_> (* return value unsed in ForEach context *) - member this.OnComplete _ = + member this.OnComplete _ = if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) @@ -939,7 +948,7 @@ namespace Microsoft.FSharp.Collections halt() Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun exists -> exists.Value - + source1 |> foreach (fun halt -> { new Composer.Core.Folder<_,bool> (false) with @@ -962,7 +971,7 @@ namespace Microsoft.FSharp.Collections [] let tail (source: seq<'T>) = source |> seqFactory (Composer.Seq.TailFactory ()) - + [] let tryLast (source : seq<_>) = source @@ -973,7 +982,7 @@ namespace Microsoft.FSharp.Collections this.Value._1 <- false this.Value._2 <- value Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun tried -> + |> fun tried -> if tried.Value._1 then None else @@ -997,9 +1006,9 @@ namespace Microsoft.FSharp.Collections else this.Value._3 <- true halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) - member this.OnComplete _ = + member this.OnComplete _ = if this.Value._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString elif this.Value._3 then @@ -1016,8 +1025,8 @@ namespace Microsoft.FSharp.Collections [] let rev source = checkNonNull "source" source - let delayedReverse () = - let array = source |> toArray + let delayedReverse () = + let array = source |> toArray Array.Reverse array array Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedReverse) diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index f06c676e4de..76ca68bb866 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -7,12 +7,12 @@ namespace Microsoft.FSharp.Collections open System.Collections.Generic open Microsoft.FSharp.Core open Microsoft.FSharp.Collections - + /// Basic operations on IEnumerables. [] [] - module Seq = + module Seq = /// Returns a new sequence that contains the cartesian product of the two input sequences. /// The first sequence. /// The second sequence. @@ -24,7 +24,7 @@ namespace Microsoft.FSharp.Collections /// Wraps the two given enumerations as a single concatenated /// enumeration. /// - /// The returned sequence may be passed between threads safely. However, + /// The returned sequence may be passed between threads safely. However, /// individual IEnumerator values generated from the returned sequence should not be accessed /// concurrently. /// @@ -36,11 +36,11 @@ namespace Microsoft.FSharp.Collections /// Thrown when either of the two provided sequences is /// null. [] - val append: source1:seq<'T> -> source2:seq<'T> -> seq<'T> + val append: source1:seq<'T> -> source2:seq<'T> -> seq<'T> /// Returns the average of the elements in the sequence. /// - /// The elements are averaged using the + operator, DivideByInt method and Zero property + /// The elements are averaged using the + operator, DivideByInt method and Zero property /// associated with the element type. /// /// The input sequence. @@ -50,15 +50,15 @@ namespace Microsoft.FSharp.Collections /// Thrown when the input sequence is null. /// Thrown when the input sequence has zero elements. [] - val inline average : source:seq<(^T)> -> ^T - when ^T : (static member ( + ) : ^T * ^T -> ^T) - and ^T : (static member DivideByInt : ^T * int -> ^T) + val inline average : source:seq<(^T)> -> ^T + when ^T : (static member ( + ) : ^T * ^T -> ^T) + and ^T : (static member DivideByInt : ^T * int -> ^T) and ^T : (static member Zero : ^T) - /// Returns the average of the results generated by applying the function to each element + /// Returns the average of the results generated by applying the function to each element /// of the sequence. /// - /// The elements are averaged using the + operator, DivideByInt method and Zero property + /// The elements are averaged using the + operator, DivideByInt method and Zero property /// associated with the generated type. /// /// A function applied to transform each element of the sequence. @@ -69,29 +69,29 @@ namespace Microsoft.FSharp.Collections /// Thrown when the input sequence is null. /// Thrown when the input sequence has zero elements. [] - val inline averageBy : projection:('T -> ^U) -> source:seq<'T> -> ^U - when ^U : (static member ( + ) : ^U * ^U -> ^U) - and ^U : (static member DivideByInt : ^U * int -> ^U) + val inline averageBy : projection:('T -> ^U) -> source:seq<'T> -> ^U + when ^U : (static member ( + ) : ^U * ^U -> ^U) + and ^U : (static member DivideByInt : ^U * int -> ^U) and ^U : (static member Zero : ^U) /// Returns a sequence that corresponds to a cached version of the input sequence. - /// This result sequence will have the same elements as the input sequence. The result - /// can be enumerated multiple times. The input sequence will be enumerated at most + /// This result sequence will have the same elements as the input sequence. The result + /// can be enumerated multiple times. The input sequence will be enumerated at most /// once and only as far as is necessary. Caching a sequence is typically useful when repeatedly /// evaluating items in the original sequence is computationally expensive or if /// iterating the sequence causes side-effects that the user does not want to be /// repeated multiple times. /// /// Enumeration of the result sequence is thread safe in the sense that multiple independent IEnumerator - /// values may be used simultaneously from different threads (accesses to + /// values may be used simultaneously from different threads (accesses to /// the internal lookaside table are thread safe). Each individual IEnumerator /// is not typically thread safe and should not be accessed concurrently. /// /// Once enumeration of the input sequence has started, /// it's enumerator will be kept live by this object until the enumeration has completed. - /// At that point, the enumerator will be disposed. + /// At that point, the enumerator will be disposed. /// - /// The enumerator may be disposed and underlying cache storage released by + /// The enumerator may be disposed and underlying cache storage released by /// converting the returned sequence object to type IDisposable, and calling the Dispose method /// on this object. The sequence object may then be re-enumerated and a fresh enumerator will /// be used. @@ -110,7 +110,7 @@ namespace Microsoft.FSharp.Collections /// An incorrect type annotation may result in runtime type /// errors. /// Individual IEnumerator values generated from the returned sequence should not be accessed concurrently. - /// + /// /// The input sequence. /// /// The result sequence. @@ -123,7 +123,7 @@ namespace Microsoft.FSharp.Collections /// the list comprised of the results "x" for each element where /// the function returns Some(x). /// - /// The returned sequence may be passed between threads safely. However, + /// The returned sequence may be passed between threads safely. However, /// individual IEnumerator values generated from the returned sequence should not /// be accessed concurrently. /// @@ -131,7 +131,7 @@ namespace Microsoft.FSharp.Collections /// The input sequence of type T. /// /// The result sequence. - /// + /// /// Thrown when the input sequence is null. [] val choose: chooser:('T -> 'U option) -> source:seq<'T> -> seq<'U> @@ -179,7 +179,7 @@ namespace Microsoft.FSharp.Collections /// Combines the given enumeration-of-enumerations as a single concatenated /// enumeration. /// - /// The returned sequence may be passed between threads safely. However, + /// The returned sequence may be passed between threads safely. However, /// individual IEnumerator values generated from the returned sequence should not be accessed concurrently. /// /// The input enumeration-of-enumerations. @@ -200,10 +200,10 @@ namespace Microsoft.FSharp.Collections /// Applies a key-generating function to each element of a sequence and returns a sequence yielding unique /// keys and their number of occurrences in the original sequence. - /// - /// Note that this function returns a sequence that digests the whole initial sequence as soon as - /// that sequence is iterated. As a result this function should not be used with - /// large or infinite sequences. The function makes no assumption on the ordering of the original + /// + /// Note that this function returns a sequence that digests the whole initial sequence as soon as + /// that sequence is iterated. As a result this function should not be used with + /// large or infinite sequences. The function makes no assumption on the ordering of the original /// sequence. /// /// A function transforming each item of the input sequence into a key to be @@ -219,7 +219,7 @@ namespace Microsoft.FSharp.Collections /// Returns a sequence that is built from the given delayed specification of a /// sequence. /// - /// The input function is evaluated each time an IEnumerator for the sequence + /// The input function is evaluated each time an IEnumerator for the sequence /// is requested. /// /// The generating function for the sequence. @@ -238,7 +238,7 @@ namespace Microsoft.FSharp.Collections [] val distinct: source:seq<'T> -> seq<'T> when 'T : equality - /// Returns a sequence that contains no duplicate entries according to the + /// Returns a sequence that contains no duplicate entries according to the /// generic hash and equality comparisons on the keys returned by the given key-generating function. /// If an element occurs multiple times in the sequence then the later occurrences are discarded. /// @@ -290,8 +290,8 @@ namespace Microsoft.FSharp.Collections /// Tests if any element of the sequence satisfies the given predicate. /// - /// The predicate is applied to the elements of the input sequence. If any application - /// returns true then the overall result is true and no further elements are tested. + /// The predicate is applied to the elements of the input sequence. If any application + /// returns true then the overall result is true and no further elements are tested. /// Otherwise, false is returned. /// /// A function to test each item of the input sequence. @@ -305,9 +305,9 @@ namespace Microsoft.FSharp.Collections /// Tests if any pair of corresponding elements of the input sequences satisfies the given predicate. /// - /// The predicate is applied to matching elements in the two sequences up to the lesser of the - /// two lengths of the collections. If any application returns true then the overall result is - /// true and no further elements are tested. Otherwise, false is returned. If one sequence is shorter than + /// The predicate is applied to matching elements in the two sequences up to the lesser of the + /// two lengths of the collections. If any application returns true then the overall result is + /// true and no further elements are tested. Otherwise, false is returned. If one sequence is shorter than /// the other then the remaining elements of the longer sequence are ignored. /// /// A function to test each pair of items from the input sequences. @@ -323,7 +323,7 @@ namespace Microsoft.FSharp.Collections /// Returns a new collection containing only the elements of the collection /// for which the given predicate returns "true". This is a synonym for Seq.where. /// - /// The returned sequence may be passed between threads safely. However, + /// The returned sequence may be passed between threads safely. However, /// individual IEnumerator values generated from the returned sequence should not be accessed concurrently. /// /// Remember sequence is lazy, effects are delayed until it is enumerated. @@ -333,18 +333,18 @@ namespace Microsoft.FSharp.Collections /// /// The result sequence. /// - /// Thrown when the input sequence is null. + /// Thrown when the input sequence is null. [] val filter: predicate:('T -> bool) -> source:seq<'T> -> seq<'T> /// Returns a new collection containing only the elements of the collection /// for which the given predicate returns "true". /// - /// The returned sequence may be passed between threads safely. However, + /// The returned sequence may be passed between threads safely. However, /// individual IEnumerator values generated from the returned sequence should not be accessed concurrently. /// /// Remember sequence is lazy, effects are delayed until it is enumerated. - /// + /// /// A synonym for Seq.filter. /// /// A function to test whether each item in the input sequence should be included in the output. @@ -352,7 +352,7 @@ namespace Microsoft.FSharp.Collections /// /// The result sequence. /// - /// Thrown when the input sequence is null. + /// Thrown when the input sequence is null. [] val where: predicate:('T -> bool) -> source:seq<'T> -> seq<'T> @@ -409,7 +409,7 @@ namespace Microsoft.FSharp.Collections val findIndexBack: predicate:('T -> bool) -> source:seq<'T> -> int /// Applies a function to each element of the collection, threading an accumulator argument - /// through the computation. If the input function is f and the elements are i0...iN + /// through the computation. If the input function is f and the elements are i0...iN /// then computes f (... (f s i0)...) iN /// /// A function that updates the state with each element from the sequence. @@ -463,8 +463,8 @@ namespace Microsoft.FSharp.Collections /// Tests if all elements of the sequence satisfy the given predicate. /// - /// The predicate is applied to the elements of the input sequence. If any application - /// returns false then the overall result is false and no further elements are tested. + /// The predicate is applied to the elements of the input sequence. If any application + /// returns false then the overall result is false and no further elements are tested. /// Otherwise, true is returned. /// /// A function to test an element of the input sequence. @@ -477,7 +477,7 @@ namespace Microsoft.FSharp.Collections val forall: predicate:('T -> bool) -> source:seq<'T> -> bool /// Tests the all pairs of elements drawn from the two sequences satisfy the - /// given predicate. If one sequence is shorter than + /// given predicate. If one sequence is shorter than /// the other then the remaining elements of the longer sequence are ignored. /// /// A function to test pairs of elements from the input sequences. @@ -490,13 +490,13 @@ namespace Microsoft.FSharp.Collections [] val forall2: predicate:('T1 -> 'T2 -> bool) -> source1:seq<'T1> -> source2:seq<'T2> -> bool - /// Applies a key-generating function to each element of a sequence and yields a sequence of - /// unique keys. Each unique key contains a sequence of all elements that match + /// Applies a key-generating function to each element of a sequence and yields a sequence of + /// unique keys. Each unique key contains a sequence of all elements that match /// to this key. - /// - /// This function returns a sequence that digests the whole initial sequence as soon as - /// that sequence is iterated. As a result this function should not be used with - /// large or infinite sequences. The function makes no assumption on the ordering of the original + /// + /// This function returns a sequence that digests the whole initial sequence as soon as + /// that sequence is iterated. As a result this function should not be used with + /// large or infinite sequences. The function makes no assumption on the ordering of the original /// sequence. /// /// A function that transforms an element of the sequence into a comparable key. @@ -580,7 +580,7 @@ namespace Microsoft.FSharp.Collections /// initialization. The function is passed the index of the item being /// generated. /// - /// The returned sequence may be passed between threads safely. However, + /// The returned sequence may be passed between threads safely. However, /// individual IEnumerator values generated from the returned sequence should not be accessed concurrently. /// /// The maximum number of items to generate for the sequence. @@ -591,14 +591,14 @@ namespace Microsoft.FSharp.Collections /// Thrown when count is negative. [] val init: count:int -> initializer:(int -> 'T) -> seq<'T> - + /// Generates a new sequence which, when iterated, will return successive /// elements by calling the given function. The results of calling the function /// will not be saved, that is the function will be reapplied as necessary to /// regenerate the elements. The function is passed the index of the item being /// generated. /// - /// The returned sequence may be passed between threads safely. However, + /// The returned sequence may be passed between threads safely. However, /// individual IEnumerator values generated from the returned sequence should not be accessed concurrently. /// Iteration can continue up to Int32.MaxValue. /// @@ -636,7 +636,7 @@ namespace Microsoft.FSharp.Collections [] val iteri: action:(int -> 'T -> unit) -> source:seq<'T> -> unit - /// Applies the given function to two collections simultaneously. If one sequence is shorter than + /// Applies the given function to two collections simultaneously. If one sequence is shorter than /// the other then the remaining elements of the longer sequence are ignored. /// /// A function to apply to each pair of elements from the input sequences. @@ -647,7 +647,7 @@ namespace Microsoft.FSharp.Collections [] val iter2: action:('T1 -> 'T2 -> unit) -> source1:seq<'T1> -> source2:seq<'T2> -> unit - /// Applies the given function to two collections simultaneously. If one sequence is shorter than + /// Applies the given function to two collections simultaneously. If one sequence is shorter than /// the other then the remaining elements of the longer sequence are ignored. The integer passed to the /// function indicates the index of element. /// @@ -674,7 +674,7 @@ namespace Microsoft.FSharp.Collections /// as elements are demanded using the MoveNext method on enumerators retrieved from the /// object. /// - /// The returned sequence may be passed between threads safely. However, + /// The returned sequence may be passed between threads safely. However, /// individual IEnumerator values generated from the returned sequence should not be accessed concurrently. /// /// A function to transform items from the input sequence. @@ -687,7 +687,7 @@ namespace Microsoft.FSharp.Collections val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U> /// Builds a new collection whose elements are the results of applying the given function - /// to the corresponding pairs of elements from the two sequences. If one input sequence is shorter than + /// to the corresponding pairs of elements from the two sequences. If one input sequence is shorter than /// the other then the remaining elements of the longer sequence are ignored. /// /// A function to transform pairs of items from the input sequences. @@ -755,7 +755,7 @@ namespace Microsoft.FSharp.Collections val mapi: mapping:(int -> 'T -> 'U) -> source:seq<'T> -> seq<'U> /// Builds a new collection whose elements are the results of applying the given function - /// to the corresponding pairs of elements from the two sequences. If one input sequence is shorter than + /// to the corresponding pairs of elements from the two sequences. If one input sequence is shorter than /// the other then the remaining elements of the longer sequence are ignored. The integer index passed to the /// function indicates the index (from 0) of element being transformed. /// @@ -778,7 +778,7 @@ namespace Microsoft.FSharp.Collections /// /// The largest element of the sequence. [] - val inline max : source:seq<'T> -> 'T when 'T : comparison + val inline max : source:seq<'T> -> 'T when 'T : comparison /// Returns the greatest of all elements of the sequence, compared via Operators.max on the function result. /// @@ -790,7 +790,7 @@ namespace Microsoft.FSharp.Collections /// Thrown when the input sequence is null. /// Thrown when the input sequence is empty. [] - val inline maxBy : projection:('T -> 'U) -> source:seq<'T> -> 'T when 'U : comparison + val inline maxBy : projection:('T -> 'U) -> source:seq<'T> -> 'T when 'U : comparison (* /// Returns the greatest function result from the elements of the sequence, compared via Operators.max. @@ -803,7 +803,7 @@ namespace Microsoft.FSharp.Collections /// Thrown when the input sequence is null. /// Thrown when the input sequence is empty. [] - val inline maxValBy : projection:('T -> 'U) -> source:seq<'T> -> 'U when 'U : comparison + val inline maxValBy : projection:('T -> 'U) -> source:seq<'T> -> 'U when 'U : comparison *) /// Returns the lowest of all elements of the sequence, compared via Operators.min. @@ -815,7 +815,7 @@ namespace Microsoft.FSharp.Collections /// Thrown when the input sequence is null. /// Thrown when the input sequence is empty. [] - val inline min : source:seq<'T> -> 'T when 'T : comparison + val inline min : source:seq<'T> -> 'T when 'T : comparison /// Returns the lowest of all elements of the sequence, compared via Operators.min on the function result. /// @@ -827,7 +827,7 @@ namespace Microsoft.FSharp.Collections /// Thrown when the input sequence is null. /// Thrown when the input sequence is empty. [] - val inline minBy : projection:('T -> 'U) -> source:seq<'T> -> 'T when 'U : comparison + val inline minBy : projection:('T -> 'U) -> source:seq<'T> -> 'T when 'U : comparison (* /// Returns the lowest function result from the elements of the sequence, compared via Operators.max. @@ -840,7 +840,7 @@ namespace Microsoft.FSharp.Collections /// Thrown when the input sequence is null. /// Thrown when the input sequence is empty. [] - val inline minValBy : projection:('T -> 'U) -> source:seq<'T> -> 'U when 'U : comparison + val inline minValBy : projection:('T -> 'U) -> source:seq<'T> -> 'U when 'U : comparison *) /// Computes the nth element in the collection. @@ -916,10 +916,10 @@ namespace Microsoft.FSharp.Collections /// Thrown when every item of the sequence /// evaluates to None when the given function is applied. [] - val pick: chooser:('T -> 'U option) -> source:seq<'T> -> 'U + val pick: chooser:('T -> 'U option) -> source:seq<'T> -> 'U - /// Builds a new sequence object that delegates to the given sequence object. This ensures - /// the original sequence cannot be rediscovered and mutated by a type cast. For example, + /// Builds a new sequence object that delegates to the given sequence object. This ensures + /// the original sequence cannot be rediscovered and mutated by a type cast. For example, /// if given an array the returned sequence will return the elements of the array, but /// you cannot cast the returned sequence object to an array. /// @@ -933,7 +933,7 @@ namespace Microsoft.FSharp.Collections /// Applies a function to each element of the sequence, threading an accumulator argument /// through the computation. Begin by applying the function to the first two elements. - /// Then feed this result into the function along with the third element and so on. + /// Then feed this result into the function along with the third element and so on. /// Return the final result. /// /// A function that takes in the current accumulated result and the next @@ -955,7 +955,7 @@ namespace Microsoft.FSharp.Collections val replicate: count:int -> initial:'T -> seq<'T> /// Applies a function to each element of the sequence, starting from the end, threading an accumulator argument - /// through the computation. If the input function is f and the elements are i0...iN + /// through the computation. If the input function is f and the elements are i0...iN /// then computes f i0 (...(f iN-1 iN)). /// A function that takes in the next-to-last element of the sequence and the /// current accumulated result to produce the next accumulated result. @@ -1022,7 +1022,7 @@ namespace Microsoft.FSharp.Collections [] val skip: count:int -> source:seq<'T> -> seq<'T> - /// Returns a sequence that, when iterated, skips elements of the underlying sequence while the + /// Returns a sequence that, when iterated, skips elements of the underlying sequence while the /// given predicate returns True, and then yields the remaining elements of the sequence. /// /// A function that evaluates an element of the sequence to a boolean value. @@ -1035,10 +1035,10 @@ namespace Microsoft.FSharp.Collections val skipWhile: predicate:('T -> bool) -> source:seq<'T> -> seq<'T> /// Yields a sequence ordered by keys. - /// - /// This function returns a sequence that digests the whole initial sequence as soon as - /// that sequence is iterated. As a result this function should not be used with - /// large or infinite sequences. The function makes no assumption on the ordering of the original + /// + /// This function returns a sequence that digests the whole initial sequence as soon as + /// that sequence is iterated. As a result this function should not be used with + /// large or infinite sequences. The function makes no assumption on the ordering of the original /// sequence. /// /// This is a stable sort, that is the original order of equal elements is preserved. @@ -1067,11 +1067,11 @@ namespace Microsoft.FSharp.Collections val sortWith : comparer:('T -> 'T -> int) -> source:seq<'T> -> seq<'T> /// Applies a key-generating function to each element of a sequence and yield a sequence ordered - /// by keys. The keys are compared using generic comparison as implemented by Operators.compare. - /// - /// This function returns a sequence that digests the whole initial sequence as soon as - /// that sequence is iterated. As a result this function should not be used with - /// large or infinite sequences. The function makes no assumption on the ordering of the original + /// by keys. The keys are compared using generic comparison as implemented by Operators.compare. + /// + /// This function returns a sequence that digests the whole initial sequence as soon as + /// that sequence is iterated. As a result this function should not be used with + /// large or infinite sequences. The function makes no assumption on the ordering of the original /// sequence. /// /// This is a stable sort, that is the original order of equal elements is preserved. @@ -1083,13 +1083,13 @@ namespace Microsoft.FSharp.Collections /// /// Thrown when the input sequence is null. [] - val sortBy : projection:('T -> 'Key) -> source:seq<'T> -> seq<'T> when 'Key : comparison + val sortBy : projection:('T -> 'Key) -> source:seq<'T> -> seq<'T> when 'Key : comparison /// Yields a sequence ordered descending by keys. - /// - /// This function returns a sequence that digests the whole initial sequence as soon as - /// that sequence is iterated. As a result this function should not be used with - /// large or infinite sequences. The function makes no assumption on the ordering of the original + /// + /// This function returns a sequence that digests the whole initial sequence as soon as + /// that sequence is iterated. As a result this function should not be used with + /// large or infinite sequences. The function makes no assumption on the ordering of the original /// sequence. /// /// This is a stable sort, that is the original order of equal elements is preserved. @@ -1103,11 +1103,11 @@ namespace Microsoft.FSharp.Collections val inline sortDescending : source:seq<'T> -> seq<'T> when 'T : comparison /// Applies a key-generating function to each element of a sequence and yield a sequence ordered - /// descending by keys. The keys are compared using generic comparison as implemented by Operators.compare. - /// - /// This function returns a sequence that digests the whole initial sequence as soon as - /// that sequence is iterated. As a result this function should not be used with - /// large or infinite sequences. The function makes no assumption on the ordering of the original + /// descending by keys. The keys are compared using generic comparison as implemented by Operators.compare. + /// + /// This function returns a sequence that digests the whole initial sequence as soon as + /// that sequence is iterated. As a result this function should not be used with + /// large or infinite sequences. The function makes no assumption on the ordering of the original /// sequence. /// /// This is a stable sort, that is the original order of equal elements is preserved. @@ -1129,8 +1129,8 @@ namespace Microsoft.FSharp.Collections /// /// The computed sum. [] - val inline sum : source:seq<(^T)> -> ^T - when ^T : (static member ( + ) : ^T * ^T -> ^T) + val inline sum : source:seq<(^T)> -> ^T + when ^T : (static member ( + ) : ^T * ^T -> ^T) and ^T : (static member Zero : ^T) /// Returns the sum of the results generated by applying the function to each element of the sequence. @@ -1141,8 +1141,8 @@ namespace Microsoft.FSharp.Collections /// /// The computed sum. [] - val inline sumBy : projection:('T -> ^U) -> source:seq<'T> -> ^U - when ^U : (static member ( + ) : ^U * ^U -> ^U) + val inline sumBy : projection:('T -> ^U) -> source:seq<'T> -> ^U + when ^U : (static member ( + ) : ^U * ^U -> ^U) and ^U : (static member Zero : ^U) /// Returns a sequence that skips 1 element of the underlying sequence and then yields the @@ -1174,7 +1174,7 @@ namespace Microsoft.FSharp.Collections [] val take: count:int -> source:seq<'T> -> seq<'T> - /// Returns a sequence that, when iterated, yields elements of the underlying sequence while the + /// Returns a sequence that, when iterated, yields elements of the underlying sequence while the /// given predicate returns True, and then returns no further elements. /// /// A function that evaluates to false when no more items should be returned. @@ -1195,7 +1195,7 @@ namespace Microsoft.FSharp.Collections /// Thrown when the input sequence is null. [] val toArray: source:seq<'T> -> 'T[] - + /// Builds an SeqEnumerable from the given collection. /// /// The input sequence. @@ -1240,7 +1240,7 @@ namespace Microsoft.FSharp.Collections [] val tryFindBack: predicate:('T -> bool) -> source:seq<'T> -> 'T option - /// Returns the index of the first element in the sequence + /// Returns the index of the first element in the sequence /// that satisfies the given predicate. Return None if no such element exists. /// /// A function that evaluates to a Boolean when given an item in the sequence. @@ -1304,7 +1304,7 @@ namespace Microsoft.FSharp.Collections /// /// The stream will be recomputed each time an IEnumerator is requested and iterated for the Seq. /// - /// The returned sequence may be passed between threads safely. However, + /// The returned sequence may be passed between threads safely. However, /// individual IEnumerator values generated from the returned sequence should not be accessed concurrently. /// /// A function that takes in the current state and returns an option tuple of the next diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 854270f94d5..b10e23860ad 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -124,10 +124,6 @@ namespace Microsoft.FSharp.Collections static member Combine (first:SeqFactory<'T,'U>) (second:SeqFactory<'U,'V>) : SeqFactory<'T,'V> = upcast ComposedFactory(first, second, first.PipeIdx+1) - and DistinctFactory<'T when 'T: equality> () = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Distinct (next) - and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = inherit SeqFactory<'T,'T> () override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) @@ -230,17 +226,6 @@ namespace Microsoft.FSharp.Collections finally next.OnDispose (&stopTailCall) - and Distinct<'T,'V when 'T: equality> (next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) - - let hashSet = HashSet<'T>(HashIdentity.Structural<'T>) - - override __.ProcessNext (input:'T) : bool = - if hashSet.Add input then - TailCall.avoid (next.ProcessNext input) - else - false - and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 8b80ef4ab22..265b5d7d5e0 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -74,6 +74,7 @@ namespace Microsoft.FSharp.Collections type SeqFactory<'T,'U> = new : unit -> SeqFactory<'T,'U> abstract PipeIdx : PipeIdx + default PipeIdx : PipeIdx abstract member Create : IOutOfBand -> PipeIdx -> Consumer<'U,'V> -> Consumer<'T,'V> type ISeq<'T> = @@ -83,6 +84,18 @@ namespace Microsoft.FSharp.Collections open Core + module internal TailCall = + val inline avoid : boolean:bool -> bool + + 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. + val inline seq : t:#ISeq<'T> -> ISeq<'T> + val inline enumerable : t:#IEnumerable<'T> -> IEnumerable<'T> + val inline enumerator : t:#IEnumerator<'T> -> IEnumerator<'T> + val inline enumeratorNonGeneric : t:#IEnumerator -> IEnumerator + val inline iCompletionChaining : t:#ICompletionChaining -> ICompletionChaining + module internal Seq = type ComposedFactory<'T,'U,'V> = class @@ -96,11 +109,6 @@ namespace Microsoft.FSharp.Collections second: SeqFactory<'U,'V> -> SeqFactory<'T,'V> end - and DistinctFactory<'T when 'T : equality> = - class - inherit SeqFactory<'T,'T> - new : unit -> DistinctFactory<'T> - end and DistinctByFactory<'T,'Key when 'Key : equality> = class inherit SeqFactory<'T,'T> @@ -218,12 +226,6 @@ namespace Microsoft.FSharp.Collections new : next:ICompletionChaining -> SeqComponent<'T,'U> end - and Distinct<'T,'V when 'T : equality> = - class - inherit SeqComponent<'T,'V> - new : next: Consumer<'T,'V> -> Distinct<'T,'V> - override ProcessNext : input:'T -> bool - end and DistinctBy<'T,'Key,'V when 'Key : equality> = class inherit SeqComponent<'T,'V> @@ -647,7 +649,7 @@ namespace Microsoft.FSharp.Collections val mapi_adapt : f:OptimizedClosures.FSharpFunc -> source: ISeq<'a> -> ISeq<'b> [] - val choose : f:('a->option<'b>) -> source: ISeq<'a> -> ISeq<'b> + val inline choose : f:('a->option<'b>) -> source: ISeq<'a> -> ISeq<'b> [] val inline indexed : source: ISeq<'a> -> ISeq From 6d6b7a612ec465b668613c22b9660d49ff27f57c Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 7 Dec 2016 21:48:01 -0500 Subject: [PATCH 217/286] revise distinct --- src/fsharp/FSharp.Core/seq.fs | 10 ++-------- src/fsharp/FSharp.Core/seqcomposer.fs | 10 ++++++++++ src/fsharp/FSharp.Core/seqcomposer.fsi | 3 +++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 157c50d75c2..aa8203d9b39 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -52,7 +52,7 @@ namespace Microsoft.FSharp.Collections let inline foreach f (source:seq<_>) = Composer.Seq.foreach f (toComposer source) - let inline seqFactory (createSeqComponent:#SeqFactory<_,_>) (source:seq<'T>) = + let private seqFactory (createSeqComponent:#SeqFactory<_,_>) (source:seq<'T>) = match source with | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose createSeqComponent) | :? array<'T> as a -> Upcast.enumerable (Composer.Seq.Array.create a createSeqComponent) @@ -645,13 +645,7 @@ namespace Microsoft.FSharp.Collections [] let distinct source = - source |> seqFactory { new SeqFactory<'T,'T>() with - member __.Create _ _ next = - upcast { new SeqComponentSimpleValue<'T,'V,HashSet<'T>> - (Upcast.iCompletionChaining next,(HashSet<'T>(HashIdentity.Structural<'T>))) with - override this.ProcessNext (input:'T) : bool = - if this.Value.Add input then TailCall.avoid (next.ProcessNext input) - else false } } + source |> toComposer |> Composer.Seq.distinct |> Upcast.enumerable [] let distinctBy keyf source = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index b10e23860ad..7f0da792f9f 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -1182,6 +1182,16 @@ namespace Microsoft.FSharp.Collections | Some value -> TailCall.avoid (next.ProcessNext value) | None -> false } } + [] + let inline distinct source = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { new SeqComponentSimpleValue<'T,'V,HashSet<'T>> + (Upcast.iCompletionChaining next,(HashSet<'T>(HashIdentity.Structural<'T>))) with + override this.ProcessNext (input:'T) : bool = + if this.Value.Add input then TailCall.avoid (next.ProcessNext input) + else false } } + [] let inline indexed source = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 265b5d7d5e0..321c9efb2b0 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -651,6 +651,9 @@ namespace Microsoft.FSharp.Collections [] val inline choose : f:('a->option<'b>) -> source: ISeq<'a> -> ISeq<'b> + [] + val inline distinct : source: ISeq<'a> -> ISeq<'a> + [] val inline indexed : source: ISeq<'a> -> ISeq From e8b9d8638dede40dbef9ee655bd3517d8890082d Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 7 Dec 2016 22:07:54 -0500 Subject: [PATCH 218/286] hide unnecessarily exposed surface area --- src/fsharp/FSharp.Core/seqcomposer.fsi | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 321c9efb2b0..cba383f9385 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -84,18 +84,6 @@ namespace Microsoft.FSharp.Collections open Core - module internal TailCall = - val inline avoid : boolean:bool -> bool - - 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. - val inline seq : t:#ISeq<'T> -> ISeq<'T> - val inline enumerable : t:#IEnumerable<'T> -> IEnumerable<'T> - val inline enumerator : t:#IEnumerator<'T> -> IEnumerator<'T> - val inline enumeratorNonGeneric : t:#IEnumerator -> IEnumerator - val inline iCompletionChaining : t:#ICompletionChaining -> ICompletionChaining - module internal Seq = type ComposedFactory<'T,'U,'V> = class From 54a2c0ee464b30d9c69d69a326cff6a1bf1be1c9 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 7 Dec 2016 22:37:28 -0500 Subject: [PATCH 219/286] inline distinctBy --- src/fsharp/FSharp.Core/seq.fs | 2 +- src/fsharp/FSharp.Core/seqcomposer.fs | 28 ++++++++++---------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 17 ++++------------ 3 files changed, 16 insertions(+), 31 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index aa8203d9b39..116cd02ee96 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -649,7 +649,7 @@ namespace Microsoft.FSharp.Collections [] let distinctBy keyf source = - source |> seqFactory (Composer.Seq.DistinctByFactory keyf) + source |> toComposer |> Composer.Seq.distinctBy keyf |> Upcast.enumerable [] let sortBy keyf source = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 7f0da792f9f..584943424af 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -124,10 +124,6 @@ namespace Microsoft.FSharp.Collections static member Combine (first:SeqFactory<'T,'U>) (second:SeqFactory<'U,'V>) : SeqFactory<'T,'V> = upcast ComposedFactory(first, second, first.PipeIdx+1) - and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast DistinctBy (keyFunction, next) - and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = inherit SeqFactory<'T,'T> () override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) @@ -225,18 +221,6 @@ namespace Microsoft.FSharp.Collections try this.OnDispose () finally next.OnDispose (&stopTailCall) - - and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) - - let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>) - - override __.ProcessNext (input:'T) : bool = - if hashSet.Add(keyFunction input) then - TailCall.avoid (next.ProcessNext input) - else - false - and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) @@ -1183,7 +1167,7 @@ namespace Microsoft.FSharp.Collections | None -> false } } [] - let inline distinct source = + let inline distinct (source:ISeq<'T>) : ISeq<'T> when 'T:equality = source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = upcast { new SeqComponentSimpleValue<'T,'V,HashSet<'T>> @@ -1192,6 +1176,16 @@ namespace Microsoft.FSharp.Collections if this.Value.Add input then TailCall.avoid (next.ProcessNext input) else false } } + [] + let inline distinctBy (keyf:'T->'Key) (source:ISeq<'T>) :ISeq<'T> when 'Key:equality = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { new SeqComponentSimpleValue<'T,'V,HashSet<'Key>> + (Upcast.iCompletionChaining next,(HashSet<'Key>(HashIdentity.Structural<'Key>))) with + override this.ProcessNext (input:'T) : bool = + if this.Value.Add (keyf input) then TailCall.avoid (next.ProcessNext input) + else false } } + [] let inline indexed source = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index cba383f9385..9fe42b1afda 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -97,11 +97,6 @@ namespace Microsoft.FSharp.Collections second: SeqFactory<'U,'V> -> SeqFactory<'T,'V> end - and DistinctByFactory<'T,'Key when 'Key : equality> = - class - inherit SeqFactory<'T,'T> - new : keyFunction:('T -> 'Key) -> DistinctByFactory<'T,'Key> - end and ExceptFactory<'T when 'T : equality> = class inherit SeqFactory<'T,'T> @@ -214,13 +209,6 @@ namespace Microsoft.FSharp.Collections new : next:ICompletionChaining -> SeqComponent<'T,'U> end - and DistinctBy<'T,'Key,'V when 'Key : equality> = - class - inherit SeqComponent<'T,'V> - new : keyFunction:('T -> 'Key) * next: Consumer<'T,'V> -> - DistinctBy<'T,'Key,'V> - override ProcessNext : input:'T -> bool - end and Except<'T,'V when 'T : equality> = class inherit SeqComponent<'T,'V> @@ -640,7 +628,10 @@ namespace Microsoft.FSharp.Collections val inline choose : f:('a->option<'b>) -> source: ISeq<'a> -> ISeq<'b> [] - val inline distinct : source: ISeq<'a> -> ISeq<'a> + 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 indexed : source: ISeq<'a> -> ISeq From 4c866d668d76c2ccbe235ec8337ab86bfc09f236 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 7 Dec 2016 23:13:24 -0500 Subject: [PATCH 220/286] inline skipWhile --- src/fsharp/FSharp.Core/seq.fs | 8 +++--- src/fsharp/FSharp.Core/seqcomposer.fs | 35 ++++++++++++-------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 15 +++-------- 3 files changed, 23 insertions(+), 35 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 116cd02ee96..197a5e4b045 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -896,12 +896,12 @@ namespace Microsoft.FSharp.Collections *) [] - let takeWhile p (source: seq<_>) = - source |> seqFactory (Composer.Seq.TakeWhileFactory p) + let takeWhile predicate (source: seq<_>) = + source |> seqFactory (Composer.Seq.TakeWhileFactory predicate) [] - let skipWhile p (source: seq<_>) = - source |> seqFactory (Composer.Seq.SkipWhileFactory p) + let skipWhile predicate (source: seq<_>) = + source |> toComposer |> Composer.Seq.skipWhile predicate |> Upcast.enumerable [] let forall2 p (source1: seq<_>) (source2: seq<_>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 584943424af..1a06c89932a 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -162,10 +162,6 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'T,'T> () override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, onNotEnoughElements, next) - and SkipWhileFactory<'T> (predicate:'T->bool) = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast SkipWhile (predicate, next) - and TakeWhileFactory<'T> (predicate:'T->bool) = inherit SeqFactory<'T,'T> () override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, outOfBand, next, pipeIdx) @@ -352,21 +348,6 @@ namespace Microsoft.FSharp.Collections notEnoughElements "{0}\ntried to skip {1} {2} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - and SkipWhile<'T,'V> (predicate:'T->bool, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) - - let mutable skip = true - - override __.ProcessNext (input:'T) : bool = - if skip then - skip <- predicate input - if skip then - false - else - TailCall.avoid (next.ProcessNext input) - else - TailCall.avoid (next.ProcessNext input) - and Take<'T,'V> (takeCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipelineIdx:int) = inherit Truncate<'T, 'V>(takeCount, outOfBand, next, pipelineIdx) @@ -1187,6 +1168,22 @@ namespace Microsoft.FSharp.Collections else false } } + [] + let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { new SeqComponentSimpleValue<'T,'V,bool>(Upcast.iCompletionChaining next,true) with + override self.ProcessNext (input:'T) : bool = + if self.Value (*skip*) then + self.Value <- predicate input + if self.Value (*skip*) then + false + else + TailCall.avoid (next.ProcessNext input) + else + TailCall.avoid (next.ProcessNext input) }} + + [] let inline indexed source = mapi (fun i x -> i,x) source diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 9fe42b1afda..0697c570120 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -153,11 +153,6 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'T,'T> new : count:int * notEnoughElements:(string->array->unit) -> SkipFactory<'T> end - and SkipWhileFactory<'T> = - class - inherit SeqFactory<'T,'T> - new : predicate:('T -> bool) -> SkipWhileFactory<'T> - end and TakeWhileFactory<'T> = class inherit SeqFactory<'T,'T> @@ -285,13 +280,6 @@ namespace Microsoft.FSharp.Collections override OnComplete : PipeIdx -> unit override ProcessNext : input:'T -> bool end - and SkipWhile<'T,'V> = - class - inherit SeqComponent<'T,'V> - new : predicate:('T -> bool) * next: Consumer<'T,'V> -> - SkipWhile<'T,'V> - override ProcessNext : input:'T -> bool - end and Take<'T,'V> = class inherit Truncate<'T,'V> @@ -633,6 +621,9 @@ namespace Microsoft.FSharp.Collections [] val inline distinctBy : keyf:('T->'Key) -> source: ISeq<'T> -> ISeq<'T> when 'Key:equality + [] + val inline skipWhile : predicate:('T->bool) -> source:ISeq<'T> -> ISeq<'T> + [] val inline indexed : source: ISeq<'a> -> ISeq From c742fa826999e07f68ea6954edad224df4905a93 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 7 Dec 2016 23:33:46 -0500 Subject: [PATCH 221/286] inline takeWhile --- src/fsharp/FSharp.Core/seq.fs | 6 ++--- src/fsharp/FSharp.Core/seqcomposer.fs | 31 ++++++++++++-------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 22 +++++------------- 3 files changed, 23 insertions(+), 36 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 197a5e4b045..bea304b4774 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -895,11 +895,11 @@ namespace Microsoft.FSharp.Collections acc *) - [] + [] let takeWhile predicate (source: seq<_>) = - source |> seqFactory (Composer.Seq.TakeWhileFactory predicate) + source |> toComposer |> Composer.Seq.takeWhile predicate |> Upcast.enumerable - [] + [] let skipWhile predicate (source: seq<_>) = source |> toComposer |> Composer.Seq.skipWhile predicate |> Upcast.enumerable diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 1a06c89932a..cc426adf7ab 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -162,10 +162,6 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'T,'T> () override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, onNotEnoughElements, next) - and TakeWhileFactory<'T> (predicate:'T->bool) = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast TakeWhile (predicate, outOfBand, next, pipeIdx) - and TakeFactory<'T> (count:int) = inherit SeqFactory<'T,'T> () override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, pipeIdx) @@ -357,16 +353,6 @@ namespace Microsoft.FSharp.Collections invalidOpFmt "tried to take {0} {1} past the end of the seq" [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - and TakeWhile<'T,'V> (predicate:'T->bool, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) - - override __.ProcessNext (input:'T) : bool = - if predicate input then - TailCall.avoid (next.ProcessNext input) - else - outOfBand.StopFurtherProcessing pipeIdx - false - and Tail<'T, 'V> (next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) @@ -1147,7 +1133,7 @@ namespace Microsoft.FSharp.Collections | Some value -> TailCall.avoid (next.ProcessNext value) | None -> false } } - [] + [] let inline distinct (source:ISeq<'T>) : ISeq<'T> when 'T:equality = source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = @@ -1157,7 +1143,7 @@ namespace Microsoft.FSharp.Collections if this.Value.Add input then TailCall.avoid (next.ProcessNext input) else false } } - [] + [] let inline distinctBy (keyf:'T->'Key) (source:ISeq<'T>) :ISeq<'T> when 'Key:equality = source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = @@ -1168,7 +1154,7 @@ namespace Microsoft.FSharp.Collections else false } } - [] + [] let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = @@ -1183,6 +1169,17 @@ namespace Microsoft.FSharp.Collections else TailCall.avoid (next.ProcessNext input) }} + [] + let inline takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create outOfBand pipeIdx next = + upcast { new SeqComponent<'T,'V>(Upcast.iCompletionChaining next) with + override __.ProcessNext (input:'T) : bool = + if predicate input then + TailCall.avoid (next.ProcessNext input) + else + outOfBand.StopFurtherProcessing pipeIdx + false }} [] let inline indexed source = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 0697c570120..4a5bee87d38 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -153,11 +153,6 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'T,'T> new : count:int * notEnoughElements:(string->array->unit) -> SkipFactory<'T> end - and TakeWhileFactory<'T> = - class - inherit SeqFactory<'T,'T> - new : predicate:('T -> bool) -> TakeWhileFactory<'T> - end and TakeFactory<'T> = class inherit SeqFactory<'T,'T> @@ -288,14 +283,6 @@ namespace Microsoft.FSharp.Collections Take<'T,'V> override OnComplete : terminatingIdx: PipeIdx -> unit end - and TakeWhile<'T,'V> = - class - inherit SeqComponent<'T,'V> - new : predicate:('T -> bool) * outOfBand: IOutOfBand * - next: Consumer<'T,'V> * pipeIdx:int -> - TakeWhile<'T,'V> - override ProcessNext : input:'T -> bool - end and Tail<'T,'V> = class inherit SeqComponent<'T,'V> @@ -621,15 +608,18 @@ namespace Microsoft.FSharp.Collections [] val inline distinctBy : keyf:('T->'Key) -> source: ISeq<'T> -> ISeq<'T> when 'Key:equality - [] + [] val inline skipWhile : predicate:('T->bool) -> source:ISeq<'T> -> ISeq<'T> + [] + val inline takeWhile : predicate:('T->bool) -> source:ISeq<'T> -> ISeq<'T> + [] val inline indexed : source: ISeq<'a> -> ISeq [] - val tryPick : - f:('T -> 'U option) -> source: ISeq<'T> -> Option<'U> + val tryPick : f:('T -> 'U option) -> source: ISeq<'T> -> Option<'U> + [] val tryFind : f:('T -> bool) -> source: ISeq<'T> -> Option<'T> From 7f2ba2543e7e7d76a75cee81f5c608ae1358be74 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 00:07:53 -0500 Subject: [PATCH 222/286] inline skip --- src/fsharp/FSharp.Core/seq.fs | 4 +- src/fsharp/FSharp.Core/seqcomposer.fs | 72 +++++++++++++------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 23 +++----- 3 files changed, 46 insertions(+), 53 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index bea304b4774..142c8dc8a04 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -91,7 +91,7 @@ namespace Microsoft.FSharp.Collections [] let skip count (source: seq<_>) = - source |> seqFactory (Composer.Seq.SkipFactory (count, invalidOpFmt)) + source |> toComposer |> Composer.Seq.skip count |> Upcast.enumerable let invalidArgumnetIndex = invalidArgFmt "index" @@ -99,7 +99,7 @@ namespace Microsoft.FSharp.Collections let item i (source : seq<'T>) = if i < 0 then invalidArgInputMustBeNonNegative "index" i else source - |> seqFactory (Composer.Seq.SkipFactory (i, invalidArgumnetIndex)) + |> toComposer |> Composer.Seq.skip i |> Upcast.enumerable |> tryHead |> function | None -> invalidArgFmt "index" "{0}\nseq was short by 1 element" [|SR.GetString SR.notEnoughElements|] diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index cc426adf7ab..d6b6747cb2e 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -158,10 +158,6 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'T,'State> () override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) - and SkipFactory<'T> (count:int, onNotEnoughElements) = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Skip (count, onNotEnoughElements, next) - and TakeFactory<'T> (count:int) = inherit SeqFactory<'T,'T> () override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, pipeIdx) @@ -318,32 +314,6 @@ namespace Microsoft.FSharp.Collections foldResult <- f.Invoke(foldResult, input) TailCall.avoid (next.ProcessNext foldResult) - and Skip<'T,'V> (skipCount:int, notEnoughElements:string->array->unit, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) - - let mutable count = 0 - - interface ISkipping with - member __.Skipping () = - if count < skipCount then - count <- count + 1 - true - else - false - - override __.ProcessNext (input:'T) : bool = - if count < skipCount then - count <- count + 1 - false - else - TailCall.avoid (next.ProcessNext input) - - override __.OnComplete _ = - if count < skipCount then - let x = skipCount - count - notEnoughElements "{0}\ntried to skip {1} {2} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - and Take<'T,'V> (takeCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipelineIdx:int) = inherit Truncate<'T, 'V>(takeCount, outOfBand, next, pipelineIdx) @@ -1034,11 +1004,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun head -> head.Value - [] - let tryItem i (source:ISeq<'T>) = - if i < 0 then None else - source.Compose (SkipFactory(i, fun _ _ -> ())) - |> tryHead + [] let iteri f (source:ISeq<'T>) = @@ -1153,6 +1119,37 @@ namespace Microsoft.FSharp.Collections if this.Value.Add (keyf input) then TailCall.avoid (next.ProcessNext input) else false } } + [] + let inline skip (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { + new SeqComponentSimpleValue<'T,'U,int>(Upcast.iCompletionChaining next,(*count*)0) with + + override self.ProcessNext (input:'T) : bool = + if (*count*) self.Value < skipCount then + self.Value <- self.Value + 1 + false + else + TailCall.avoid (next.ProcessNext input) + + override self.OnComplete _ = + if (*count*) self.Value < skipCount then + let x = skipCount - self.Value + 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")|] + + interface ISkipping with + member self.Skipping () = + let self = self :?> SeqComponentSimpleValue<'T,'U,int> + if (*count*) self.Value < skipCount then + self.Value <- self.Value + 1 + true + else + false + }} + + [] let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = @@ -1185,6 +1182,11 @@ namespace Microsoft.FSharp.Collections let inline 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 tryPick f (source:ISeq<'T>) = source diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 4a5bee87d38..1c1deb8de25 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -148,11 +148,6 @@ namespace Microsoft.FSharp.Collections new : folder:('State -> 'T -> 'State) * initialState:'State -> ScanFactory<'T,'State> end - and SkipFactory<'T> = - class - inherit SeqFactory<'T,'T> - new : count:int * notEnoughElements:(string->array->unit) -> SkipFactory<'T> - end and TakeFactory<'T> = class inherit SeqFactory<'T,'T> @@ -266,15 +261,6 @@ namespace Microsoft.FSharp.Collections Scan<'T,'State,'V> override ProcessNext : input:'T -> bool end - and Skip<'T,'V> = - class - inherit SeqComponent<'T,'V> - interface ISkipping - new : skipCount:int * exceptionOnNotEnoughElements:(string->array->unit) * next: Consumer<'T,'V> -> - Skip<'T,'V> - override OnComplete : PipeIdx -> unit - override ProcessNext : input:'T -> bool - end and Take<'T,'V> = class inherit Truncate<'T,'V> @@ -576,8 +562,7 @@ namespace Microsoft.FSharp.Collections val iter : f:('T -> unit) -> source: ISeq<'T> -> unit [] val tryHead : source: ISeq<'T> -> 'T option - [] - val tryItem : i:int -> source: ISeq<'T> -> 'T option + [] val iteri : f:(int -> 'T -> unit) -> source: ISeq<'T> -> unit [] @@ -608,6 +593,9 @@ namespace Microsoft.FSharp.Collections [] val inline distinctBy : keyf:('T->'Key) -> source: ISeq<'T> -> ISeq<'T> when 'Key:equality + [] + val inline skip : skipCount:int -> source:ISeq<'T> -> ISeq<'T> + [] val inline skipWhile : predicate:('T->bool) -> source:ISeq<'T> -> ISeq<'T> @@ -617,6 +605,9 @@ namespace Microsoft.FSharp.Collections [] val inline indexed : source: ISeq<'a> -> ISeq + [] + val tryItem : index:int -> source: ISeq<'T> -> 'T option + [] val tryPick : f:('T -> 'U option) -> source: ISeq<'T> -> Option<'U> From bd06705b47108750a24ee20d9fa28403f67ceede Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 01:50:20 -0500 Subject: [PATCH 223/286] inline scan --- src/fsharp/FSharp.Core/seq.fs | 8 +++---- src/fsharp/FSharp.Core/seqcomposer.fs | 32 +++++++++++++++----------- src/fsharp/FSharp.Core/seqcomposer.fsi | 17 +++----------- 3 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 142c8dc8a04..c07a43a827b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -468,11 +468,9 @@ namespace Microsoft.FSharp.Collections let pairwise<'T> (source:seq<'T>) : seq<'T*'T> = source |> seqFactory (Composer.Seq.PairwiseFactory ()) - [] - let scan<'T,'State> f (z:'State) (source : seq<'T>): seq<'State> = - let first = [|z|] :> IEnumerable<'State> - let rest = source |> seqFactory (Composer.Seq.ScanFactory (f, z)) - upcast Composer.Seq.Enumerable.ConcatEnumerable [|first; rest;|] + [] + let scan<'T,'State> (folder:'State->'T->'State) (state:'State) (source:seq<'T>) : seq<'State> = + source |> toComposer |> Composer.Seq.scan folder state |> Upcast.enumerable [] let tryFindBack f (source : seq<'T>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index d6b6747cb2e..147d0329be7 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -154,10 +154,6 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'T,'T*'T> () override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) - and ScanFactory<'T,'State> (folder:'State->'T->'State, initialState:'State) = - inherit SeqFactory<'T,'State> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'State,'V>) : Consumer<'T,'V> = upcast Scan<_,_,_> (folder, initialState, next) - and TakeFactory<'T> (count:int) = inherit SeqFactory<'T,'T> () override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, pipeIdx) @@ -304,16 +300,6 @@ namespace Microsoft.FSharp.Collections lastValue <- input TailCall.avoid (next.ProcessNext currentPair) - and Scan<'T,'State,'V> (folder:'State->'T->'State, initialState: 'State, next:Consumer<'State,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) - - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder - let mutable foldResult = initialState - - override __.ProcessNext (input:'T) : bool = - foldResult <- f.Invoke(foldResult, input) - TailCall.avoid (next.ProcessNext foldResult) - and Take<'T,'V> (takeCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipelineIdx:int) = inherit Truncate<'T, 'V>(takeCount, outOfBand, next, pipelineIdx) @@ -1119,6 +1105,24 @@ namespace Microsoft.FSharp.Collections if this.Value.Add (keyf input) then TailCall.avoid (next.ProcessNext input) else false } } + [] + let inline scan (folder:'State->'T->'State) (initialState: 'State) (source:ISeq<'T>) :ISeq<'State> = + source |> compose { new SeqFactory<'T,'State>() with + member __.Create _ _ next = + upcast { new SeqComponentSimpleValue<'T,'V,'State>(Upcast.iCompletionChaining next, initialState) with + override this.ProcessNext (input:'T) : bool = + this.Value <- folder this.Value input + TailCall.avoid (next.ProcessNext this.Value) } } + + + let scan_adapt (folder:OptimizedClosures.FSharpFunc<'State,'T,'State>) (initialState: 'State) (source:ISeq<'T>) :ISeq<'State> = + source |> compose { new SeqFactory<'T,'State>() with + member __.Create _ _ next = + upcast { new SeqComponentSimpleValue<'T,'V,'State>(Upcast.iCompletionChaining next, initialState) with + override this.ProcessNext (input:'T) : bool = + this.Value <- folder.Invoke(this.Value,input) + TailCall.avoid (next.ProcessNext this.Value) } } + [] let inline skip (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 1c1deb8de25..4dacf511b77 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -142,12 +142,6 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'T,('T * 'T)> new : unit -> PairwiseFactory<'T> end - and ScanFactory<'T,'State> = - class - inherit SeqFactory<'T,'State> - new : folder:('State -> 'T -> 'State) * initialState:'State -> - ScanFactory<'T,'State> - end and TakeFactory<'T> = class inherit SeqFactory<'T,'T> @@ -253,14 +247,6 @@ namespace Microsoft.FSharp.Collections Pairwise<'T,'V> override ProcessNext : input:'T -> bool end - and Scan<'T,'State,'V> = - class - inherit SeqComponent<'T,'V> - new : folder:('State -> 'T -> 'State) * initialState:'State * - next: Consumer<'State,'V> -> - Scan<'T,'State,'V> - override ProcessNext : input:'T -> bool - end and Take<'T,'V> = class inherit Truncate<'T,'V> @@ -593,6 +579,9 @@ namespace Microsoft.FSharp.Collections [] val inline distinctBy : keyf:('T->'Key) -> source: ISeq<'T> -> ISeq<'T> when 'Key:equality + [] + val inline scan : folder:('State->'T->'State) -> initialState:'State -> source:ISeq<'T> -> ISeq<'State> + [] val inline skip : skipCount:int -> source:ISeq<'T> -> ISeq<'T> From 0ab5af652deb9d1a4de6a2f7d476407bbf77b606 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 02:34:20 -0500 Subject: [PATCH 224/286] inline take & inline truncate --- src/fsharp/FSharp.Core/seq.fs | 6 +- src/fsharp/FSharp.Core/seqcomposer.fs | 78 ++++++++++++++------------ src/fsharp/FSharp.Core/seqcomposer.fsi | 33 ++--------- 3 files changed, 50 insertions(+), 67 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index c07a43a827b..656cb8221f3 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -257,7 +257,7 @@ namespace Microsoft.FSharp.Collections if count < 0 then invalidArgInputMustBeNonNegative "count" count (* Note: don't create or dispose any IEnumerable if n = 0 *) if count = 0 then empty else - source |> seqFactory (Composer.Seq.TakeFactory count) + source |> toComposer |> Composer.Seq.take count |> Upcast.enumerable [] let isEmpty (source : seq<'T>) = @@ -459,10 +459,10 @@ namespace Microsoft.FSharp.Collections let singleton x = mkSeq (fun () -> IEnumerator.Singleton x) - [] + [] let truncate n (source: seq<'T>) = if n <= 0 then empty else - source |> seqFactory (Composer.Seq.TruncateFactory n) + source |> toComposer |> Composer.Seq.truncate n |> Upcast.enumerable [] let pairwise<'T> (source:seq<'T>) : seq<'T*'T> = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 147d0329be7..d374d236364 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -154,18 +154,10 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'T,'T*'T> () override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) - and TakeFactory<'T> (count:int) = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Take (count, outOfBand, next, pipeIdx) - and TailFactory<'T> () = inherit SeqFactory<'T,'T> () override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) - and TruncateFactory<'T> (count:int) = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Truncate (count, outOfBand, next, pipeIdx) - and WindowedFactory<'T> (windowSize:int) = inherit SeqFactory<'T, 'T[]> () override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T[],'V>) : Consumer<'T,'V> = upcast Windowed (windowSize, next) @@ -300,15 +292,6 @@ namespace Microsoft.FSharp.Collections lastValue <- input TailCall.avoid (next.ProcessNext currentPair) - and Take<'T,'V> (takeCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipelineIdx:int) = - inherit Truncate<'T, 'V>(takeCount, outOfBand, next, pipelineIdx) - - override this.OnComplete terminatingIdx = - if terminatingIdx < pipelineIdx && this.Count < takeCount then - let x = takeCount - this.Count - invalidOpFmt "tried to take {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - and Tail<'T, 'V> (next:Consumer<'T,'V>) = inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) @@ -325,23 +308,6 @@ namespace Microsoft.FSharp.Collections if first then invalidArg "source" (SR.GetString(SR.notEnoughElements)) - and Truncate<'T,'V> (truncateCount:int, outOfBand:IOutOfBand, next:Consumer<'T,'V>, pipeIdx:int) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) - - let mutable count = 0 - - member __.Count = count - - override __.ProcessNext (input:'T) : bool = - if count < truncateCount then - count <- count + 1 - if count = truncateCount then - outOfBand.StopFurtherProcessing pipeIdx - TailCall.avoid (next.ProcessNext input) - else - outOfBand.StopFurtherProcessing pipeIdx - false - and Windowed<'T,'V> (windowSize: int, next:Consumer<'T[],'V>) = inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) @@ -1153,8 +1119,6 @@ namespace Microsoft.FSharp.Collections false }} - - [] let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with @@ -1170,6 +1134,29 @@ namespace Microsoft.FSharp.Collections else TailCall.avoid (next.ProcessNext input) }} + [] + let inline take (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create outOfBand pipelineIdx next = + upcast { + new SeqComponentSimpleValue<'T,'U,int>(Upcast.iCompletionChaining next,(*count*)0) with + override self.ProcessNext (input:'T) : bool = + if (*count*) self.Value < takeCount then + self.Value <- self.Value + 1 + if self.Value = takeCount then + outOfBand.StopFurtherProcessing pipelineIdx + TailCall.avoid (next.ProcessNext input) + else + outOfBand.StopFurtherProcessing pipelineIdx + false + + override this.OnComplete terminatingIdx = + if terminatingIdx < pipelineIdx && this.Value < takeCount then + let x = takeCount - this.Value + invalidOpFmt "tried to take {0} {1} past the end of the seq" + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] + }} + [] let inline takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with @@ -1182,6 +1169,23 @@ namespace Microsoft.FSharp.Collections outOfBand.StopFurtherProcessing pipeIdx false }} + [] + let inline truncate (truncateCount:int) (source:ISeq<'T>) : ISeq<'T> = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create outOfBand pipeIdx next = + upcast { + new SeqComponentSimpleValue<'T,'U,int>(Upcast.iCompletionChaining next,(*count*)0) with + override self.ProcessNext (input:'T) : bool = + if (*count*) self.Value < truncateCount then + self.Value <- self.Value + 1 + if self.Value = truncateCount then + outOfBand.StopFurtherProcessing pipeIdx + TailCall.avoid (next.ProcessNext input) + else + outOfBand.StopFurtherProcessing pipeIdx + false + }} + [] let inline indexed source = mapi (fun i x -> i,x) source @@ -1215,4 +1219,4 @@ namespace Microsoft.FSharp.Collections this.Value <- Some value halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun find -> find.Value \ No newline at end of file + |> fun find -> find.Value diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 4dacf511b77..f2658b96485 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -142,21 +142,11 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'T,('T * 'T)> new : unit -> PairwiseFactory<'T> end - and TakeFactory<'T> = - class - inherit SeqFactory<'T,'T> - new : count:int -> TakeFactory<'T> - end and TailFactory<'T> = class inherit SeqFactory<'T,'T> new : unit -> TailFactory<'T> end - and TruncateFactory<'T> = - class - inherit SeqFactory<'T,'T> - new : count:int -> TruncateFactory<'T> - end and WindowedFactory<'T> = class inherit SeqFactory<'T,'T []> @@ -247,14 +237,6 @@ namespace Microsoft.FSharp.Collections Pairwise<'T,'V> override ProcessNext : input:'T -> bool end - and Take<'T,'V> = - class - inherit Truncate<'T,'V> - new : takeCount:int * outOfBand: IOutOfBand * - next: Consumer<'T,'V> * pipelineIdx:int -> - Take<'T,'V> - override OnComplete : terminatingIdx: PipeIdx -> unit - end and Tail<'T,'V> = class inherit SeqComponent<'T,'V> @@ -262,15 +244,6 @@ namespace Microsoft.FSharp.Collections override OnComplete : PipeIdx -> unit override ProcessNext : input:'T -> bool end - and Truncate<'T,'V> = - class - inherit SeqComponent<'T,'V> - new : truncateCount:int * outOfBand: IOutOfBand * - next: Consumer<'T,'V> * pipeIdx:int -> - Truncate<'T,'V> - override ProcessNext : input:'T -> bool - member Count : int - end and Windowed<'T,'V> = class inherit SeqComponent<'T,'V> @@ -588,9 +561,15 @@ namespace Microsoft.FSharp.Collections [] val inline skipWhile : predicate:('T->bool) -> source:ISeq<'T> -> ISeq<'T> + [] + val inline take : takeCount:int -> source:ISeq<'T> -> ISeq<'T> + [] val inline takeWhile : predicate:('T->bool) -> source:ISeq<'T> -> ISeq<'T> + [] + val inline truncate : truncateCount:int -> source:ISeq<'T> -> ISeq<'T> + [] val inline indexed : source: ISeq<'a> -> ISeq From 082ccd5873135a0cfb19fea37650d39220ef5c0d Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 03:24:34 -0500 Subject: [PATCH 225/286] inline windowed --- src/fsharp/FSharp.Core/seq.fs | 2 +- src/fsharp/FSharp.Core/seqcomposer.fs | 67 ++++++++++++++------------ src/fsharp/FSharp.Core/seqcomposer.fsi | 14 +----- 3 files changed, 38 insertions(+), 45 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 656cb8221f3..29c585f0222 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -525,7 +525,7 @@ namespace Microsoft.FSharp.Collections let windowed windowSize (source: seq<_>) = if windowSize <= 0 then invalidArgFmt "windowSize" "{0}\nwindowSize = {1}" [|SR.GetString SR.inputMustBePositive; windowSize|] - source |> seqFactory (Composer.Seq.WindowedFactory (windowSize)) + source |> toComposer |> Composer.Seq.windowed windowSize |> Upcast.enumerable [] let cache (source : seq<'T>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index d374d236364..7f4827120b3 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -158,10 +158,6 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'T,'T> () override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) - and WindowedFactory<'T> (windowSize:int) = - inherit SeqFactory<'T, 'T[]> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T[],'V>) : Consumer<'T,'V> = upcast Windowed (windowSize, next) - and ISkipping = // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip // and it can only do it at the start of a sequence @@ -308,34 +304,6 @@ namespace Microsoft.FSharp.Collections if first then invalidArg "source" (SR.GetString(SR.notEnoughElements)) - and Windowed<'T,'V> (windowSize: int, next:Consumer<'T[],'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) - - let circularBuffer = Array.zeroCreateUnchecked windowSize - let mutable idx = 0 - - let mutable priming = windowSize - 1 - - override __.ProcessNext (input:'T) : bool = - circularBuffer.[idx] <- input - - idx <- idx + 1 - if idx = windowSize then - idx <- 0 - - if priming > 0 then - priming <- priming - 1 - false - else - if windowSize < 32 then - let window = Array.init windowSize (fun i -> circularBuffer.[(idx+i) % windowSize]) - 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) - type SeqProcessNextStates = | InProcess = 0 | NotStarted = 1 @@ -1220,3 +1188,38 @@ namespace Microsoft.FSharp.Collections halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun find -> find.Value + + [] + let inline windowed (windowSize:int) (source:ISeq<'T>) : ISeq<'T[]> = + source |> compose { new SeqFactory<'T,'T[]>() with + member __.Create outOfBand pipeIdx next = + upcast { + new SeqComponentSimpleValue<'T,'U,Values<'T[],int,int>> + ( Upcast.iCompletionChaining next + , Values<'T[],int,int> + ((*circularBuffer = _1 *) Array.zeroCreateUnchecked windowSize + ,(* idx = _2 *) 0 + ,(* priming = _3 *) windowSize-1 + ) + ) with + override self.ProcessNext (input:'T) : bool = + self.Value._1.[(* idx *)self.Value._2] <- input + + self.Value._2 <- (* idx *)self.Value._2 + 1 + if (* idx *) self.Value._2 = windowSize then + self.Value._2 <- 0 + + if (* priming *) self.Value._3 > 0 then + self.Value._3 <- self.Value._3 - 1 + false + else + if windowSize < 32 then + let window :'T [] = Array.init windowSize (fun i -> self.Value._1.[((* idx *)self.Value._2+i) % windowSize]: 'T) + TailCall.avoid (next.ProcessNext window) + else + let window = Array.zeroCreateUnchecked windowSize + Array.Copy((*circularBuffer*)self.Value._1, (* idx *)self.Value._2, window, 0, windowSize - (* idx *)self.Value._2) + Array.Copy((*circularBuffer*)self.Value._1, 0, window, windowSize - (* idx *)self.Value._2, (* idx *)self.Value._2) + TailCall.avoid (next.ProcessNext window) + + }} diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index f2658b96485..8a4a9cbf73c 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -147,11 +147,6 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'T,'T> new : unit -> TailFactory<'T> end - and WindowedFactory<'T> = - class - inherit SeqFactory<'T,'T []> - new : windowSize:int -> WindowedFactory<'T> - end and ISkipping = interface abstract member Skipping : unit -> bool @@ -244,13 +239,6 @@ namespace Microsoft.FSharp.Collections override OnComplete : PipeIdx -> unit override ProcessNext : input:'T -> bool end - and Windowed<'T,'V> = - class - inherit SeqComponent<'T,'V> - new : windowSize:int * next: Consumer<'T [],'V> -> - Windowed<'T,'V> - override ProcessNext : input:'T -> bool - end type SeqProcessNextStates = | InProcess = 0 | NotStarted = 1 @@ -582,3 +570,5 @@ namespace Microsoft.FSharp.Collections [] val tryFind : f:('T -> bool) -> source: ISeq<'T> -> Option<'T> + [] + val inline windowed : windowSize:int -> source:ISeq<'T> -> ISeq<'T[]> From 153540acbd555d58b72b95e0acff353dbbb038e3 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 03:39:30 -0500 Subject: [PATCH 226/286] inline tail --- src/fsharp/FSharp.Core/seq.fs | 4 +-- src/fsharp/FSharp.Core/seqcomposer.fs | 40 ++++++++++++-------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 15 ++-------- 3 files changed, 24 insertions(+), 35 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 29c585f0222..ad824861dc3 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -960,9 +960,9 @@ namespace Microsoft.FSharp.Collections | None -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString | Some x -> x - [] + [] let tail (source: seq<'T>) = - source |> seqFactory (Composer.Seq.TailFactory ()) + source |> toComposer |> Composer.Seq.tail |> Upcast.enumerable [] let tryLast (source : seq<_>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 7f4827120b3..0a9b00a6d12 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -154,10 +154,6 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'T,'T*'T> () override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) - and TailFactory<'T> () = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Tail<'T,'V> (next) - and ISkipping = // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip // and it can only do it at the start of a sequence @@ -288,22 +284,6 @@ namespace Microsoft.FSharp.Collections lastValue <- input TailCall.avoid (next.ProcessNext currentPair) - and Tail<'T, 'V> (next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) - - let mutable first = true - - override __.ProcessNext (input:'T) : bool = - if first then - first <- false - false - else - TailCall.avoid (next.ProcessNext input) - - override this.OnComplete _ = - if first then - invalidArg "source" (SR.GetString(SR.notEnoughElements)) - type SeqProcessNextStates = | InProcess = 0 | NotStarted = 1 @@ -1135,7 +1115,25 @@ namespace Microsoft.FSharp.Collections TailCall.avoid (next.ProcessNext input) else outOfBand.StopFurtherProcessing pipeIdx - false }} + false + }} + + [] + let inline tail (source:ISeq<'T>) :ISeq<'T> = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { new SeqComponentSimpleValue<'T,'V,bool>(Upcast.iCompletionChaining next,(*first*) true) with + override self.ProcessNext (input:'T) : bool = + if (*first*) self.Value then + self.Value <- false + false + else + TailCall.avoid (next.ProcessNext input) + + override self.OnComplete _ = + if (*first*) self.Value then + invalidArg "source" (SR.GetString(SR.notEnoughElements)) + }} [] let inline truncate (truncateCount:int) (source:ISeq<'T>) : ISeq<'T> = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 8a4a9cbf73c..499dc595381 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -142,11 +142,6 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'T,('T * 'T)> new : unit -> PairwiseFactory<'T> end - and TailFactory<'T> = - class - inherit SeqFactory<'T,'T> - new : unit -> TailFactory<'T> - end and ISkipping = interface abstract member Skipping : unit -> bool @@ -232,13 +227,6 @@ namespace Microsoft.FSharp.Collections Pairwise<'T,'V> override ProcessNext : input:'T -> bool end - and Tail<'T,'V> = - class - inherit SeqComponent<'T,'V> - new : next: Consumer<'T,'V> -> Tail<'T,'V> - override OnComplete : PipeIdx -> unit - override ProcessNext : input:'T -> bool - end type SeqProcessNextStates = | InProcess = 0 | NotStarted = 1 @@ -555,6 +543,9 @@ namespace Microsoft.FSharp.Collections [] val inline takeWhile : predicate:('T->bool) -> source:ISeq<'T> -> ISeq<'T> + [] + val inline tail : source:ISeq<'T> -> ISeq<'T> + [] val inline truncate : truncateCount:int -> source:ISeq<'T> -> ISeq<'T> From 8b43ba5a9351fb8ff5bb45a7577c241d746a26d3 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 04:16:18 -0500 Subject: [PATCH 227/286] pipeline formatting --- src/fsharp/FSharp.Core/seq.fs | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ad824861dc3..06e8bcb6726 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -83,11 +83,11 @@ namespace Microsoft.FSharp.Collections [] let iter f (source : seq<'T>) = - Composer.Seq.iter f (toComposer source) + source |> toComposer |> Composer.Seq.iter f [] let tryHead (source : seq<_>) = - Composer.Seq.tryHead (toComposer source) + source |> toComposer |> Composer.Seq.tryHead [] let skip count (source: seq<_>) = @@ -107,26 +107,26 @@ namespace Microsoft.FSharp.Collections [] let tryItem i (source:seq<'T>) = - Composer.Seq.tryItem i (toComposer source) + source |> toComposer |> Composer.Seq.tryItem i [] let nth i (source : seq<'T>) = item i source [] let iteri f (source:seq<'T>) = - Composer.Seq.iteri f (toComposer source) + source |> toComposer |> Composer.Seq.iteri f [] let exists f (source:seq<'T>) = - Composer.Seq.exists f (toComposer source) + source |> toComposer |> Composer.Seq.exists f [] let inline contains element (source:seq<'T>) = - Composer.Seq.contains element (toComposer source) + source |> toComposer |> Composer.Seq.contains element [] let forall f (source:seq<'T>) = - Composer.Seq.forall f (toComposer source) + source |> toComposer |> Composer.Seq.forall f [] let iter2 f (source1 : seq<_>) (source2 : seq<_>) = @@ -174,22 +174,19 @@ namespace Microsoft.FSharp.Collections [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = - Composer.Seq.filter f (toComposer source) - |> Upcast.enumerable + source |> toComposer |> Composer.Seq.filter f |> Upcast.enumerable [] let where f source = filter f source [] let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> = - Composer.Seq.map f (toComposer source) - |> Upcast.enumerable + source |> toComposer |> Composer.Seq.map f |> Upcast.enumerable [] let mapi f source = let f' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f - Composer.Seq.mapi_adapt f' (toComposer source) - |> Upcast.enumerable + source |> toComposer |> Composer.Seq.mapi_adapt f' |> Upcast.enumerable [] let mapi2 f source1 source2 = @@ -211,13 +208,11 @@ namespace Microsoft.FSharp.Collections [] let choose f source = - Composer.Seq.choose f (toComposer source) - |> Upcast.enumerable + source |> toComposer |> Composer.Seq.choose f |> Upcast.enumerable [] let indexed source = - Composer.Seq.indexed (toComposer source) - |> Upcast.enumerable + source |> toComposer |> Composer.Seq.indexed |> Upcast.enumerable [] let zip source1 source2 = @@ -234,7 +229,7 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source : seq<'T>) = - Composer.Seq.tryPick f (toComposer source) + source |> toComposer |> Composer.Seq.tryPick f [] let pick f source = @@ -244,7 +239,7 @@ namespace Microsoft.FSharp.Collections [] let tryFind f (source : seq<'T>) = - Composer.Seq.tryFind f (toComposer source) + source |> toComposer |> Composer.Seq.tryFind f [] let find f source = From 880e9ee859eeb47f6a9ffd737aff3f5793d2e91c Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 04:42:50 -0500 Subject: [PATCH 228/286] signature file formatting --- src/fsharp/FSharp.Core/seqcomposer.fsi | 60 ++++++++++++++------------ 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 499dc595381..974c730a217 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -478,34 +478,40 @@ namespace Microsoft.FSharp.Collections EnumerableDecider<'T> end end - [] + + [] val toComposer : source:seq<'T> -> ISeq<'T> - val inline foreach : - f:((unit -> unit) -> 'a) -> source: ISeq<'b> -> 'a - when 'a :> Consumer<'b,'b> - [] + + val inline foreach : f:((unit -> unit) -> 'a) -> source: ISeq<'b> -> 'a when 'a :> Consumer<'b,'b> + + [] val empty<'T> : ISeq<'T> - [] - val unfold : - generator:('State -> ('T * 'State) option) -> - state:'State -> ISeq<'T> - [] + + [] + val unfold : generator:('State -> ('T * 'State) option) -> state:'State -> ISeq<'T> + + [] val initInfinite : f:(int -> 'T) -> ISeq<'T> - [] + + [] val init : count:int -> f:(int -> 'T) -> ISeq<'T> - [] + + [] val iter : f:('T -> unit) -> source: ISeq<'T> -> unit - [] + + [] val tryHead : source: ISeq<'T> -> 'T option - [] + [] val iteri : f:(int -> 'T -> unit) -> source: ISeq<'T> -> unit - [] + + [] val exists : f:('T -> bool) -> source: ISeq<'T> -> bool - [] - val inline contains : - element:'T -> source: ISeq<'T> -> bool when 'T : equality - [] + + [] + val inline contains : element:'T -> source: ISeq<'T> -> bool when 'T : equality + + [] val forall : f:('T -> bool) -> source: ISeq<'T> -> bool [] @@ -514,18 +520,18 @@ namespace Microsoft.FSharp.Collections [] val inline map : f:('T -> 'U) -> source: ISeq<'T> -> ISeq<'U> - [] + [] val inline mapi : f:(int->'a->'b) -> source: ISeq<'a> -> ISeq<'b> val mapi_adapt : f:OptimizedClosures.FSharpFunc -> source: ISeq<'a> -> ISeq<'b> - [] + [] 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 [] @@ -549,16 +555,16 @@ namespace Microsoft.FSharp.Collections [] val inline truncate : truncateCount:int -> source:ISeq<'T> -> ISeq<'T> - [] + [] val inline indexed : source: ISeq<'a> -> ISeq - [] + [] val tryItem : index:int -> source: ISeq<'T> -> 'T option - [] + [] val tryPick : f:('T -> 'U option) -> source: ISeq<'T> -> Option<'U> - [] + [] val tryFind : f:('T -> bool) -> source: ISeq<'T> -> Option<'T> [] From b1f298d4151472eee8b4489e922df10623f570ee Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 05:04:32 -0500 Subject: [PATCH 229/286] inline except --- src/fsharp/FSharp.Core/seq.fs | 5 +++-- src/fsharp/FSharp.Core/seqcomposer.fs | 26 +++++++++++--------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 15 +++------------ 3 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 06e8bcb6726..9d7e7cb2e22 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1040,10 +1040,11 @@ namespace Microsoft.FSharp.Collections let arr,state = Array.mapFoldBack f array acc readonly arr, state - [] + [] let except (itemsToExclude: seq<'T>) (source: seq<'T>) = checkNonNull "itemsToExclude" itemsToExclude - source |> seqFactory (Composer.Seq.ExceptFactory itemsToExclude) + if isEmpty itemsToExclude then source else + source |> toComposer |> Composer.Seq.except itemsToExclude |> Upcast.enumerable [] let chunkBySize chunkSize (source : seq<_>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 0a9b00a6d12..a4d7d4a280e 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -124,10 +124,6 @@ namespace Microsoft.FSharp.Collections static member Combine (first:SeqFactory<'T,'U>) (second:SeqFactory<'U,'V>) : SeqFactory<'T,'V> = upcast ComposedFactory(first, second, first.PipeIdx+1) - and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) = - inherit SeqFactory<'T,'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = upcast Except (itemsToExclude, next) - and IdentityFactory<'T> () = inherit SeqFactory<'T,'T> () static let singleton : SeqFactory<'T,'T> = upcast (IdentityFactory<'T>()) @@ -189,17 +185,6 @@ namespace Microsoft.FSharp.Collections try this.OnDispose () finally next.OnDispose (&stopTailCall) - and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:Consumer<'T,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) - - let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural)) - - override __.ProcessNext (input:'T) : bool = - if cached.Value.Add input then - TailCall.avoid (next.ProcessNext input) - else - false - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = inherit SeqComponent<'First,'V>(Upcast.iCompletionChaining next) @@ -919,6 +904,17 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore + [] + let inline except (itemsToExclude: seq<'T>) (source:ISeq<'T>) : ISeq<'T> when 'T:equality = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { new SeqComponentSimpleValue<'T,'V,Lazy>> + (Upcast.iCompletionChaining next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with + override this.ProcessNext (input:'T) : bool = + if this.Value.Value.Add input then TailCall.avoid (next.ProcessNext input) + else false + }} + [] let exists f (source:ISeq<'T>) = source diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 974c730a217..3a7caadc3f1 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -97,11 +97,6 @@ namespace Microsoft.FSharp.Collections second: SeqFactory<'U,'V> -> SeqFactory<'T,'V> end - and ExceptFactory<'T when 'T : equality> = - class - inherit SeqFactory<'T,'T> - new : itemsToExclude:seq<'T> -> ExceptFactory<'T> - end and IdentityFactory<'T> = class inherit SeqFactory<'T,'T> @@ -168,13 +163,6 @@ namespace Microsoft.FSharp.Collections new : next:ICompletionChaining -> SeqComponent<'T,'U> end - and Except<'T,'V when 'T : equality> = - class - inherit SeqComponent<'T,'V> - new : itemsToExclude:seq<'T> * next: Consumer<'T,'V> -> - Except<'T,'V> - override ProcessNext : input:'T -> bool - end and Map2First<'First,'Second,'U,'V> = class inherit SeqComponent<'First,'V> @@ -505,6 +493,9 @@ namespace Microsoft.FSharp.Collections [] val iteri : f:(int -> 'T -> unit) -> source: ISeq<'T> -> unit + [] + val inline except : itemsToExclude:seq<'T> -> source:ISeq<'T> -> ISeq<'T> when 'T:equality + [] val exists : f:('T -> bool) -> source: ISeq<'T> -> bool From da4d93add46d809d679eb4afec6507fbb362dab2 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 05:27:40 -0500 Subject: [PATCH 230/286] inline pairwise --- src/fsharp/FSharp.Core/seq.fs | 4 +-- src/fsharp/FSharp.Core/seqcomposer.fs | 42 ++++++++++++++------------ src/fsharp/FSharp.Core/seqcomposer.fsi | 15 ++------- 3 files changed, 27 insertions(+), 34 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 9d7e7cb2e22..6edb97f3110 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -459,9 +459,9 @@ namespace Microsoft.FSharp.Collections if n <= 0 then empty else source |> toComposer |> Composer.Seq.truncate n |> Upcast.enumerable - [] + [] let pairwise<'T> (source:seq<'T>) : seq<'T*'T> = - source |> seqFactory (Composer.Seq.PairwiseFactory ()) + source |> toComposer |> Composer.Seq.pairwise |> Upcast.enumerable [] let scan<'T,'State> (folder:'State->'T->'State) (state:'State) (source:seq<'T>) : seq<'State> = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index a4d7d4a280e..3026661ab3b 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -146,10 +146,6 @@ namespace Microsoft.FSharp.Collections inherit SeqFactory<'First,'U> () override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, outOfBand, next, pipeIdx) - and PairwiseFactory<'T> () = - inherit SeqFactory<'T,'T*'T> () - override this.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T*'T,'V>) : Consumer<'T,'V> = upcast Pairwise (next) - and ISkipping = // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip // and it can only do it at the start of a sequence @@ -253,22 +249,6 @@ namespace Microsoft.FSharp.Collections override __.OnDispose () = input2.Dispose () - and Pairwise<'T,'V> (next:Consumer<'T*'T,'V>) = - inherit SeqComponent<'T,'V>(Upcast.iCompletionChaining next) - - let mutable isFirst = true - let mutable lastValue = Unchecked.defaultof<'T> - - override __.ProcessNext (input:'T) : bool = - if isFirst then - lastValue <- input - isFirst <- false - false - else - let currentPair = lastValue, input - lastValue <- input - TailCall.avoid (next.ProcessNext currentPair) - type SeqProcessNextStates = | InProcess = 0 | NotStarted = 1 @@ -1015,6 +995,28 @@ namespace Microsoft.FSharp.Collections if this.Value.Add (keyf input) then TailCall.avoid (next.ProcessNext input) else false } } + [] + let inline pairwise (source:ISeq<'T>) : ISeq<'T * 'T> = + source |> compose { new SeqFactory<'T,'T * 'T>() with + member __.Create _ _ next = + upcast { new SeqComponentSimpleValue<'T,'U,Values> + ( Upcast.iCompletionChaining next + , Values + ((* isFirst = _1*) true + ,(* lastValue = _2*) Unchecked.defaultof<'T> + ) + ) with + override self.ProcessNext (input:'T) : bool = + if (*isFirst*) self.Value._1 then + self.Value._2 (*lastValue*)<- input + self.Value._1 (*isFirst*)<- false + false + else + let currentPair = self.Value._2, input + self.Value._2 (*lastValue*)<- input + TailCall.avoid (next.ProcessNext currentPair) + }} + [] let inline scan (folder:'State->'T->'State) (initialState: 'State) (source:ISeq<'T>) :ISeq<'State> = source |> compose { new SeqFactory<'T,'State>() with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 3a7caadc3f1..391c67566cb 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -132,11 +132,6 @@ namespace Microsoft.FSharp.Collections input2:IEnumerable<'Second> -> Mapi2Factory<'First,'Second,'U> end - and PairwiseFactory<'T> = - class - inherit SeqFactory<'T,('T * 'T)> - new : unit -> PairwiseFactory<'T> - end and ISkipping = interface abstract member Skipping : unit -> bool @@ -208,13 +203,6 @@ namespace Microsoft.FSharp.Collections override OnDispose : unit -> unit override ProcessNext : input:'First -> bool end - and Pairwise<'T,'V> = - class - inherit SeqComponent<'T,'V> - new : next: Consumer<('T * 'T),'V> -> - Pairwise<'T,'V> - override ProcessNext : input:'T -> bool - end type SeqProcessNextStates = | InProcess = 0 | NotStarted = 1 @@ -525,6 +513,9 @@ namespace Microsoft.FSharp.Collections [] val inline distinctBy : keyf:('T->'Key) -> source: ISeq<'T> -> ISeq<'T> when 'Key:equality + [] + val inline pairwise : source:ISeq<'T> -> ISeq<'T * 'T> + [] val inline scan : folder:('State->'T->'State) -> initialState:'State -> source:ISeq<'T> -> ISeq<'State> From abf7d95f0112603a98f8cfdf124e45b19ff3faa4 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 10 Dec 2016 20:04:23 +1100 Subject: [PATCH 231/286] Simplified OnComplete/OnDispose - Removed Default implementations - Renamed methods on ICompletionChain - Simplied defined hierarch make choosing correct level to implement easier --- src/fsharp/FSharp.Core/seq.fs | 18 +- src/fsharp/FSharp.Core/seqcomposer.fs | 229 +++++++++++++------------ src/fsharp/FSharp.Core/seqcomposer.fsi | 133 ++++++++------ 3 files changed, 208 insertions(+), 172 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 6edb97f3110..c21ed8cf977 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -328,7 +328,7 @@ namespace Microsoft.FSharp.Collections source |> foreach (fun _ -> - { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with + { new Composer.Core.FolderWithOnComplete<'T, Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -374,7 +374,7 @@ namespace Microsoft.FSharp.Collections source1 |> foreach (fun halt -> - { new Composer.Core.Folder<'T,int> (0) with + { new Composer.Core.FolderWithOnComplete<'T,int> (0) with override this.ProcessNext value = if not (e2.MoveNext()) then this.Value <- 1 @@ -740,7 +740,7 @@ namespace Microsoft.FSharp.Collections let inline average (source: seq< ^a>) : ^a = source |> foreach (fun _ -> - { new Composer.Core.Folder<'a, Composer.Core.Values<'a, int>> (Composer.Core.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + { new Composer.Core.FolderWithOnComplete<'a, Composer.Core.Values<'a, int>> (Composer.Core.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 value this.Value._2 <- this.Value._2 + 1 @@ -755,7 +755,7 @@ namespace Microsoft.FSharp.Collections let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = source |> foreach (fun _ -> - { new Composer.Core.Folder<'T,Composer.Core.Values<'U, int>> (Composer.Core.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + { new Composer.Core.FolderWithOnComplete<'T,Composer.Core.Values<'U, int>> (Composer.Core.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = this.Value._1 <- Checked.(+) this.Value._1 (f value) this.Value._2 <- this.Value._2 + 1 @@ -775,7 +775,7 @@ namespace Microsoft.FSharp.Collections let inline min (source: seq<_>) = source |> foreach (fun _ -> - { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with + { new Composer.Core.FolderWithOnComplete<'T,Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -794,7 +794,7 @@ namespace Microsoft.FSharp.Collections let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = source |> foreach (fun _ -> - { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + { new Composer.Core.FolderWithOnComplete<'T,Composer.Core.Values> (Composer.Core.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with override this.ProcessNext value = match this.Value._1, f value with | true, valueU -> @@ -833,7 +833,7 @@ namespace Microsoft.FSharp.Collections let inline max (source: seq<_>) = source |> foreach (fun _ -> - { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with + { new Composer.Core.FolderWithOnComplete<'T,Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false @@ -852,7 +852,7 @@ namespace Microsoft.FSharp.Collections let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = source |> foreach (fun _ -> - { new Composer.Core.Folder<'T,Composer.Core.Values> (Composer.Core.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + { new Composer.Core.FolderWithOnComplete<'T,Composer.Core.Values> (Composer.Core.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with override this.ProcessNext value = match this.Value._1, f value with | true, valueU -> @@ -985,7 +985,7 @@ namespace Microsoft.FSharp.Collections let exactlyOne (source : seq<_>) = source |> foreach (fun halt -> - { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values(true, Unchecked.defaultof<'T>, false)) with + { new Composer.Core.FolderWithOnComplete<'T, Composer.Core.Values> (Composer.Core.Values(true, Unchecked.defaultof<'T>, false)) with override this.ProcessNext value = if this.Value._1 then this.Value._1 <- false diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 3026661ab3b..155343fff88 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -20,65 +20,105 @@ namespace Microsoft.FSharp.Collections open IEnumerator module Core = - type PipeIdx = int + [] + type NoValue = struct end - type ICompletionChaining = - abstract OnComplete : stopTailCall:byref * PipeIdx -> unit - abstract OnDispose : stopTailCall:byref -> unit + [] + 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 ICompletionChain = + abstract ChainComplete : stopTailCall:byref * PipeIdx -> unit + abstract ChainDispose : stopTailCall:byref -> unit + [] type Consumer<'T,'U> () = abstract ProcessNext : input:'T -> bool - abstract OnComplete : PipeIdx -> unit - abstract OnDispose : unit -> unit + interface ICompletionChain with + member this.ChainComplete (_,_) = () + member this.ChainDispose _ = () - default __.OnComplete _ = () - default __.OnDispose () = () + [] + type ConsumerWithState<'T,'U,'Value> = + inherit Consumer<'T,'U> - interface ICompletionChaining with - member this.OnComplete (_, terminatingIdx) = - this.OnComplete terminatingIdx + val mutable Value : 'Value + + new (init) = { + Value = init + } - member this.OnDispose _ = - try this.OnDispose () - finally () + [] + type ConsumerChainedWithState<'T,'U,'Value> = + inherit ConsumerWithState<'T,'U,'Value> - [] - type Values<'a,'b> = - val mutable _1 : 'a - val mutable _2 : 'b + val private Next : ICompletionChain - new (a:'a, b: 'b) = { - _1 = a - _2 = b + new (next:ICompletionChain, init) = { + inherit ConsumerWithState<'T,'U,'Value> (init) + Next = next } - [] - type Values<'a,'b,'c> = - val mutable _1 : 'a - val mutable _2 : 'b - val mutable _3 : 'c + interface ICompletionChain with + member this.ChainComplete (stopTailCall, terminatingIdx) = + this.Next.ChainComplete (&stopTailCall, terminatingIdx) + member this.ChainDispose stopTailCall = + this.Next.ChainDispose (&stopTailCall) - new (a:'a, b:'b, c:'c) = { - _1 = a - _2 = b - _3 = c - } + [] + type ConsumerChained<'T,'U>(next:ICompletionChain) = + inherit ConsumerChainedWithState<'T,'U,NoValue>(next, Unchecked.defaultof) + + [] + type ConsumerChainedWithStateAndCleanup<'T,'U,'Value> (next, init) = + inherit ConsumerChainedWithState<'T,'U,'Value>(next, init) + + abstract OnComplete : PipeIdx -> unit + abstract OnDispose : unit -> unit + + interface ICompletionChain with + member this.ChainComplete (stopTailCall, terminatingIdx) = + this.OnComplete terminatingIdx + next.ChainComplete (&stopTailCall, terminatingIdx) + member this.ChainDispose stopTailCall = + try this.OnDispose () + finally next.ChainDispose (&stopTailCall) [] - type Folder<'T, 'U> = - inherit Consumer<'T,'T> + type ConsumerChainedWithCleanup<'T,'U>(next:ICompletionChain) = + inherit ConsumerChainedWithStateAndCleanup<'T,'U,NoValue>(next, Unchecked.defaultof) - val mutable Value : 'U + [] + type Folder<'T,'U>(init) = + inherit ConsumerWithState<'T,'T,'U>(init) - new (init) = { - inherit Consumer<'T,'T>() - Value = init - } + [] + type FolderWithOnComplete<'T, 'U>(init) = + inherit Folder<'T,'U>(init) + + abstract OnComplete : PipeIdx -> unit + + interface ICompletionChain with + member this.ChainComplete (stopTailCall, terminatingIdx) = + this.OnComplete terminatingIdx + member this.ChainDispose _ = () [] type SeqFactory<'T,'U> () = @@ -109,7 +149,7 @@ namespace Microsoft.FSharp.Collections let inline enumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) let inline enumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline enumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline iCompletionChaining (t:#ICompletionChaining) : ICompletionChaining = (# "" t : ICompletionChaining #) + let inline iCompletionChain (t:#ICompletionChain) : ICompletionChain = (# "" t : ICompletionChain #) module internal Seq = type ComposedFactory<'T,'U,'V> private (first:SeqFactory<'T,'U>, second:SeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = @@ -151,38 +191,8 @@ namespace Microsoft.FSharp.Collections // and it can only do it at the start of a sequence abstract Skipping : unit -> bool - and [] SeqComponentSimple<'T,'U> (next:ICompletionChaining) = - inherit Consumer<'T,'U>() - - interface ICompletionChaining with - member this.OnComplete (stopTailCall, terminatingIdx) = - next.OnComplete (&stopTailCall, terminatingIdx) - member this.OnDispose stopTailCall = - next.OnDispose (&stopTailCall) - - and [] SeqComponentSimpleValue<'T,'U,'Value> = - inherit SeqComponentSimple<'T,'U> - - val mutable Value : 'Value - - new (next, init) = { - inherit SeqComponentSimple<'T,'U>(next) - Value = init - } - - and [] SeqComponent<'T,'U> (next:ICompletionChaining) = - inherit Consumer<'T,'U>() - - interface ICompletionChaining with - member this.OnComplete (stopTailCall, terminatingIdx) = - this.OnComplete terminatingIdx - next.OnComplete (&stopTailCall, terminatingIdx) - member this.OnDispose stopTailCall = - try this.OnDispose () - finally next.OnDispose (&stopTailCall) - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(Upcast.iCompletionChaining next) + inherit ConsumerChainedWithCleanup<'First,'V>(Upcast.iCompletionChain next) let input2 = enumerable2.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -194,11 +204,12 @@ namespace Microsoft.FSharp.Collections outOfBand.StopFurtherProcessing pipeIdx false + override __.OnComplete _ = () override __.OnDispose () = input2.Dispose () and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'Second,'V>(Upcast.iCompletionChaining next) + inherit ConsumerChainedWithCleanup<'Second,'V>(Upcast.iCompletionChain next) let input1 = enumerable1.GetEnumerator () let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map @@ -210,11 +221,12 @@ namespace Microsoft.FSharp.Collections outOfBand.StopFurtherProcessing pipeIdx false + override __.OnComplete _ = () override __.OnDispose () = input1.Dispose () and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(Upcast.iCompletionChaining next) + inherit ConsumerChainedWithCleanup<'First,'V>(Upcast.iCompletionChain next) let input2 = enumerable2.GetEnumerator () let input3 = enumerable3.GetEnumerator () @@ -227,12 +239,13 @@ namespace Microsoft.FSharp.Collections outOfBand.StopFurtherProcessing pipeIdx false + override __.OnComplete _ = () override __.OnDispose () = try input2.Dispose () finally input3.Dispose () and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit SeqComponent<'First,'V>(Upcast.iCompletionChaining next) + inherit ConsumerChainedWithCleanup<'First,'V>(Upcast.iCompletionChain next) let mutable idx = 0 let input2 = enumerable2.GetEnumerator () @@ -246,6 +259,7 @@ namespace Microsoft.FSharp.Collections outOfBand.StopFurtherProcessing pipeIdx false + override __.OnComplete _ = () override __.OnDispose () = input2.Dispose () @@ -333,11 +347,11 @@ namespace Microsoft.FSharp.Collections try executeOn pipeline consumer let mutable stopTailCall = () - (Upcast.iCompletionChaining consumer).OnComplete (&stopTailCall, pipeline.HaltedIdx) + (Upcast.iCompletionChain consumer).ChainComplete (&stopTailCall, pipeline.HaltedIdx) result finally let mutable stopTailCall = () - (Upcast.iCompletionChaining consumer).OnDispose (&stopTailCall) + (Upcast.iCompletionChain consumer).ChainDispose (&stopTailCall) module Enumerable = type Empty<'T>() = @@ -356,11 +370,11 @@ namespace Microsoft.FSharp.Collections static member Element = element [] - type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ICompletionChaining) = + type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ICompletionChain) = interface IDisposable with member __.Dispose() : unit = let mutable stopTailCall = () - seqComponent.OnDispose (&stopTailCall) + seqComponent.ChainDispose (&stopTailCall) interface IEnumerator with member this.Current : obj = box ((Upcast.enumerator this)).Current @@ -409,7 +423,7 @@ namespace Microsoft.FSharp.Collections else result.SeqState <- SeqProcessNextStates.Finished let mutable stopTailCall = () - (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) + (Upcast.iCompletionChain seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -423,7 +437,7 @@ namespace Microsoft.FSharp.Collections source.Dispose () finally let mutable stopTailCall = () - (Upcast.iCompletionChaining seqComponent).OnDispose (&stopTailCall) + (Upcast.iCompletionChain seqComponent).ChainDispose (&stopTailCall) and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqFactory<'T,'U>) = inherit EnumerableBase<'U>() @@ -559,7 +573,7 @@ namespace Microsoft.FSharp.Collections else result.SeqState <- SeqProcessNextStates.Finished let mutable stopTailCall = () - (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) + (Upcast.iCompletionChain seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -611,7 +625,7 @@ namespace Microsoft.FSharp.Collections | _ -> result.SeqState <- SeqProcessNextStates.Finished let mutable stopTailCall = () - (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) + (Upcast.iCompletionChain seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -725,7 +739,7 @@ namespace Microsoft.FSharp.Collections else result.SeqState <- SeqProcessNextStates.Finished let mutable stopTailCall = () - (Upcast.iCompletionChaining seqComponent).OnComplete (&stopTailCall, result.HaltedIdx) + (Upcast.iCompletionChain seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -888,8 +902,8 @@ namespace Microsoft.FSharp.Collections let inline except (itemsToExclude: seq<'T>) (source:ISeq<'T>) : ISeq<'T> when 'T:equality = source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = - upcast { new SeqComponentSimpleValue<'T,'V,Lazy>> - (Upcast.iCompletionChaining next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with + upcast { new ConsumerChainedWithState<'T,'V,Lazy>> + (Upcast.iCompletionChain next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = if this.Value.Value.Add input then TailCall.avoid (next.ProcessNext input) else false @@ -935,7 +949,7 @@ namespace Microsoft.FSharp.Collections let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = - upcast { new SeqComponentSimple<'T,'V>(Upcast.iCompletionChaining next) with + upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with member __.ProcessNext input = if f input then TailCall.avoid (next.ProcessNext input) else false } } @@ -944,7 +958,7 @@ namespace Microsoft.FSharp.Collections let inline map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = source |> compose { new SeqFactory<'T,'U>() with member __.Create _ _ next = - upcast { new SeqComponentSimple<'T,'V>(Upcast.iCompletionChaining next) with + upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with member __.ProcessNext input = TailCall.avoid (next.ProcessNext (f input)) } } @@ -952,7 +966,7 @@ namespace Microsoft.FSharp.Collections let inline mapi f source = source |> compose { new SeqFactory<'T,'U>() with member __.Create _ _ next = - upcast { new SeqComponentSimpleValue<'T,'V,int>(Upcast.iCompletionChaining next, -1) with + upcast { new ConsumerChainedWithState<'T,'V,int>(Upcast.iCompletionChain next, -1) with override this.ProcessNext (input:'T) : bool = this.Value <- this.Value + 1 TailCall.avoid (next.ProcessNext (f this.Value input)) } } @@ -960,7 +974,7 @@ namespace Microsoft.FSharp.Collections let mapi_adapt (f:OptimizedClosures.FSharpFunc<_,_,_>) source = source |> compose { new SeqFactory<'T,'U>() with member __.Create _ _ next = - upcast { new SeqComponentSimpleValue<'T,'V,int>(Upcast.iCompletionChaining next, -1) with + upcast { new ConsumerChainedWithState<'T,'V,int>(Upcast.iCompletionChain next, -1) with override this.ProcessNext (input:'T) : bool = this.Value <- this.Value + 1 TailCall.avoid (next.ProcessNext (f.Invoke (this.Value, input))) } } @@ -969,7 +983,7 @@ namespace Microsoft.FSharp.Collections let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = source |> compose { new SeqFactory<'T,'U>() with member __.Create _ _ next = - upcast { new SeqComponentSimple<'T,'V>(Upcast.iCompletionChaining next) with + upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with member __.ProcessNext input = match f input with | Some value -> TailCall.avoid (next.ProcessNext value) @@ -979,8 +993,8 @@ namespace Microsoft.FSharp.Collections let inline distinct (source:ISeq<'T>) : ISeq<'T> when 'T:equality = source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = - upcast { new SeqComponentSimpleValue<'T,'V,HashSet<'T>> - (Upcast.iCompletionChaining next,(HashSet<'T>(HashIdentity.Structural<'T>))) with + upcast { new ConsumerChainedWithState<'T,'V,HashSet<'T>> + (Upcast.iCompletionChain next,(HashSet<'T>(HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = if this.Value.Add input then TailCall.avoid (next.ProcessNext input) else false } } @@ -989,8 +1003,8 @@ namespace Microsoft.FSharp.Collections let inline distinctBy (keyf:'T->'Key) (source:ISeq<'T>) :ISeq<'T> when 'Key:equality = source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = - upcast { new SeqComponentSimpleValue<'T,'V,HashSet<'Key>> - (Upcast.iCompletionChaining next,(HashSet<'Key>(HashIdentity.Structural<'Key>))) with + upcast { new ConsumerChainedWithState<'T,'V,HashSet<'Key>> + (Upcast.iCompletionChain next,(HashSet<'Key>(HashIdentity.Structural<'Key>))) with override this.ProcessNext (input:'T) : bool = if this.Value.Add (keyf input) then TailCall.avoid (next.ProcessNext input) else false } } @@ -999,8 +1013,8 @@ namespace Microsoft.FSharp.Collections let inline pairwise (source:ISeq<'T>) : ISeq<'T * 'T> = source |> compose { new SeqFactory<'T,'T * 'T>() with member __.Create _ _ next = - upcast { new SeqComponentSimpleValue<'T,'U,Values> - ( Upcast.iCompletionChaining next + upcast { new ConsumerChainedWithState<'T,'U,Values> + ( Upcast.iCompletionChain next , Values ((* isFirst = _1*) true ,(* lastValue = _2*) Unchecked.defaultof<'T> @@ -1021,7 +1035,7 @@ namespace Microsoft.FSharp.Collections let inline scan (folder:'State->'T->'State) (initialState: 'State) (source:ISeq<'T>) :ISeq<'State> = source |> compose { new SeqFactory<'T,'State>() with member __.Create _ _ next = - upcast { new SeqComponentSimpleValue<'T,'V,'State>(Upcast.iCompletionChaining next, initialState) with + upcast { new ConsumerChainedWithState<'T,'V,'State>(Upcast.iCompletionChain next, initialState) with override this.ProcessNext (input:'T) : bool = this.Value <- folder this.Value input TailCall.avoid (next.ProcessNext this.Value) } } @@ -1030,7 +1044,7 @@ namespace Microsoft.FSharp.Collections let scan_adapt (folder:OptimizedClosures.FSharpFunc<'State,'T,'State>) (initialState: 'State) (source:ISeq<'T>) :ISeq<'State> = source |> compose { new SeqFactory<'T,'State>() with member __.Create _ _ next = - upcast { new SeqComponentSimpleValue<'T,'V,'State>(Upcast.iCompletionChaining next, initialState) with + upcast { new ConsumerChainedWithState<'T,'V,'State>(Upcast.iCompletionChain next, initialState) with override this.ProcessNext (input:'T) : bool = this.Value <- folder.Invoke(this.Value,input) TailCall.avoid (next.ProcessNext this.Value) } } @@ -1040,7 +1054,7 @@ namespace Microsoft.FSharp.Collections source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = upcast { - new SeqComponentSimpleValue<'T,'U,int>(Upcast.iCompletionChaining next,(*count*)0) with + new ConsumerChainedWithStateAndCleanup<'T,'U,int>(Upcast.iCompletionChain next,(*count*)0) with override self.ProcessNext (input:'T) : bool = if (*count*) self.Value < skipCount then @@ -1049,6 +1063,7 @@ namespace Microsoft.FSharp.Collections else TailCall.avoid (next.ProcessNext input) + override self.OnDispose () = () override self.OnComplete _ = if (*count*) self.Value < skipCount then let x = skipCount - self.Value @@ -1057,7 +1072,7 @@ namespace Microsoft.FSharp.Collections interface ISkipping with member self.Skipping () = - let self = self :?> SeqComponentSimpleValue<'T,'U,int> + let self = self :?> ConsumerChainedWithState<'T,'U,int> if (*count*) self.Value < skipCount then self.Value <- self.Value + 1 true @@ -1069,7 +1084,7 @@ namespace Microsoft.FSharp.Collections let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = - upcast { new SeqComponentSimpleValue<'T,'V,bool>(Upcast.iCompletionChaining next,true) with + upcast { new ConsumerChainedWithState<'T,'V,bool>(Upcast.iCompletionChain next,true) with override self.ProcessNext (input:'T) : bool = if self.Value (*skip*) then self.Value <- predicate input @@ -1085,7 +1100,7 @@ namespace Microsoft.FSharp.Collections source |> compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipelineIdx next = upcast { - new SeqComponentSimpleValue<'T,'U,int>(Upcast.iCompletionChaining next,(*count*)0) with + new ConsumerChainedWithStateAndCleanup<'T,'U,int>(Upcast.iCompletionChain next,(*count*)0) with override self.ProcessNext (input:'T) : bool = if (*count*) self.Value < takeCount then self.Value <- self.Value + 1 @@ -1096,6 +1111,7 @@ namespace Microsoft.FSharp.Collections outOfBand.StopFurtherProcessing pipelineIdx false + override this.OnDispose () = () override this.OnComplete terminatingIdx = if terminatingIdx < pipelineIdx && this.Value < takeCount then let x = takeCount - this.Value @@ -1107,7 +1123,7 @@ namespace Microsoft.FSharp.Collections let inline takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipeIdx next = - upcast { new SeqComponent<'T,'V>(Upcast.iCompletionChaining next) with + upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with override __.ProcessNext (input:'T) : bool = if predicate input then TailCall.avoid (next.ProcessNext input) @@ -1120,7 +1136,7 @@ namespace Microsoft.FSharp.Collections let inline tail (source:ISeq<'T>) :ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = - upcast { new SeqComponentSimpleValue<'T,'V,bool>(Upcast.iCompletionChaining next,(*first*) true) with + upcast { new ConsumerChainedWithStateAndCleanup<'T,'V,bool>(Upcast.iCompletionChain next,(*first*) true) with override self.ProcessNext (input:'T) : bool = if (*first*) self.Value then self.Value <- false @@ -1128,6 +1144,7 @@ namespace Microsoft.FSharp.Collections else TailCall.avoid (next.ProcessNext input) + override self.OnDispose () = () override self.OnComplete _ = if (*first*) self.Value then invalidArg "source" (SR.GetString(SR.notEnoughElements)) @@ -1138,7 +1155,7 @@ namespace Microsoft.FSharp.Collections source |> compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipeIdx next = upcast { - new SeqComponentSimpleValue<'T,'U,int>(Upcast.iCompletionChaining next,(*count*)0) with + new ConsumerChainedWithState<'T,'U,int>(Upcast.iCompletionChain next,(*count*)0) with override self.ProcessNext (input:'T) : bool = if (*count*) self.Value < truncateCount then self.Value <- self.Value + 1 @@ -1190,8 +1207,8 @@ namespace Microsoft.FSharp.Collections source |> compose { new SeqFactory<'T,'T[]>() with member __.Create outOfBand pipeIdx next = upcast { - new SeqComponentSimpleValue<'T,'U,Values<'T[],int,int>> - ( Upcast.iCompletionChaining next + new ConsumerChainedWithState<'T,'U,Values<'T[],int,int>> + ( Upcast.iCompletionChain next , Values<'T[],int,int> ((*circularBuffer = _1 *) Array.zeroCreateUnchecked windowSize ,(* idx = _2 *) 0 diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 391c67566cb..9b66a5e49b1 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -11,64 +11,104 @@ namespace Microsoft.FSharp.Collections [] module Composer = 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 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 - /// ICompletionChaining is used to correctly handle cleaning up of the pipeline. A + type IOutOfBand = + abstract StopFurtherProcessing : PipeIdx -> unit + + /// ICompletionChain is used to correctly handle cleaning up of the pipeline. A /// base implementation is provided in Consumer, and should not be overwritten. Consumer /// provides it's own OnComplete and OnDispose function which should be used to handle /// a particular consumers cleanup. - type ICompletionChaining = + type ICompletionChain = /// OnComplete is used to determine if the object has been processed correctly, /// and possibly throw exceptions to denote incorrect application (i.e. such as a Take /// operation which didn't have a source at least as large as was required). It is /// not called in the case of an exception being thrown whilst the stream is still /// being processed. - abstract OnComplete : stopTailCall:byref*PipeIdx -> unit + 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 OnDispose : stopTailCall:byref -> unit - - type IOutOfBand = - abstract StopFurtherProcessing : PipeIdx -> unit + abstract ChainDispose : stopTailCall:byref -> unit /// Consumer is the base class of all elements within the pipeline [] type Consumer<'T,'U> = - interface ICompletionChaining + interface ICompletionChain new : unit -> Consumer<'T,'U> abstract member ProcessNext : input:'T -> bool - abstract member OnComplete : PipeIdx -> unit - abstract member OnDispose : unit -> unit - override OnComplete : PipeIdx -> unit - override OnDispose : unit -> unit - /// 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 + [] + type ConsumerWithState<'T,'U,'Value> = + inherit Consumer<'T,'U> + val mutable Value : 'Value + new : init:'Value -> ConsumerWithState<'T,'U,'Value> - /// 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 + [] + type ConsumerChainedWithState<'T,'U,'Value> = + inherit ConsumerWithState<'T,'U,'Value> + interface ICompletionChain + val private Next : ICompletionChain + new : next:ICompletionChain * init:'Value -> ConsumerChainedWithState<'T,'U,'Value> + + [] + type ConsumerChained<'T,'U> = + inherit ConsumerChainedWithState<'T,'U,NoValue> + new : next:ICompletionChain -> ConsumerChained<'T,'U> + + [] + type ConsumerChainedWithStateAndCleanup<'T,'U,'Value> = + inherit ConsumerChainedWithState<'T,'U,'Value> + interface ICompletionChain + + abstract OnComplete : PipeIdx -> unit + abstract OnDispose : unit -> unit + + new : next:ICompletionChain * init:'Value -> ConsumerChainedWithStateAndCleanup<'T,'U,'Value> + + [] + type ConsumerChainedWithCleanup<'T,'U> = + inherit ConsumerChainedWithStateAndCleanup<'T,'U,NoValue> + new : next:ICompletionChain -> ConsumerChainedWithCleanup<'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 ForEach function. [] - type Folder<'T,'U> = - inherit Consumer<'T,'T> - new : init:'U -> Folder<'T,'U> - val mutable Value: 'U + type Folder<'T,'Value> = + inherit ConsumerWithState<'T,'T,'Value> + new : init:'Value -> Folder<'T,'Value> + + [] + type FolderWithOnComplete<'T, 'Value> = + inherit Folder<'T,'Value> + interface ICompletionChain + + abstract OnComplete : PipeIdx -> unit + + new : init:'Value -> FolderWithOnComplete<'T,'Value> [] type SeqFactory<'T,'U> = @@ -137,30 +177,9 @@ namespace Microsoft.FSharp.Collections abstract member Skipping : unit -> bool end - and [] SeqComponentSimple<'T,'U> = - class - inherit Consumer<'T,'U> - interface ICompletionChaining - new : next:ICompletionChaining -> SeqComponentSimple<'T,'U> - end - - and [] SeqComponentSimpleValue<'T,'U,'Value> = - class - inherit SeqComponentSimple<'T,'U> - val mutable Value : 'Value - new : next:ICompletionChaining*value:'Value -> SeqComponentSimpleValue<'T,'U,'Value> - end - - and [] SeqComponent<'T,'U> = - class - inherit Consumer<'T,'U> - interface ICompletionChaining - new : next:ICompletionChaining -> - SeqComponent<'T,'U> - end and Map2First<'First,'Second,'U,'V> = class - inherit SeqComponent<'First,'V> + inherit ConsumerChainedWithCleanup<'First,'V> new : map:('First -> 'Second -> 'U) * enumerable2:IEnumerable<'Second> * outOfBand: IOutOfBand * @@ -171,7 +190,7 @@ namespace Microsoft.FSharp.Collections end and Map2Second<'First,'Second,'U,'V> = class - inherit SeqComponent<'Second,'V> + inherit ConsumerChainedWithCleanup<'Second,'V> new : map:('First -> 'Second -> 'U) * enumerable1:IEnumerable<'First> * outOfBand: IOutOfBand * @@ -182,7 +201,7 @@ namespace Microsoft.FSharp.Collections end and Map3<'First,'Second,'Third,'U,'V> = class - inherit SeqComponent<'First,'V> + inherit ConsumerChainedWithCleanup<'First,'V> new : map:('First -> 'Second -> 'Third -> 'U) * enumerable2:IEnumerable<'Second> * enumerable3:IEnumerable<'Third> * @@ -194,7 +213,7 @@ namespace Microsoft.FSharp.Collections end and Mapi2<'First,'Second,'U,'V> = class - inherit SeqComponent<'First,'V> + inherit ConsumerChainedWithCleanup<'First,'V> new : map:(int -> 'First -> 'Second -> 'U) * enumerable2:IEnumerable<'Second> * outOfBand: IOutOfBand * @@ -280,7 +299,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerator interface IDisposable new : result: Result<'T> * - seqComponent: ICompletionChaining -> + seqComponent: ICompletionChain -> EnumeratorBase<'T> end and [] EnumerableBase<'T> = From 1a5b520780052fb315d013084b98b6f9b1958d2d Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Mon, 12 Dec 2016 22:25:47 -0500 Subject: [PATCH 232/286] remove parens --- src/fsharp/FSharp.Core/seqcomposer.fs | 38 +++++++++++++-------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 155343fff88..066035e94c8 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -86,7 +86,7 @@ namespace Microsoft.FSharp.Collections type ConsumerChained<'T,'U>(next:ICompletionChain) = inherit ConsumerChainedWithState<'T,'U,NoValue>(next, Unchecked.defaultof) - [] + [] type ConsumerChainedWithStateAndCleanup<'T,'U,'Value> (next, init) = inherit ConsumerChainedWithState<'T,'U,'Value>(next, init) @@ -830,7 +830,7 @@ namespace Microsoft.FSharp.Collections member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (Upcast.enumerable this)) - [] + [] let toComposer (source:seq<'T>) : ISeq<'T> = match source with | :? ISeq<'T> as s -> s @@ -845,24 +845,24 @@ namespace Microsoft.FSharp.Collections let inline compose (factory:#SeqFactory<_,_>) (source:ISeq<'T>) = source.Compose factory - [] + [] let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance - [] + [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = Upcast.seq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) - [] + [] let initInfinite<'T> (f:int->'T) : ISeq<'T> = Upcast.seq (new Init.EnumerableDecider<'T>(Nullable (), f)) - [] + [] 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)) - [] + [] let iter f (source:ISeq<'T>) = source |> foreach (fun _ -> @@ -872,7 +872,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore - [] + [] let tryHead (source:ISeq<'T>) = source |> foreach (fun halt -> @@ -885,7 +885,7 @@ namespace Microsoft.FSharp.Collections - [] + [] let iteri f (source:ISeq<'T>) = let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f @@ -909,7 +909,7 @@ namespace Microsoft.FSharp.Collections else false }} - [] + [] let exists f (source:ISeq<'T>) = source |> foreach (fun halt -> @@ -921,7 +921,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun exists -> exists.Value - [] + [] let inline contains element (source:ISeq<'T>) = source |> foreach (fun halt -> @@ -933,7 +933,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun contains -> contains.Value - [] + [] let forall f (source:ISeq<'T>) = source |> foreach (fun halt -> @@ -945,7 +945,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun forall -> forall.Value - [] + [] let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = @@ -954,7 +954,7 @@ namespace Microsoft.FSharp.Collections 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 |> compose { new SeqFactory<'T,'U>() with member __.Create _ _ next = @@ -962,7 +962,7 @@ namespace Microsoft.FSharp.Collections member __.ProcessNext input = TailCall.avoid (next.ProcessNext (f input)) } } - [] + [] let inline mapi f source = source |> compose { new SeqFactory<'T,'U>() with member __.Create _ _ next = @@ -979,7 +979,7 @@ namespace Microsoft.FSharp.Collections this.Value <- this.Value + 1 TailCall.avoid (next.ProcessNext (f.Invoke (this.Value, input))) } } - [] + [] let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = source |> compose { new SeqFactory<'T,'U>() with member __.Create _ _ next = @@ -1167,7 +1167,7 @@ namespace Microsoft.FSharp.Collections false }} - [] + [] let inline indexed source = mapi (fun i x -> i,x) source @@ -1176,7 +1176,7 @@ namespace Microsoft.FSharp.Collections if index < 0 then None else source |> skip index |> tryHead - [] + [] let tryPick f (source:ISeq<'T>) = source |> foreach (fun halt -> @@ -1190,7 +1190,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun pick -> pick.Value - [] + [] let tryFind f (source:ISeq<'T>) = source |> foreach (fun halt -> From 6ba943851bf39bcc120ec512928234df6a6b853c Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Mon, 12 Dec 2016 22:48:13 -0500 Subject: [PATCH 233/286] inline fold --- src/fsharp/FSharp.Core/seq.fs | 13 ++++--------- src/fsharp/FSharp.Core/seqcomposer.fs | 12 ++++++++++++ src/fsharp/FSharp.Core/seqcomposer.fsi | 5 ++++- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index c21ed8cf977..a7f78713ff4 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -284,17 +284,12 @@ namespace Microsoft.FSharp.Collections state <- state + 1 state - [] - let fold<'T,'State> f (x:'State) (source:seq<'T>) = + [] + let fold<'T,'State> (f:'State->'T->'State) (x:'State) (source:seq<'T>) = let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) + source |> toComposer + |> Composer.Seq.fold<'T,'State>(fun (a:'State) (b:'T) -> f.Invoke(a,b)) x - source - |> foreach (fun _ -> - { new Composer.Core.Folder<'T,'State> (x) with - override this.ProcessNext value = - this.Value <- f.Invoke (this.Value, value) - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun folded -> folded.Value source |> foreach (fun _ -> diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 066035e94c8..49094b7d996 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -848,6 +848,18 @@ namespace Microsoft.FSharp.Collections [] let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance + + [] + let inline fold<'T,'State> (f:'State->'T->'State) (seed:'State) (source:ISeq<'T>) : 'State = + source + |> foreach (fun _ -> + { new Folder<'T,'State>(seed) with + override this.ProcessNext value = + this.Value <- f this.Value value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + }) + |> fun folded -> folded.Value + [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = Upcast.seq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 9b66a5e49b1..4959e41a0c4 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -78,7 +78,7 @@ namespace Microsoft.FSharp.Collections inherit ConsumerChainedWithState<'T,'U,NoValue> new : next:ICompletionChain -> ConsumerChained<'T,'U> - [] + [] type ConsumerChainedWithStateAndCleanup<'T,'U,'Value> = inherit ConsumerChainedWithState<'T,'U,'Value> interface ICompletionChain @@ -482,6 +482,9 @@ namespace Microsoft.FSharp.Collections [] val empty<'T> : ISeq<'T> + [] + val inline fold<'T,'State> : f:('State->'T->'State) -> seed:'State -> source:ISeq<'T> -> 'State + [] val unfold : generator:('State -> ('T * 'State) option) -> state:'State -> ISeq<'T> From 7fa959351aaf07b98d211c328b470c7970eeaad8 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Mon, 12 Dec 2016 23:37:12 -0500 Subject: [PATCH 234/286] inline sum --- src/fsharp/FSharp.Core/seq.fs | 10 ++-------- src/fsharp/FSharp.Core/seqcomposer.fs | 12 ++++++++++++ src/fsharp/FSharp.Core/seqcomposer.fsi | 5 +++++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index a7f78713ff4..313400601d1 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -711,15 +711,9 @@ namespace Microsoft.FSharp.Collections then mkDelayedSeq (fun () -> countByValueType keyf source) else mkDelayedSeq (fun () -> countByRefType keyf source) - [] + [] let inline sum (source:seq<'a>) : 'a = - source - |> foreach (fun _ -> - { new Composer.Core.Folder<'a,'a> (LanguagePrimitives.GenericZero) with - override this.ProcessNext value = - this.Value <- Checked.(+) this.Value value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun sum -> sum.Value + source |> toComposer |> Composer.Seq.sum [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 49094b7d996..2748c02c24c 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -1107,6 +1107,18 @@ namespace Microsoft.FSharp.Collections else TailCall.avoid (next.ProcessNext input) }} + [] + let inline sum (source:ISeq< ^T>) : ^T + when ^T:(static member Zero : ^T) + and ^T:(static member (+) : ^T * ^T -> ^T) = + source + |> foreach (fun _ -> + { new Folder< ^T,^T> (LanguagePrimitives.GenericZero) with + override this.ProcessNext value = + this.Value <- Checked.(+) this.Value value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun sum -> sum.Value + [] let inline take (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 4959e41a0c4..a0f456daf53 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -547,6 +547,11 @@ namespace Microsoft.FSharp.Collections [] 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 take : takeCount:int -> source:ISeq<'T> -> ISeq<'T> From 84a3f38bffe9293cb186bc64393a841e73b30279 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Mon, 12 Dec 2016 23:52:20 -0500 Subject: [PATCH 235/286] inline sumBy & inline average --- src/fsharp/FSharp.Core/seq.fs | 31 ++++++-------------------- src/fsharp/FSharp.Core/seqcomposer.fs | 31 +++++++++++++++++++++++++- src/fsharp/FSharp.Core/seqcomposer.fsi | 13 ++++++++++- 3 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 313400601d1..3f6299af3e2 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -712,33 +712,16 @@ namespace Microsoft.FSharp.Collections else mkDelayedSeq (fun () -> countByRefType keyf source) [] - let inline sum (source:seq<'a>) : 'a = + let sum (source:seq<'a>) : 'a = source |> toComposer |> Composer.Seq.sum - [] - let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = - source - |> foreach (fun _ -> - { new Composer.Core.Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with - override this.ProcessNext value = - this.Value <- Checked.(+) this.Value (f value) - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun sum -> sum.Value + [] + let sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = + source |> toComposer |> Composer.Seq.sumBy f - [] - let inline average (source: seq< ^a>) : ^a = - source - |> foreach (fun _ -> - { new Composer.Core.FolderWithOnComplete<'a, Composer.Core.Values<'a, int>> (Composer.Core.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with - override this.ProcessNext value = - this.Value._1 <- Checked.(+) this.Value._1 value - this.Value._2 <- this.Value._2 + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - - member this.OnComplete _ = - if this.Value._2 = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - |> fun total -> LanguagePrimitives.DivideByInt< ^a> total.Value._1 total.Value._2 + [] + let average (source: seq< ^a>) : ^a = + source |> toComposer |> Composer.Seq.average [] let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 2748c02c24c..6d76b34b037 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -845,10 +845,27 @@ namespace Microsoft.FSharp.Collections let inline compose (factory:#SeqFactory<_,_>) (source:ISeq<'T>) = source.Compose factory + [] + let 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) = + source + |> foreach (fun _ -> + { new FolderWithOnComplete< ^T, Values< ^T, int>> (Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + override this.ProcessNext value = + this.Value._1 <- Checked.(+) this.Value._1 value + this.Value._2 <- this.Value._2 + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + member this.OnComplete _ = + if this.Value._2 = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) + |> fun total -> LanguagePrimitives.DivideByInt< ^T> total.Value._1 total.Value._2 + [] let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance - [] let inline fold<'T,'State> (f:'State->'T->'State) (seed:'State) (source:ISeq<'T>) : 'State = source @@ -1119,6 +1136,18 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun sum -> sum.Value + [] + let inline sumBy (f : 'T -> ^U) (source: ISeq<'T>) : ^U + when ^U:(static member Zero : ^U) + and ^U:(static member (+) : ^U * ^U -> ^U) = + source + |> foreach (fun _ -> + { new Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + override this.ProcessNext value = + this.Value <- Checked.(+) this.Value (f value) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun sum -> sum.Value + [] let inline take (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index a0f456daf53..ca5d4eff8d5 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -479,6 +479,12 @@ namespace Microsoft.FSharp.Collections val inline foreach : f:((unit -> unit) -> 'a) -> source: ISeq<'b> -> 'a when 'a :> Consumer<'b,'b> + [] + 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 empty<'T> : ISeq<'T> @@ -550,7 +556,12 @@ namespace Microsoft.FSharp.Collections [] val inline sum : source:ISeq<'T> -> 'T when 'T:(static member Zero : ^T) - and 'T:(static member (+) : ^T * ^T -> ^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 inline take : takeCount:int -> source:ISeq<'T> -> ISeq<'T> From 8cb2be274d621a1252c63e8923d5f2bea610559a Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Mon, 12 Dec 2016 23:57:39 -0500 Subject: [PATCH 236/286] inline averageBy --- src/fsharp/FSharp.Core/seq.fs | 21 +++++---------------- src/fsharp/FSharp.Core/seqcomposer.fs | 18 ++++++++++++++++++ src/fsharp/FSharp.Core/seqcomposer.fsi | 6 ++++++ 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 3f6299af3e2..ff6205668ff 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -712,31 +712,20 @@ namespace Microsoft.FSharp.Collections else mkDelayedSeq (fun () -> countByRefType keyf source) [] - let sum (source:seq<'a>) : 'a = + let inline sum (source:seq<'a>) : 'a = source |> toComposer |> Composer.Seq.sum [] - let sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = + let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = source |> toComposer |> Composer.Seq.sumBy f [] - let average (source: seq< ^a>) : ^a = + let inline average (source: seq< ^a>) : ^a = source |> toComposer |> Composer.Seq.average - [] + [] let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = - source - |> foreach (fun _ -> - { new Composer.Core.FolderWithOnComplete<'T,Composer.Core.Values<'U, int>> (Composer.Core.Values<_,_>(LanguagePrimitives.GenericZero, 0)) with - override this.ProcessNext value = - this.Value._1 <- Checked.(+) this.Value._1 (f value) - this.Value._2 <- this.Value._2 + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - - member this.OnComplete _ = - if this.Value._2 = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.Value._1 total.Value._2 + source |> toComposer |> Composer.Seq.averageBy f member this.OnComplete _ = if this.Value._2 = 0 then diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 6d76b34b037..729dd46d680 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -863,6 +863,24 @@ namespace Microsoft.FSharp.Collections invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun total -> LanguagePrimitives.DivideByInt< ^T> total.Value._1 total.Value._2 + [] + let 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) = + source + |> foreach (fun _ -> + { new FolderWithOnComplete<'T,Values<'U, int>>(Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + override this.ProcessNext value = + this.Value._1 <- Checked.(+) this.Value._1 (f value) + this.Value._2 <- this.Value._2 + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + member this.OnComplete _ = + if this.Value._2 = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) + |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.Value._1 total.Value._2 + [] let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index ca5d4eff8d5..8e5a3003518 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -485,6 +485,12 @@ namespace Microsoft.FSharp.Collections 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> From e1d92b66d43640f7232f3f48711b32770765620e Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 13 Dec 2016 00:22:38 -0500 Subject: [PATCH 237/286] inline min & inline minBy --- src/fsharp/FSharp.Core/seq.fs | 51 +++----------------------- src/fsharp/FSharp.Core/seqcomposer.fs | 43 ++++++++++++++++++++++ src/fsharp/FSharp.Core/seqcomposer.fsi | 6 +++ 3 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ff6205668ff..dfe658c76fa 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -727,52 +727,13 @@ namespace Microsoft.FSharp.Collections let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = source |> toComposer |> Composer.Seq.averageBy f - member this.OnComplete _ = - if this.Value._2 = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.Value._1 total.Value._2 + [] + let inline min (source: seq<'T>): 'T when 'T : comparison = + source |> toComposer |> Composer.Seq.min - [] - let inline min (source: seq<_>) = - source - |> foreach (fun _ -> - { new Composer.Core.FolderWithOnComplete<'T,Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - elif value < this.Value._2 then - this.Value._2 <- value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun min -> min.Value._2 - - [] - let inline minBy (f : 'T -> 'U) (source: seq<'T>) : 'T = - source - |> foreach (fun _ -> - { new Composer.Core.FolderWithOnComplete<'T,Composer.Core.Values> (Composer.Core.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - match this.Value._1, f value with - | true, valueU -> - this.Value._1 <- false - this.Value._2 <- valueU - this.Value._3 <- value - | false, valueU when valueU < this.Value._2 -> - this.Value._2 <- valueU - this.Value._3 <- value - | _ -> () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun min -> min.Value._3 + [] + let inline minBy (projection: 'T -> 'U when 'U:comparison) (source: seq<'T>) : 'T = + source |> toComposer |> Composer.Seq.minBy projection (* [] let inline minValBy (f : 'T -> 'U) (source: seq<'T>) : 'U = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 729dd46d680..db5ef3788b6 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -1056,6 +1056,49 @@ namespace Microsoft.FSharp.Collections if this.Value.Add (keyf input) then TailCall.avoid (next.ProcessNext input) else false } } + + [] + let inline min (source: ISeq< 'T>) : 'T when 'T:comparison = + source + |> foreach (fun _ -> + { new FolderWithOnComplete<'T,Values>(Values<_,_>(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + elif value < this.Value._2 then + this.Value._2 <- value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + member this.OnComplete _ = + if this.Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun min -> min.Value._2 + + [] + let inline minBy (f : 'T -> 'U) (source: ISeq<'T>) : 'T = + source + |> foreach (fun _ -> + { new FolderWithOnComplete< 'T,Values>(Values<_,_,_>(true,Unchecked.defaultof< 'U>,Unchecked.defaultof< 'T>)) with + override this.ProcessNext value = + match this.Value._1, f value with + | true, valueU -> + this.Value._1 <- false + this.Value._2 <- valueU + this.Value._3 <- value + | false, valueU when valueU < this.Value._2 -> + this.Value._2 <- valueU + this.Value._3 <- value + | _ -> () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + member this.OnComplete _ = + if this.Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun min -> min.Value._3 + [] let inline pairwise (source:ISeq<'T>) : ISeq<'T * 'T> = source |> compose { new SeqFactory<'T,'T * 'T>() with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 8e5a3003518..03d342c13e7 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -547,6 +547,12 @@ namespace Microsoft.FSharp.Collections [] val inline distinctBy : keyf:('T->'Key) -> source: ISeq<'T> -> ISeq<'T> when 'Key:equality + [] + val inline min : source: ISeq<'T> -> 'T when 'T:comparison + + [] + val inline minBy : f:('T -> 'U) -> source: ISeq<'T> -> 'T when 'U:comparison + [] val inline pairwise : source:ISeq<'T> -> ISeq<'T * 'T> From b8a53570c3bfc6d0b69937d0ae10f4c247c0d218 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 13 Dec 2016 00:32:12 -0500 Subject: [PATCH 238/286] inline max & inline maxBy --- src/fsharp/FSharp.Core/seq.fs | 46 ++++---------------------- src/fsharp/FSharp.Core/seqcomposer.fs | 41 +++++++++++++++++++++++ src/fsharp/FSharp.Core/seqcomposer.fsi | 6 ++++ 3 files changed, 53 insertions(+), 40 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index dfe658c76fa..4b134992b8d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -751,47 +751,13 @@ namespace Microsoft.FSharp.Collections acc *) - [] - let inline max (source: seq<_>) = - source - |> foreach (fun _ -> - { new Composer.Core.FolderWithOnComplete<'T,Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - elif value > this.Value._2 then - this.Value._2 <- value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + [] + let inline max (source: seq<'T>) = + source |> toComposer |> Composer.Seq.max - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun max -> max.Value._2 - - [] - let inline maxBy (f : 'T -> 'U) (source: seq<'T>) : 'T = - source - |> foreach (fun _ -> - { new Composer.Core.FolderWithOnComplete<'T,Composer.Core.Values> (Composer.Core.Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - match this.Value._1, f value with - | true, valueU -> - this.Value._1 <- false - this.Value._2 <- valueU - this.Value._3 <- value - | false, valueU when valueU > this.Value._2 -> - this.Value._2 <- valueU - this.Value._3 <- value - | _ -> () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun min -> min.Value._3 + [] + let inline maxBy (projection: 'T -> 'U) (source: seq<'T>) : 'T = + source |> toComposer |> Composer.Seq.maxBy projection (* [] diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index db5ef3788b6..5589f1bc6c0 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -1056,6 +1056,47 @@ namespace Microsoft.FSharp.Collections if this.Value.Add (keyf input) then TailCall.avoid (next.ProcessNext input) else false } } + [] + let inline max (source: ISeq<'T>) : 'T when 'T:comparison = + source + |> foreach (fun _ -> + { new FolderWithOnComplete<'T,Values>(Values<_,_>(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + elif value > this.Value._2 then + this.Value._2 <- value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + member this.OnComplete _ = + if this.Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun max -> max.Value._2 + + [] + let inline maxBy (f :'T -> 'U) (source: ISeq<'T>) : 'T when 'U:comparison = + source + |> foreach (fun _ -> + { new FolderWithOnComplete<'T,Values>(Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + match this.Value._1, f value with + | true, valueU -> + this.Value._1 <- false + this.Value._2 <- valueU + this.Value._3 <- value + | false, valueU when valueU > this.Value._2 -> + this.Value._2 <- valueU + this.Value._3 <- value + | _ -> () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + member this.OnComplete _ = + if this.Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun min -> min.Value._3 [] let inline min (source: ISeq< 'T>) : 'T when 'T:comparison = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 03d342c13e7..a6448498667 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -547,6 +547,12 @@ namespace Microsoft.FSharp.Collections [] 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 From 038861486592978a48a25df5d8da8bec00316a22 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 13 Dec 2016 00:43:41 -0500 Subject: [PATCH 239/286] inline reduce --- src/fsharp/FSharp.Core/seq.fs | 20 ++------------------ src/fsharp/FSharp.Core/seqcomposer.fs | 19 +++++++++++++++++++ src/fsharp/FSharp.Core/seqcomposer.fsi | 3 +++ 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 4b134992b8d..b72ed98255a 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -317,26 +317,10 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun fold -> fold.Value - [] + [] let reduce f (source : seq<'T>) = let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - - source - |> foreach (fun _ -> - { new Composer.Core.FolderWithOnComplete<'T, Composer.Core.Values> (Composer.Core.Values<_,_>(true, Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - else - this.Value._2 <- f.Invoke (this.Value._2, value) - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun reduced -> reduced.Value._2 + source |> toComposer |> Composer.Seq.reduce(fun a b -> f.Invoke(a,b)) [] let replicate count x = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 5589f1bc6c0..8834018caf7 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -1162,6 +1162,25 @@ namespace Microsoft.FSharp.Collections TailCall.avoid (next.ProcessNext currentPair) }} + [] + let inline reduce (f:'T->'T->'T) (source : ISeq<'T>) : 'T = + source + |> foreach (fun _ -> + { new FolderWithOnComplete<'T, Values>(Values<_,_>(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + else + this.Value._2 <- f this.Value._2 value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + member this.OnComplete _ = + if this.Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun reduced -> reduced.Value._2 + [] let inline scan (folder:'State->'T->'State) (initialState: 'State) (source:ISeq<'T>) :ISeq<'State> = source |> compose { new SeqFactory<'T,'State>() with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index a6448498667..a8d13e2bda7 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -562,6 +562,9 @@ namespace Microsoft.FSharp.Collections [] val inline 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> From f10820565d35790a6dae1d5b2d2c5a697b7f74b3 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 13 Dec 2016 00:51:57 -0500 Subject: [PATCH 240/286] inline tryFindIndex --- src/fsharp/FSharp.Core/seq.fs | 14 ++------------ src/fsharp/FSharp.Core/seqcomposer.fs | 14 ++++++++++++++ src/fsharp/FSharp.Core/seqcomposer.fsi | 3 +++ 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index b72ed98255a..5d70e56acfd 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -464,19 +464,9 @@ namespace Microsoft.FSharp.Collections let res = Array.scanSubRight f arr 0 (arr.Length - 1) acc res :> seq<_>) - [] + [] let tryFindIndex p (source:seq<_>) = - source - |> foreach (fun halt -> - { new Composer.Core.Folder<'T, Composer.Core.Values, int>> (Composer.Core.Values<_,_>(None, 0)) with - override this.ProcessNext value = - if p value then - this.Value._1 <- Some(this.Value._2) - halt () - else - this.Value._2 <- this.Value._2 + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun tried -> tried.Value._1 + source |> toComposer |> Composer.Seq.tryFindIndex p [] let findIndex p (source:seq<_>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 8834018caf7..fbff3fef873 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -1376,6 +1376,20 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun find -> find.Value + [] + let inline tryFindIndex (predicate:'T->bool) (source:ISeq<'T>) : int option = + source + |> foreach (fun halt -> + { new Folder<'T, Values, int>>(Values<_,_>(None, 0)) with + override this.ProcessNext value = + if predicate value then + this.Value._1 <- Some(this.Value._2) + halt () + else + this.Value._2 <- this.Value._2 + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun tried -> tried.Value._1 + [] let inline windowed (windowSize:int) (source:ISeq<'T>) : ISeq<'T[]> = source |> compose { new SeqFactory<'T,'T[]>() with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index a8d13e2bda7..89e4ca10a40 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -608,5 +608,8 @@ namespace Microsoft.FSharp.Collections [] val tryFind : f:('T -> bool) -> source: ISeq<'T> -> Option<'T> + [] + val inline tryFindIndex: preidcate:('T->bool) -> source:ISeq<'T> -> int option + [] val inline windowed : windowSize:int -> source:ISeq<'T> -> ISeq<'T[]> From 6333ac483e4c94c35de29217c4079d8a0c322f71 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 13 Dec 2016 01:02:53 -0500 Subject: [PATCH 241/286] inline tryLast --- src/fsharp/FSharp.Core/seq.fs | 16 ++-------------- src/fsharp/FSharp.Core/seqcomposer.fs | 16 ++++++++++++++++ src/fsharp/FSharp.Core/seqcomposer.fsi | 3 +++ 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 5d70e56acfd..db6a84f30fa 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -821,21 +821,9 @@ namespace Microsoft.FSharp.Collections let tail (source: seq<'T>) = source |> toComposer |> Composer.Seq.tail |> Upcast.enumerable - [] + [] let tryLast (source : seq<_>) = - source - |> foreach (fun _ -> - { new Composer.Core.Folder<'T, Composer.Core.Values> (Composer.Core.Values(true, Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun tried -> - if tried.Value._1 then - None - else - Some tried.Value._2 + source |> toComposer |> Composer.Seq.tryLast [] let last (source : seq<_>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index fbff3fef873..c73aa1b4b7e 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -1390,6 +1390,22 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun tried -> tried.Value._1 + [] + let inline tryLast (source :ISeq<'T>) : 'T option = + source + |> foreach (fun _ -> + { new Folder<'T, Values>(Values(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun tried -> + if tried.Value._1 then + None + else + Some tried.Value._2 + [] let inline windowed (windowSize:int) (source:ISeq<'T>) : ISeq<'T[]> = source |> compose { new SeqFactory<'T,'T[]>() with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 89e4ca10a40..8e0808e6b75 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -611,5 +611,8 @@ namespace Microsoft.FSharp.Collections [] val inline tryFindIndex: preidcate:('T->bool) -> source:ISeq<'T> -> int option + [] + val inline tryLast : source:ISeq<'T> -> 'T option + [] val inline windowed : windowSize:int -> source:ISeq<'T> -> ISeq<'T[]> From 72b441b71aa433a9c81f2cd5a50a19e951ef14da Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 13 Dec 2016 01:08:27 -0500 Subject: [PATCH 242/286] inline exactlyOne --- src/fsharp/FSharp.Core/seq.fs | 21 ++------------------- src/fsharp/FSharp.Core/seqcomposer.fs | 22 ++++++++++++++++++++++ src/fsharp/FSharp.Core/seqcomposer.fsi | 3 +++ 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index db6a84f30fa..5361ebe1609 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -831,26 +831,9 @@ namespace Microsoft.FSharp.Collections | None -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString | Some x -> x - [] + [] let exactlyOne (source : seq<_>) = - source - |> foreach (fun halt -> - { new Composer.Core.FolderWithOnComplete<'T, Composer.Core.Values> (Composer.Core.Values(true, Unchecked.defaultof<'T>, false)) with - override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - else - this.Value._3 <- true - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - elif this.Value._3 then - invalidArg "source" (SR.GetString(SR.inputSequenceTooLong)) }) - |> fun one -> one.Value._2 + source |> toComposer |> Composer.Seq.exactlyOne member this.OnComplete _ = if this.Value._1 then diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index c73aa1b4b7e..92af4649f7e 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -884,6 +884,28 @@ namespace Microsoft.FSharp.Collections [] let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance + [] + let inline exactlyOne (source : ISeq<'T>) : 'T = + source + |> foreach (fun halt -> + { new FolderWithOnComplete<'T, Values>(Values(true, Unchecked.defaultof<'T>, false)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + else + this.Value._3 <- true + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + member this.OnComplete _ = + if this.Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + elif this.Value._3 then + invalidArg "source" (SR.GetString(SR.inputSequenceTooLong)) }) + |> fun one -> one.Value._2 + + [] let inline fold<'T,'State> (f:'State->'T->'State) (seed:'State) (source:ISeq<'T>) : 'State = source diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 8e0808e6b75..e39efd3e121 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -494,6 +494,9 @@ namespace Microsoft.FSharp.Collections [] val empty<'T> : ISeq<'T> + [] + val inline exactlyOne : source : ISeq<'T> -> 'T + [] val inline fold<'T,'State> : f:('State->'T->'State) -> seed:'State -> source:ISeq<'T> -> 'State From d5fa3adbe857183ea42876ec0c3f78715b7795f6 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 13 Dec 2016 01:13:55 -0500 Subject: [PATCH 243/286] remove adapt variants --- src/fsharp/FSharp.Core/seq.fs | 4 ++-- src/fsharp/FSharp.Core/seqcomposer.fs | 17 ----------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 2 -- 3 files changed, 2 insertions(+), 21 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 5361ebe1609..cfaaa281944 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -185,8 +185,8 @@ namespace Microsoft.FSharp.Collections [] let mapi f source = - let f' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f - source |> toComposer |> Composer.Seq.mapi_adapt f' |> Upcast.enumerable + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f + source |> toComposer |> Composer.Seq.mapi (fun idx a ->f.Invoke(idx,a)) |> Upcast.enumerable [] let mapi2 f source1 source2 = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 92af4649f7e..b8303d91ee6 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -1040,14 +1040,6 @@ namespace Microsoft.FSharp.Collections this.Value <- this.Value + 1 TailCall.avoid (next.ProcessNext (f this.Value input)) } } - let mapi_adapt (f:OptimizedClosures.FSharpFunc<_,_,_>) source = - source |> compose { new SeqFactory<'T,'U>() with - member __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,int>(Upcast.iCompletionChain next, -1) with - override this.ProcessNext (input:'T) : bool = - this.Value <- this.Value + 1 - TailCall.avoid (next.ProcessNext (f.Invoke (this.Value, input))) } } - [] let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = source |> compose { new SeqFactory<'T,'U>() with @@ -1212,15 +1204,6 @@ namespace Microsoft.FSharp.Collections this.Value <- folder this.Value input TailCall.avoid (next.ProcessNext this.Value) } } - - let scan_adapt (folder:OptimizedClosures.FSharpFunc<'State,'T,'State>) (initialState: 'State) (source:ISeq<'T>) :ISeq<'State> = - source |> compose { new SeqFactory<'T,'State>() with - member __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,'State>(Upcast.iCompletionChain next, initialState) with - override this.ProcessNext (input:'T) : bool = - this.Value <- folder.Invoke(this.Value,input) - TailCall.avoid (next.ProcessNext this.Value) } } - [] let inline skip (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index e39efd3e121..9925c62ed82 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -539,8 +539,6 @@ namespace Microsoft.FSharp.Collections [] val inline mapi : f:(int->'a->'b) -> source: ISeq<'a> -> ISeq<'b> - val mapi_adapt : f:OptimizedClosures.FSharpFunc -> source: ISeq<'a> -> ISeq<'b> - [] val inline choose : f:('a->option<'b>) -> source: ISeq<'a> -> ISeq<'b> From d2f7f92f819bbf4c35d9ea886e458623f12c0abd Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 15:38:41 -0500 Subject: [PATCH 244/286] inline map2, inline mapi2, & inline map3 --- src/fsharp/FSharp.Core/seq.fs | 30 ++--- src/fsharp/FSharp.Core/seqcomposer.fs | 145 ++++++++++--------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 84 ++------------ 3 files changed, 84 insertions(+), 175 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index cfaaa281944..0ef1a8328fa 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -179,32 +179,36 @@ namespace Microsoft.FSharp.Collections [] let where f source = filter f source - [] + [] let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> = source |> toComposer |> Composer.Seq.map f |> Upcast.enumerable - [] + [] let mapi f source = let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f source |> toComposer |> Composer.Seq.mapi (fun idx a ->f.Invoke(idx,a)) |> Upcast.enumerable - [] - let mapi2 f source1 source2 = + [] + let mapi2 (mapfn:int->'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) = + checkNonNull "source1" source1 checkNonNull "source2" source2 - source1 |> seqFactory (Composer.Seq.Mapi2Factory (f, source2)) + let f = OptimizedClosures.FSharpFunc.Adapt mapfn + (source1|>toComposer, source2|>toComposer) + ||> Composer.Seq.mapi2 (fun idx a b ->f.Invoke(idx,a,b)) |> Upcast.enumerable - [] - let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = + [] + let map2<'T,'U,'V> (mapfn:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = checkNonNull "source1" source1 - match source1 with - | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose (Composer.Seq.Map2FirstFactory (f, source2))) - | _ -> source2 |> seqFactory (Composer.Seq.Map2SecondFactory (f, source1)) + checkNonNull "source2" source2 + (source1|>toComposer, source2|>toComposer) + ||> Composer.Seq.map2 mapfn |> Upcast.enumerable - [] - let map3 f source1 source2 source3 = + [] + let map3 mapfn source1 source2 source3 = checkNonNull "source2" source2 checkNonNull "source3" source3 - source1 |> seqFactory (Composer.Seq.Map3Factory (f, source2, source3)) + (source1|>toComposer, source2|>toComposer, source3|>toComposer) + |||> Composer.Seq.map3 mapfn |> Upcast.enumerable [] let choose f source = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index b8303d91ee6..56605b30125 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -170,99 +170,11 @@ namespace Microsoft.FSharp.Collections override __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next static member Instance = singleton - and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) = - inherit SeqFactory<'First,'U> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map2First (map, input2, outOfBand, next, pipeIdx) - - and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) = - inherit SeqFactory<'Second,'U> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'Second,'V> = upcast Map2Second (map, input1, outOfBand, next, pipeIdx) - - and Map3Factory<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U, input2:IEnumerable<'Second>, input3:IEnumerable<'Third>) = - inherit SeqFactory<'First,'U> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Map3 (map, input2, input3, outOfBand, next, pipeIdx) - - and Mapi2Factory<'First,'Second,'U> (map:int->'First->'Second->'U, input2:IEnumerable<'Second>) = - inherit SeqFactory<'First,'U> () - override this.Create<'V> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'U,'V>) : Consumer<'First,'V> = upcast Mapi2 (map, input2, outOfBand, next, pipeIdx) - and ISkipping = // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip // and it can only do it at the start of a sequence abstract Skipping : unit -> bool - and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit ConsumerChainedWithCleanup<'First,'V>(Upcast.iCompletionChain next) - - let input2 = enumerable2.GetEnumerator () - let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map - - override __.ProcessNext (input:'First) : bool = - if input2.MoveNext () then - TailCall.avoid (next.ProcessNext (map'.Invoke (input, input2.Current))) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - override __.OnComplete _ = () - override __.OnDispose () = - input2.Dispose () - - and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit ConsumerChainedWithCleanup<'Second,'V>(Upcast.iCompletionChain next) - - let input1 = enumerable1.GetEnumerator () - let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map - - override __.ProcessNext (input:'Second) : bool = - if input1.MoveNext () then - TailCall.avoid (next.ProcessNext (map'.Invoke (input1.Current, input))) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - override __.OnComplete _ = () - override __.OnDispose () = - input1.Dispose () - - and Map3<'First,'Second,'Third,'U,'V> (map:'First->'Second->'Third->'U, enumerable2:IEnumerable<'Second>, enumerable3:IEnumerable<'Third>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit ConsumerChainedWithCleanup<'First,'V>(Upcast.iCompletionChain next) - - let input2 = enumerable2.GetEnumerator () - let input3 = enumerable3.GetEnumerator () - let map' = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt map - - override __.ProcessNext (input:'First) : bool = - if input2.MoveNext () && input3.MoveNext () then - TailCall.avoid (next.ProcessNext (map'.Invoke (input, input2.Current, input3.Current))) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - override __.OnComplete _ = () - override __.OnDispose () = - try input2.Dispose () - finally input3.Dispose () - - and Mapi2<'First,'Second,'U,'V> (map:int->'First->'Second->'U, enumerable2:IEnumerable<'Second>, outOfBand:IOutOfBand, next:Consumer<'U,'V>, pipeIdx:int) = - inherit ConsumerChainedWithCleanup<'First,'V>(Upcast.iCompletionChain next) - - let mutable idx = 0 - let input2 = enumerable2.GetEnumerator () - let mapi2' = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt map - - override __.ProcessNext (input:'First) : bool = - if input2.MoveNext () then - idx <- idx + 1 - TailCall.avoid (next.ProcessNext (mapi2'.Invoke (idx-1, input, input2.Current))) - else - outOfBand.StopFurtherProcessing pipeIdx - false - - override __.OnComplete _ = () - override __.OnDispose () = - input2.Dispose () - type SeqProcessNextStates = | InProcess = 0 | NotStarted = 1 @@ -1040,6 +952,63 @@ namespace Microsoft.FSharp.Collections this.Value <- this.Value + 1 TailCall.avoid (next.ProcessNext (f this.Value input)) } } + + [] + let inline map2<'First,'Second,'U> (map:'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = + source1 |> compose { new SeqFactory<'First,'U>() with + member __.Create<'V> outOfBand pipeIdx next = + upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, IEnumerator<'Second>>(Upcast.iCompletionChain next, (source2.GetEnumerator ())) with + member self.ProcessNext input = + if self.Value.MoveNext () then + TailCall.avoid (next.ProcessNext (map input self.Value.Current)) + else + outOfBand.StopFurtherProcessing pipeIdx + false + + override self.OnDispose () = () + override self.OnComplete _ = + self.Value.Dispose () } } + + + [] + let inline mapi2<'First,'Second,'U> (map:int -> 'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = + source1 |> compose { new SeqFactory<'First,'U>() with + member __.Create<'V> outOfBand pipeIdx next = + upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values>> + (Upcast.iCompletionChain next, Values<_,_>(-1, source2.GetEnumerator ())) with + member self.ProcessNext input = + if self.Value._2.MoveNext () then + self.Value._1 <- self.Value._1 + 1 + TailCall.avoid (next.ProcessNext (map self.Value._1 input self.Value._2.Current)) + else + outOfBand.StopFurtherProcessing pipeIdx + false + + override self.OnDispose () = () + override self.OnComplete _ = + self.Value._2.Dispose () } } + + + [] + let inline map3<'First,'Second,'Third,'U> + (map:'First->'Second->'Third->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) (source3:ISeq<'Third>) : ISeq<'U> = + source1 |> compose { new SeqFactory<'First,'U>() with + member __.Create<'V> outOfBand pipeIdx next = + upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values,IEnumerator<'Third>>> + (Upcast.iCompletionChain next, Values<_,_>(source2.GetEnumerator(),source3.GetEnumerator())) with + member self.ProcessNext input = + if self.Value._1.MoveNext() && self.Value._2.MoveNext () then + TailCall.avoid (next.ProcessNext (map input self.Value._1 .Current self.Value._2.Current)) + else + outOfBand.StopFurtherProcessing pipeIdx + false + + override self.OnDispose () = () + override self.OnComplete _ = + self.Value._1.Dispose () + self.Value._2.Dispose () } } + + [] let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = source |> compose { new SeqFactory<'T,'U>() with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 9925c62ed82..ddda14e0070 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -143,85 +143,12 @@ namespace Microsoft.FSharp.Collections new : unit -> IdentityFactory<'T> static member Instance : SeqFactory<'T,'T> end - and Map2FirstFactory<'First,'Second,'U> = - class - inherit SeqFactory<'First,'U> - new : map:('First -> 'Second -> 'U) * - input2:IEnumerable<'Second> -> - Map2FirstFactory<'First,'Second,'U> - end - and Map2SecondFactory<'First,'Second,'U> = - class - inherit SeqFactory<'Second,'U> - new : map:('First -> 'Second -> 'U) * - input1:IEnumerable<'First> -> - Map2SecondFactory<'First,'Second,'U> - end - and Map3Factory<'First,'Second,'Third,'U> = - class - inherit SeqFactory<'First,'U> - new : map:('First -> 'Second -> 'Third -> 'U) * - input2:IEnumerable<'Second> * - input3:IEnumerable<'Third> -> - Map3Factory<'First,'Second,'Third,'U> - end - and Mapi2Factory<'First,'Second,'U> = - class - inherit SeqFactory<'First,'U> - new : map:(int -> 'First -> 'Second -> 'U) * - input2:IEnumerable<'Second> -> - Mapi2Factory<'First,'Second,'U> - end + and ISkipping = interface abstract member Skipping : unit -> bool end - and Map2First<'First,'Second,'U,'V> = - class - inherit ConsumerChainedWithCleanup<'First,'V> - new : map:('First -> 'Second -> 'U) * - enumerable2:IEnumerable<'Second> * - outOfBand: IOutOfBand * - next: Consumer<'U,'V> * pipeIdx:int -> - Map2First<'First,'Second,'U,'V> - override OnDispose : unit -> unit - override ProcessNext : input:'First -> bool - end - and Map2Second<'First,'Second,'U,'V> = - class - inherit ConsumerChainedWithCleanup<'Second,'V> - new : map:('First -> 'Second -> 'U) * - enumerable1:IEnumerable<'First> * - outOfBand: IOutOfBand * - next: Consumer<'U,'V> * pipeIdx:int -> - Map2Second<'First,'Second,'U,'V> - override OnDispose : unit -> unit - override ProcessNext : input:'Second -> bool - end - and Map3<'First,'Second,'Third,'U,'V> = - class - inherit ConsumerChainedWithCleanup<'First,'V> - new : map:('First -> 'Second -> 'Third -> 'U) * - enumerable2:IEnumerable<'Second> * - enumerable3:IEnumerable<'Third> * - outOfBand: IOutOfBand * - next: Consumer<'U,'V> * pipeIdx:int -> - Map3<'First,'Second,'Third,'U,'V> - override OnDispose : unit -> unit - override ProcessNext : input:'First -> bool - end - and Mapi2<'First,'Second,'U,'V> = - class - inherit ConsumerChainedWithCleanup<'First,'V> - new : map:(int -> 'First -> 'Second -> 'U) * - enumerable2:IEnumerable<'Second> * - outOfBand: IOutOfBand * - next: Consumer<'U,'V> * pipeIdx:int -> - Mapi2<'First,'Second,'U,'V> - override OnDispose : unit -> unit - override ProcessNext : input:'First -> bool - end type SeqProcessNextStates = | InProcess = 0 | NotStarted = 1 @@ -539,6 +466,15 @@ namespace Microsoft.FSharp.Collections [] val inline mapi : f:(int->'a->'b) -> source: ISeq<'a> -> ISeq<'b> + [] + val inline map2<'First,'Second,'U> : map:('First->'Second->'U) -> source1:ISeq<'First> -> source2:ISeq<'Second> -> ISeq<'U> + + [] + val inline mapi2<'First,'Second,'U> : map:(int -> 'First->'Second->'U) -> source1:ISeq<'First> -> source2:ISeq<'Second> -> ISeq<'U> + + [] + val inline map3<'First,'Second,'Third,'U> : map:('First->'Second->'Third->'U) -> source1:ISeq<'First> -> source2:ISeq<'Second> -> source3:ISeq<'Third> -> ISeq<'U> + [] val inline choose : f:('a->option<'b>) -> source: ISeq<'a> -> ISeq<'b> From ffa88cd92baeda6d597e5e8204614c1233263939 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 18:20:01 -0500 Subject: [PATCH 245/286] inline iter2 & inline iteri2 --- src/fsharp/FSharp.Core/seq.fs | 41 +++++++------------------- src/fsharp/FSharp.Core/seqcomposer.fs | 28 ++++++++++++++++++ src/fsharp/FSharp.Core/seqcomposer.fsi | 6 ++++ 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 0ef1a8328fa..4d0b2f63d06 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -101,7 +101,7 @@ namespace Microsoft.FSharp.Collections source |> toComposer |> Composer.Seq.skip i |> Upcast.enumerable |> tryHead - |> function + |> function | None -> invalidArgFmt "index" "{0}\nseq was short by 1 element" [|SR.GetString SR.notEnoughElements|] | Some value -> value @@ -128,42 +128,23 @@ namespace Microsoft.FSharp.Collections let forall f (source:seq<'T>) = source |> toComposer |> Composer.Seq.forall f - [] - let iter2 f (source1 : seq<_>) (source2 : seq<_>) = + [] + let iter2 (f:'T->'U->unit) (source1 : seq<'T>) (source2 : seq<'U>) = + checkNonNull "source1" source1 checkNonNull "source2" source2 - - use e2 = source2.GetEnumerator() let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) + (source1|>toComposer, source2|>toComposer) + ||> Composer.Seq.iter2 (fun a b -> f.Invoke(a,b)) - source1 - |> foreach (fun halt -> - { new Composer.Core.Folder<_,_> () with - override this.ProcessNext value = - if (e2.MoveNext()) then - f.Invoke(value, e2.Current) - else - halt() - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> ignore - [] - let iteri2 f (source1 : seq<_>) (source2 : seq<_>) = + [] + let iteri2 (f:int->'T->'U->unit) (source1 : seq<_>) (source2 : seq<_>) = + checkNonNull "source1" source1 checkNonNull "source2" source2 - - use e2 = source2.GetEnumerator() let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) + (source1|>toComposer, source2|>toComposer) + ||> Composer.Seq.iteri2 (fun idx a b -> f.Invoke(idx,a,b)) - source1 - |> foreach (fun halt -> - { new Composer.Core.Folder<_,int> (0) with - override this.ProcessNext value = - if (e2.MoveNext()) then - f.Invoke(this.Value, value, e2.Current) - this.Value <- this.Value + 1 - else - halt() - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> ignore // Build an IEnumerble by wrapping/transforming iterators as they get generated. let revamp f (ie : seq<_>) = mkSeq (fun () -> f (ie.GetEnumerator())) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 56605b30125..a21e96b99b4 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -853,6 +853,34 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore + [] + let inline iter2 (f:'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = + source1 + |> foreach (fun halt -> + { new Folder<'T,IEnumerator<'U>> (source2.GetEnumerator()) with + override self.ProcessNext value = + if self.Value.MoveNext() then + f value self.Value.Current + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> ignore + + [] + let inline iteri2 (f:int->'T->'U->unit) (source1:ISeq<'T>) (source2:seq<'U>) : unit = + source1 + |> foreach (fun halt -> + { new Folder<'T,Values>>(Values<_,_>(-1,source2.GetEnumerator())) with + override self.ProcessNext value = + if self.Value._2.MoveNext() then + f self.Value._1 value self.Value._2.Current + self.Value._1 <- self.Value._1 + 1 + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> ignore + + [] let tryHead (source:ISeq<'T>) = source diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index ddda14e0070..5564ff68dec 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -439,6 +439,12 @@ namespace Microsoft.FSharp.Collections [] val 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:seq<'U> -> unit + [] val tryHead : source: ISeq<'T> -> 'T option From 4465df4fe61d3ac1214312d02ca864e971920dc9 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 18:47:18 -0500 Subject: [PATCH 246/286] inline forall2 & inline exists2 --- src/fsharp/FSharp.Core/seq.fs | 69 ++++++-------------------- src/fsharp/FSharp.Core/seqcomposer.fs | 35 ++++++++++++- src/fsharp/FSharp.Core/seqcomposer.fsi | 6 +++ 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 4d0b2f63d06..03e8548d907 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -109,22 +109,22 @@ namespace Microsoft.FSharp.Collections let tryItem i (source:seq<'T>) = source |> toComposer |> Composer.Seq.tryItem i - [] + [] let nth i (source : seq<'T>) = item i source - [] + [] let iteri f (source:seq<'T>) = source |> toComposer |> Composer.Seq.iteri f - [] + [] let exists f (source:seq<'T>) = source |> toComposer |> Composer.Seq.exists f - [] + [] let inline contains element (source:seq<'T>) = source |> toComposer |> Composer.Seq.contains element - [] + [] let forall f (source:seq<'T>) = source |> toComposer |> Composer.Seq.forall f @@ -743,60 +743,23 @@ namespace Microsoft.FSharp.Collections let skipWhile predicate (source: seq<_>) = source |> toComposer |> Composer.Seq.skipWhile predicate |> Upcast.enumerable - [] + [] let forall2 p (source1: seq<_>) (source2: seq<_>) = + checkNonNull "source1" source1 checkNonNull "source2" source2 + let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt p + (source1|>toComposer, source2|>toComposer) + ||> Composer.Seq.forall2 (fun a b -> p.Invoke(a,b)) - use e2 = source2.GetEnumerator() - let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(p) - - source1 - |> foreach (fun halt -> - { new Composer.Core.Folder<_,bool> (true) with - override this.ProcessNext value = - if (e2.MoveNext()) then - if not (p.Invoke(value, e2.Current)) then - this.Value <- false - halt() - else - halt() - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun all -> all.Value - - [] + [] let exists2 p (source1: seq<_>) (source2: seq<_>) = + checkNonNull "source1" source1 checkNonNull "source2" source2 + let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt p + (source1|>toComposer, source2|>toComposer) + ||> Composer.Seq.exists2 (fun a b -> p.Invoke(a,b)) - use e2 = source2.GetEnumerator() - let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(p) - - source1 - |> foreach (fun halt -> - { new Composer.Core.Folder<_,bool> (false) with - override this.ProcessNext value = - if (e2.MoveNext()) then - if p.Invoke(value, e2.Current) then - this.Value <- true - halt() - else - halt() - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun exists -> exists.Value - - source1 - |> foreach (fun halt -> - { new Composer.Core.Folder<_,bool> (false) with - override this.ProcessNext value = - if (e2.MoveNext()) then - if p.Invoke(value, e2.Current) then - this.Value <- true - halt() - else - halt() - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun exists -> exists.Value - - [] + [] let head (source : seq<_>) = match tryHead source with | None -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index a21e96b99b4..0a3941094d5 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -930,6 +930,22 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun exists -> exists.Value + [] + let exists2 (predicate:'T->'U->bool) (source1: ISeq<'T>) (source2: ISeq<'U>) : bool = + source1 + |> foreach (fun halt -> + { new Folder<'T,Values>>(Values<_,_>(false,source2.GetEnumerator())) with + override self.ProcessNext value = + if self.Value._2.MoveNext() then + if predicate value self.Value._2.Current then + self.Value._1 <- true + halt() + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun exists -> exists.Value._1 + + [] let inline contains element (source:ISeq<'T>) = source @@ -943,17 +959,32 @@ namespace Microsoft.FSharp.Collections |> fun contains -> contains.Value [] - let forall f (source:ISeq<'T>) = + let forall predicate (source:ISeq<'T>) = source |> foreach (fun halt -> { new Folder<'T, bool> (true) with override this.ProcessNext value = - if not (f value) then + if not (predicate value) then this.Value <- false halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun forall -> forall.Value + [] + let inline forall2 predicate (source1:ISeq<'T>) (source2:ISeq<'U>) : bool = + source1 + |> foreach (fun halt -> + { new Folder<'T,Values>>(Values<_,_>(true,source2.GetEnumerator())) with + override self.ProcessNext value = + if self.Value._2.MoveNext() then + if not (predicate value self.Value._2.Current) then + self.Value._1 <- false + halt() + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun all -> all.Value._1 + [] let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 5564ff68dec..f757aa6c0f4 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -457,12 +457,18 @@ namespace Microsoft.FSharp.Collections [] val exists : f:('T -> bool) -> source: ISeq<'T> -> bool + [] + val 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 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> From 78669b7e674bf3a4748a6dc0151cecfba5a53154 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 19:27:58 -0500 Subject: [PATCH 247/286] inline fold2 --- src/fsharp/FSharp.Core/seq.fs | 29 ++++++-------------------- src/fsharp/FSharp.Core/seqcomposer.fs | 18 ++++++++++++---- src/fsharp/FSharp.Core/seqcomposer.fsi | 3 +++ 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 03e8548d907..6e6492221d7 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -114,7 +114,8 @@ namespace Microsoft.FSharp.Collections [] let iteri f (source:seq<'T>) = - source |> toComposer |> Composer.Seq.iteri f + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f + source |> toComposer |> Composer.Seq.iteri (fun idx a -> f.Invoke(idx,a)) [] let exists f (source:seq<'T>) = @@ -276,31 +277,13 @@ namespace Microsoft.FSharp.Collections |> Composer.Seq.fold<'T,'State>(fun (a:'State) (b:'T) -> f.Invoke(a,b)) x - source - |> foreach (fun _ -> - { new Composer.Core.Folder<'T,'State> (x) with - override this.ProcessNext value = - this.Value <- f.Invoke (this.Value, value) - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun folded -> folded.Value - - [] + [] let fold2<'T1,'T2,'State> f (state:'State) (source1: seq<'T1>) (source2: seq<'T2>) = + checkNonNull "source1" source1 checkNonNull "source2" source2 - - use e2 = source2.GetEnumerator() let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) - - source1 - |> foreach (fun halt -> - { new Composer.Core.Folder<_,'State> (state) with - override this.ProcessNext value = - if (e2.MoveNext()) then - this.Value <- f.Invoke(this.Value, value, e2.Current) - else - halt() - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun fold -> fold.Value + (source1 |> toComposer, source2|>toComposer) + ||> Composer.Seq.fold2(fun s a b -> f.Invoke(s,a,b)) state [] let reduce f (source : seq<'T>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 0a3941094d5..0aa5bdd1357 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -829,6 +829,19 @@ namespace Microsoft.FSharp.Collections }) |> fun folded -> folded.Value + [] + let inline fold2<'T1,'T2,'State> (folder:'State->'T1->'T2->'State) (state:'State) (source1: ISeq<'T1>) (source2: ISeq<'T2>) = + source1 + |> foreach (fun halt -> + { new Folder<_,Values<'State,IEnumerator<'T2>>>(Values<_,_>(state,source2.GetEnumerator())) with + override self.ProcessNext value = + if self.Value._2.MoveNext() then + self.Value._1 <- folder self.Value._1 value self.Value._2.Current + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun fold -> fold.Value._1 + [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = Upcast.seq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) @@ -893,16 +906,13 @@ namespace Microsoft.FSharp.Collections |> fun head -> head.Value - [] let iteri f (source:ISeq<'T>) = - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f - source |> foreach (fun _ -> { new Folder<'T, int> (0) with override this.ProcessNext value = - f.Invoke(this.Value, value) + f this.Value value this.Value <- this.Value + 1 Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index f757aa6c0f4..997469ca2cf 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -427,6 +427,9 @@ namespace Microsoft.FSharp.Collections [] 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 -> ('T * 'State) option) -> state:'State -> ISeq<'T> From 7ce9fb509b211b0cd2fab0dd0066126e892341b3 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 19:37:46 -0500 Subject: [PATCH 248/286] add cleanup to folders --- src/fsharp/FSharp.Core/seqcomposer.fs | 84 ++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 9 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 0aa5bdd1357..03b7ba90919 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -742,6 +742,7 @@ namespace Microsoft.FSharp.Collections member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (Upcast.enumerable this)) + [] let toComposer (source:seq<'T>) : ISeq<'T> = match source with @@ -751,12 +752,15 @@ namespace Microsoft.FSharp.Collections | null -> nullArg "source" | _ -> Upcast.seq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) + let inline foreach f (source:ISeq<_>) = source.ForEach f + let inline compose (factory:#SeqFactory<_,_>) (source:ISeq<'T>) = source.Compose factory + [] let inline average (source: ISeq< ^T>) : ^T when ^T:(static member Zero : ^T) @@ -775,6 +779,7 @@ namespace Microsoft.FSharp.Collections invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun total -> LanguagePrimitives.DivideByInt< ^T> total.Value._1 total.Value._2 + [] let inline averageBy (f : 'T -> ^U) (source: ISeq< 'T >) : ^U when ^U:(static member Zero : ^U) @@ -793,9 +798,11 @@ namespace Microsoft.FSharp.Collections invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.Value._1 total.Value._2 + [] let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance + [] let inline exactlyOne (source : ISeq<'T>) : 'T = source @@ -829,33 +836,42 @@ namespace Microsoft.FSharp.Collections }) |> fun folded -> folded.Value + [] let inline fold2<'T1,'T2,'State> (folder:'State->'T1->'T2->'State) (state:'State) (source1: ISeq<'T1>) (source2: ISeq<'T2>) = source1 |> foreach (fun halt -> - { new Folder<_,Values<'State,IEnumerator<'T2>>>(Values<_,_>(state,source2.GetEnumerator())) with + { new FolderWithOnComplete<_,Values<'State,IEnumerator<'T2>>>(Values<_,_>(state,source2.GetEnumerator())) with override self.ProcessNext value = if self.Value._2.MoveNext() then self.Value._1 <- folder self.Value._1 value self.Value._2.Current else halt() - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + override self.OnComplete _ = + self.Value._2.Dispose() + }) |> fun fold -> fold.Value._1 + [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = Upcast.seq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) + [] let initInfinite<'T> (f:int->'T) : ISeq<'T> = Upcast.seq (new Init.EnumerableDecider<'T>(Nullable (), f)) + [] 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)) + [] let iter f (source:ISeq<'T>) = source @@ -866,30 +882,42 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore + [] let inline iter2 (f:'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = source1 |> foreach (fun halt -> - { new Folder<'T,IEnumerator<'U>> (source2.GetEnumerator()) with + { new FolderWithOnComplete<'T,IEnumerator<'U>> (source2.GetEnumerator()) with override self.ProcessNext value = if self.Value.MoveNext() then f value self.Value.Current else halt() - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + override self.OnComplete _ = + self.Value.Dispose() + }) |> ignore + [] let inline iteri2 (f:int->'T->'U->unit) (source1:ISeq<'T>) (source2:seq<'U>) : unit = source1 |> foreach (fun halt -> - { new Folder<'T,Values>>(Values<_,_>(-1,source2.GetEnumerator())) with + { new FolderWithOnComplete<'T,Values>>(Values<_,_>(-1,source2.GetEnumerator())) with override self.ProcessNext value = if self.Value._2.MoveNext() then f self.Value._1 value self.Value._2.Current self.Value._1 <- self.Value._1 + 1 + Unchecked.defaultof<_> else halt() + Unchecked.defaultof<_> + + override self.OnComplete _ = + self.Value._2.Dispose() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore @@ -928,6 +956,7 @@ namespace Microsoft.FSharp.Collections else false }} + [] let exists f (source:ISeq<'T>) = source @@ -940,11 +969,12 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun exists -> exists.Value + [] let exists2 (predicate:'T->'U->bool) (source1: ISeq<'T>) (source2: ISeq<'U>) : bool = source1 |> foreach (fun halt -> - { new Folder<'T,Values>>(Values<_,_>(false,source2.GetEnumerator())) with + { new FolderWithOnComplete<'T,Values>>(Values<_,_>(false,source2.GetEnumerator())) with override self.ProcessNext value = if self.Value._2.MoveNext() then if predicate value self.Value._2.Current then @@ -952,7 +982,12 @@ namespace Microsoft.FSharp.Collections halt() else halt() - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + override self.OnComplete _ = + self.Value._2.Dispose() + + }) |> fun exists -> exists.Value._1 @@ -968,6 +1003,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun contains -> contains.Value + [] let forall predicate (source:ISeq<'T>) = source @@ -980,11 +1016,12 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun forall -> forall.Value + [] let inline forall2 predicate (source1:ISeq<'T>) (source2:ISeq<'U>) : bool = source1 |> foreach (fun halt -> - { new Folder<'T,Values>>(Values<_,_>(true,source2.GetEnumerator())) with + { new FolderWithOnComplete<'T,Values>>(Values<_,_>(true,source2.GetEnumerator())) with override self.ProcessNext value = if self.Value._2.MoveNext() then if not (predicate value self.Value._2.Current) then @@ -992,9 +1029,14 @@ namespace Microsoft.FSharp.Collections halt() else halt() - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + override self.OnComplete _ = + self.Value._2.Dispose() + }) |> fun all -> all.Value._1 + [] let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with @@ -1004,6 +1046,7 @@ namespace Microsoft.FSharp.Collections 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 |> compose { new SeqFactory<'T,'U>() with @@ -1012,6 +1055,7 @@ namespace Microsoft.FSharp.Collections member __.ProcessNext input = TailCall.avoid (next.ProcessNext (f input)) } } + [] let inline mapi f source = source |> compose { new SeqFactory<'T,'U>() with @@ -1088,6 +1132,7 @@ namespace Microsoft.FSharp.Collections | Some value -> TailCall.avoid (next.ProcessNext value) | None -> false } } + [] let inline distinct (source:ISeq<'T>) : ISeq<'T> when 'T:equality = source |> compose { new SeqFactory<'T,'T>() with @@ -1098,6 +1143,7 @@ namespace Microsoft.FSharp.Collections if this.Value.Add input then TailCall.avoid (next.ProcessNext input) else false } } + [] let inline distinctBy (keyf:'T->'Key) (source:ISeq<'T>) :ISeq<'T> when 'Key:equality = source |> compose { new SeqFactory<'T,'T>() with @@ -1108,6 +1154,7 @@ namespace Microsoft.FSharp.Collections if this.Value.Add (keyf input) then TailCall.avoid (next.ProcessNext input) else false } } + [] let inline max (source: ISeq<'T>) : 'T when 'T:comparison = source @@ -1127,6 +1174,7 @@ namespace Microsoft.FSharp.Collections }) |> fun max -> max.Value._2 + [] let inline maxBy (f :'T -> 'U) (source: ISeq<'T>) : 'T when 'U:comparison = source @@ -1150,6 +1198,7 @@ namespace Microsoft.FSharp.Collections }) |> fun min -> min.Value._3 + [] let inline min (source: ISeq< 'T>) : 'T when 'T:comparison = source @@ -1169,6 +1218,7 @@ namespace Microsoft.FSharp.Collections }) |> fun min -> min.Value._2 + [] let inline minBy (f : 'T -> 'U) (source: ISeq<'T>) : 'T = source @@ -1192,6 +1242,7 @@ namespace Microsoft.FSharp.Collections }) |> fun min -> min.Value._3 + [] let inline pairwise (source:ISeq<'T>) : ISeq<'T * 'T> = source |> compose { new SeqFactory<'T,'T * 'T>() with @@ -1214,6 +1265,7 @@ namespace Microsoft.FSharp.Collections TailCall.avoid (next.ProcessNext currentPair) }} + [] let inline reduce (f:'T->'T->'T) (source : ISeq<'T>) : 'T = source @@ -1233,6 +1285,7 @@ namespace Microsoft.FSharp.Collections }) |> fun reduced -> reduced.Value._2 + [] let inline scan (folder:'State->'T->'State) (initialState: 'State) (source:ISeq<'T>) :ISeq<'State> = source |> compose { new SeqFactory<'T,'State>() with @@ -1242,6 +1295,7 @@ namespace Microsoft.FSharp.Collections this.Value <- folder this.Value input TailCall.avoid (next.ProcessNext this.Value) } } + [] let inline skip (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with @@ -1273,6 +1327,7 @@ namespace Microsoft.FSharp.Collections false }} + [] let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with @@ -1288,6 +1343,7 @@ namespace Microsoft.FSharp.Collections else TailCall.avoid (next.ProcessNext input) }} + [] let inline sum (source:ISeq< ^T>) : ^T when ^T:(static member Zero : ^T) @@ -1300,6 +1356,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun sum -> sum.Value + [] let inline sumBy (f : 'T -> ^U) (source: ISeq<'T>) : ^U when ^U:(static member Zero : ^U) @@ -1312,6 +1369,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun sum -> sum.Value + [] let inline take (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with @@ -1336,6 +1394,7 @@ namespace Microsoft.FSharp.Collections [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] }} + [] let inline takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with @@ -1349,6 +1408,7 @@ namespace Microsoft.FSharp.Collections false }} + [] let inline tail (source:ISeq<'T>) :ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with @@ -1384,15 +1444,18 @@ namespace Microsoft.FSharp.Collections false }} + [] let inline 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 tryPick f (source:ISeq<'T>) = source @@ -1407,6 +1470,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun pick -> pick.Value + [] let tryFind f (source:ISeq<'T>) = source @@ -1419,6 +1483,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun find -> find.Value + [] let inline tryFindIndex (predicate:'T->bool) (source:ISeq<'T>) : int option = source @@ -1449,6 +1514,7 @@ namespace Microsoft.FSharp.Collections else Some tried.Value._2 + [] let inline windowed (windowSize:int) (source:ISeq<'T>) : ISeq<'T[]> = source |> compose { new SeqFactory<'T,'T[]>() with From 6c014b593f5b896458010338ff0aea40cb952446 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 19:38:40 -0500 Subject: [PATCH 249/286] and cleanup to folders --- src/fsharp/FSharp.Core/seqcomposer.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 03b7ba90919..1d1a758e792 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -1427,6 +1427,7 @@ namespace Microsoft.FSharp.Collections invalidArg "source" (SR.GetString(SR.notEnoughElements)) }} + [] let inline truncate (truncateCount:int) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with From 7b1b88193956253d864fb1d80d9e204b9467eca4 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 19:51:22 -0500 Subject: [PATCH 250/286] inline compareWith --- src/fsharp/FSharp.Core/seq.fs | 24 ++++-------------------- src/fsharp/FSharp.Core/seqcomposer.fs | 23 +++++++++++++++++++++++ src/fsharp/FSharp.Core/seqcomposer.fsi | 3 +++ 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 6e6492221d7..6245eb765e5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -312,30 +312,14 @@ namespace Microsoft.FSharp.Collections [] let collect f sources = map f sources |> concat - [] + [] let compareWith (f:'T -> 'T -> int) (source1 : seq<'T>) (source2: seq<'T>) = + checkNonNull "source1" source1 checkNonNull "source2" source2 - - use e2 = source2.GetEnumerator() let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) + (source1|>toComposer, source2|>toComposer) + ||> Composer.Seq.compareWith (fun a b -> f.Invoke(a,b)) - source1 - |> foreach (fun halt -> - { new Composer.Core.FolderWithOnComplete<'T,int> (0) with - override this.ProcessNext value = - if not (e2.MoveNext()) then - this.Value <- 1 - halt () - else - let c = f.Invoke (value, e2.Current) - if c <> 0 then - this.Value <- c - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - member this.OnComplete _ = - if this.Value = 0 && e2.MoveNext() then - this.Value <- -1 }) - |> fun compare -> compare.Value [] let ofList (source : 'T list) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 1d1a758e792..01e7b138456 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -1122,6 +1122,29 @@ namespace Microsoft.FSharp.Collections self.Value._2.Dispose () } } + [] + let inline compareWith (f:'T -> 'T -> int) (source1 :ISeq<'T>) (source2:ISeq<'T>) : int = + source1 + |> foreach (fun halt -> + { new FolderWithOnComplete<'T,Values>>(Values<_,_>(0,source2.GetEnumerator())) with + override self.ProcessNext value = + if not (self.Value._2.MoveNext()) then + self.Value._1 <- 1 + halt () + else + let c = f value self.Value._2.Current + if c <> 0 then + self.Value._1 <- c + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + override self.OnComplete _ = + if self.Value._1 = 0 && self.Value._2.MoveNext() then + self.Value._1 <- -1 + self.Value._2.Dispose() + }) + |> fun compare -> compare.Value._1 + [] let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = source |> compose { new SeqFactory<'T,'U>() with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 997469ca2cf..db61c6c6acf 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -490,6 +490,9 @@ namespace Microsoft.FSharp.Collections [] val inline map3<'First,'Second,'Third,'U> : map:('First->'Second->'Third->'U) -> source1:ISeq<'First> -> source2:ISeq<'Second> -> source3:ISeq<'Third> -> ISeq<'U> + [] + 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> From 6d9a764c7d591b34ccca04d139a24e33ffa5ca17 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 20:28:25 -0500 Subject: [PATCH 251/286] elevate composers --- src/fsharp/FSharp.Core/seq.fs | 134 +- src/fsharp/FSharp.Core/seqcomposer.fs | 2559 ++++++++++++------------ src/fsharp/FSharp.Core/seqcomposer.fsi | 707 ++++--- 3 files changed, 1697 insertions(+), 1703 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 6245eb765e5..c5adc43ac6f 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -15,7 +15,6 @@ namespace Microsoft.FSharp.Collections open Microsoft.FSharp.Collections open Microsoft.FSharp.Collections.Composer open Microsoft.FSharp.Collections.Composer.Core - open Microsoft.FSharp.Collections.Composer.Seq open Microsoft.FSharp.Primitives.Basics open Microsoft.FSharp.Collections.IEnumerator @@ -47,25 +46,25 @@ namespace Microsoft.FSharp.Collections [] let toComposer (source:seq<'T>): Composer.Core.ISeq<'T> = - Composer.Seq.toComposer source + Composer.toComposer source let inline foreach f (source:seq<_>) = - Composer.Seq.foreach f (toComposer source) + Composer.foreach f (toComposer source) let private seqFactory (createSeqComponent:#SeqFactory<_,_>) (source:seq<'T>) = match source with | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose createSeqComponent) - | :? array<'T> as a -> Upcast.enumerable (Composer.Seq.Array.create a createSeqComponent) - | :? list<'T> as a -> Upcast.enumerable (Composer.Seq.List.create a createSeqComponent) + | :? array<'T> as a -> Upcast.enumerable (Composer.Array.create a createSeqComponent) + | :? list<'T> as a -> Upcast.enumerable (Composer.List.create a createSeqComponent) | null -> nullArg "source" - | _ -> Upcast.enumerable (Composer.Seq.Enumerable.create source createSeqComponent) + | _ -> Upcast.enumerable (Composer.Enumerable.create source createSeqComponent) [] let delay f = mkDelayedSeq f [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : seq<'T> = - Composer.Seq.unfold generator state + Composer.unfold generator state |> Upcast.enumerable [] @@ -73,25 +72,26 @@ namespace Microsoft.FSharp.Collections [] let initInfinite<'T> (f:int->'T) : IEnumerable<'T> = - Composer.Seq.initInfinite f + Composer.initInfinite f |> Upcast.enumerable [] let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> = - Composer.Seq.init count f + Composer.init count f |> Upcast.enumerable [] let iter f (source : seq<'T>) = - source |> toComposer |> Composer.Seq.iter f + source |> toComposer |> Composer.iter f [] let tryHead (source : seq<_>) = - source |> toComposer |> Composer.Seq.tryHead + source |> toComposer |> Composer.tryHead [] let skip count (source: seq<_>) = - source |> toComposer |> Composer.Seq.skip count |> Upcast.enumerable + source |> toComposer + |> Composer.skip (SR.GetString SR.notEnoughElements) count |> Upcast.enumerable let invalidArgumnetIndex = invalidArgFmt "index" @@ -99,7 +99,7 @@ namespace Microsoft.FSharp.Collections let item i (source : seq<'T>) = if i < 0 then invalidArgInputMustBeNonNegative "index" i else source - |> toComposer |> Composer.Seq.skip i |> Upcast.enumerable + |> toComposer |> Composer.skip (SR.GetString SR.notEnoughElements) i |> Upcast.enumerable |> tryHead |> function | None -> invalidArgFmt "index" "{0}\nseq was short by 1 element" [|SR.GetString SR.notEnoughElements|] @@ -107,7 +107,7 @@ namespace Microsoft.FSharp.Collections [] let tryItem i (source:seq<'T>) = - source |> toComposer |> Composer.Seq.tryItem i + source |> toComposer |> Composer.tryItem (SR.GetString SR.notEnoughElements) i [] let nth i (source : seq<'T>) = item i source @@ -115,19 +115,19 @@ namespace Microsoft.FSharp.Collections [] let iteri f (source:seq<'T>) = let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f - source |> toComposer |> Composer.Seq.iteri (fun idx a -> f.Invoke(idx,a)) + source |> toComposer |> Composer.iteri (fun idx a -> f.Invoke(idx,a)) [] let exists f (source:seq<'T>) = - source |> toComposer |> Composer.Seq.exists f + source |> toComposer |> Composer.exists f [] let inline contains element (source:seq<'T>) = - source |> toComposer |> Composer.Seq.contains element + source |> toComposer |> Composer.contains element [] let forall f (source:seq<'T>) = - source |> toComposer |> Composer.Seq.forall f + source |> toComposer |> Composer.forall f [] let iter2 (f:'T->'U->unit) (source1 : seq<'T>) (source2 : seq<'U>) = @@ -135,7 +135,7 @@ namespace Microsoft.FSharp.Collections checkNonNull "source2" source2 let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) (source1|>toComposer, source2|>toComposer) - ||> Composer.Seq.iter2 (fun a b -> f.Invoke(a,b)) + ||> Composer.iter2 (fun a b -> f.Invoke(a,b)) [] @@ -144,7 +144,7 @@ namespace Microsoft.FSharp.Collections checkNonNull "source2" source2 let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) (source1|>toComposer, source2|>toComposer) - ||> Composer.Seq.iteri2 (fun idx a b -> f.Invoke(idx,a,b)) + ||> Composer.iteri2 (fun idx a b -> f.Invoke(idx,a,b)) // Build an IEnumerble by wrapping/transforming iterators as they get generated. @@ -156,19 +156,19 @@ namespace Microsoft.FSharp.Collections [] let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> = - source |> toComposer |> Composer.Seq.filter f |> Upcast.enumerable + source |> toComposer |> Composer.filter f |> Upcast.enumerable [] let where f source = filter f source [] let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> = - source |> toComposer |> Composer.Seq.map f |> Upcast.enumerable + source |> toComposer |> Composer.map f |> Upcast.enumerable [] let mapi f source = let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt f - source |> toComposer |> Composer.Seq.mapi (fun idx a ->f.Invoke(idx,a)) |> Upcast.enumerable + source |> toComposer |> Composer.mapi (fun idx a ->f.Invoke(idx,a)) |> Upcast.enumerable [] let mapi2 (mapfn:int->'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) = @@ -176,29 +176,29 @@ namespace Microsoft.FSharp.Collections checkNonNull "source2" source2 let f = OptimizedClosures.FSharpFunc.Adapt mapfn (source1|>toComposer, source2|>toComposer) - ||> Composer.Seq.mapi2 (fun idx a b ->f.Invoke(idx,a,b)) |> Upcast.enumerable + ||> Composer.mapi2 (fun idx a b ->f.Invoke(idx,a,b)) |> Upcast.enumerable [] let map2<'T,'U,'V> (mapfn:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = checkNonNull "source1" source1 checkNonNull "source2" source2 (source1|>toComposer, source2|>toComposer) - ||> Composer.Seq.map2 mapfn |> Upcast.enumerable + ||> Composer.map2 mapfn |> Upcast.enumerable [] let map3 mapfn source1 source2 source3 = checkNonNull "source2" source2 checkNonNull "source3" source3 (source1|>toComposer, source2|>toComposer, source3|>toComposer) - |||> Composer.Seq.map3 mapfn |> Upcast.enumerable + |||> Composer.map3 mapfn |> Upcast.enumerable [] let choose f source = - source |> toComposer |> Composer.Seq.choose f |> Upcast.enumerable + source |> toComposer |> Composer.choose f |> Upcast.enumerable [] let indexed source = - source |> toComposer |> Composer.Seq.indexed |> Upcast.enumerable + source |> toComposer |> Composer.indexed |> Upcast.enumerable [] let zip source1 source2 = @@ -215,7 +215,7 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source : seq<'T>) = - source |> toComposer |> Composer.Seq.tryPick f + source |> toComposer |> Composer.tryPick f [] let pick f source = @@ -225,7 +225,7 @@ namespace Microsoft.FSharp.Collections [] let tryFind f (source : seq<'T>) = - source |> toComposer |> Composer.Seq.tryFind f + source |> toComposer |> Composer.tryFind f [] let find f source = @@ -238,7 +238,7 @@ namespace Microsoft.FSharp.Collections if count < 0 then invalidArgInputMustBeNonNegative "count" count (* Note: don't create or dispose any IEnumerable if n = 0 *) if count = 0 then empty else - source |> toComposer |> Composer.Seq.take count |> Upcast.enumerable + source |> toComposer |> Composer.take (SR.GetString SR.notEnoughElements) count |> Upcast.enumerable [] let isEmpty (source : seq<'T>) = @@ -254,7 +254,7 @@ namespace Microsoft.FSharp.Collections [] let concat (sources:seq<#seq<'T>>) : seq<'T> = checkNonNull "sources" sources - upcast Composer.Seq.Enumerable.ConcatEnumerable sources + upcast Composer.Enumerable.ConcatEnumerable sources [] let length (source : seq<'T>) = @@ -274,7 +274,7 @@ namespace Microsoft.FSharp.Collections let fold<'T,'State> (f:'State->'T->'State) (x:'State) (source:seq<'T>) = let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) source |> toComposer - |> Composer.Seq.fold<'T,'State>(fun (a:'State) (b:'T) -> f.Invoke(a,b)) x + |> Composer.fold<'T,'State>(fun (a:'State) (b:'T) -> f.Invoke(a,b)) x [] @@ -283,12 +283,12 @@ namespace Microsoft.FSharp.Collections checkNonNull "source2" source2 let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) (source1 |> toComposer, source2|>toComposer) - ||> Composer.Seq.fold2(fun s a b -> f.Invoke(s,a,b)) state + ||> Composer.fold2(fun s a b -> f.Invoke(s,a,b)) state [] let reduce f (source : seq<'T>) = let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - source |> toComposer |> Composer.Seq.reduce(fun a b -> f.Invoke(a,b)) + source |> toComposer |> Composer.reduce(fun a b -> f.Invoke(a,b)) [] let replicate count x = @@ -305,8 +305,8 @@ namespace Microsoft.FSharp.Collections checkNonNull "source1" source1 checkNonNull "source2" source2 match source1 with - | :? Composer.Seq.Enumerable.EnumerableBase<'T> as s -> s.Append source2 - | _ -> Upcast.enumerable (new Composer.Seq.Enumerable.AppendEnumerable<_>([source2; source1])) + | :? Composer.Enumerable.EnumerableBase<'T> as s -> s.Append source2 + | _ -> Upcast.enumerable (new Composer.Enumerable.AppendEnumerable<_>([source2; source1])) [] @@ -318,7 +318,7 @@ namespace Microsoft.FSharp.Collections checkNonNull "source2" source2 let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) (source1|>toComposer, source2|>toComposer) - ||> Composer.Seq.compareWith (fun a b -> f.Invoke(a,b)) + ||> Composer.compareWith (fun a b -> f.Invoke(a,b)) [] @@ -334,7 +334,7 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source : 'T array) = checkNonNull "source" source - Upcast.enumerable (Composer.Seq.Array.createId source) + Upcast.enumerable (Composer.Array.createId source) [] let toArray (source : seq<'T>) = @@ -388,15 +388,15 @@ namespace Microsoft.FSharp.Collections [] let truncate n (source: seq<'T>) = if n <= 0 then empty else - source |> toComposer |> Composer.Seq.truncate n |> Upcast.enumerable + source |> toComposer |> Composer.truncate n |> Upcast.enumerable [] let pairwise<'T> (source:seq<'T>) : seq<'T*'T> = - source |> toComposer |> Composer.Seq.pairwise |> Upcast.enumerable + source |> toComposer |> Composer.pairwise |> Upcast.enumerable [] let scan<'T,'State> (folder:'State->'T->'State) (state:'State) (source:seq<'T>) : seq<'State> = - source |> toComposer |> Composer.Seq.scan folder state |> Upcast.enumerable + source |> toComposer |> Composer.scan folder state |> Upcast.enumerable [] let tryFindBack f (source : seq<'T>) = @@ -418,7 +418,7 @@ namespace Microsoft.FSharp.Collections [] let tryFindIndex p (source:seq<_>) = - source |> toComposer |> Composer.Seq.tryFindIndex p + source |> toComposer |> Composer.tryFindIndex p [] let findIndex p (source:seq<_>) = @@ -441,7 +441,7 @@ namespace Microsoft.FSharp.Collections let windowed windowSize (source: seq<_>) = if windowSize <= 0 then invalidArgFmt "windowSize" "{0}\nwindowSize = {1}" [|SR.GetString SR.inputMustBePositive; windowSize|] - source |> toComposer |> Composer.Seq.windowed windowSize |> Upcast.enumerable + source |> toComposer |> Composer.windowed windowSize |> Upcast.enumerable [] let cache (source : seq<'T>) = @@ -559,11 +559,11 @@ namespace Microsoft.FSharp.Collections [] let distinct source = - source |> toComposer |> Composer.Seq.distinct |> Upcast.enumerable + source |> toComposer |> Composer.distinct |> Upcast.enumerable [] let distinctBy keyf source = - source |> toComposer |> Composer.Seq.distinctBy keyf |> Upcast.enumerable + source |> toComposer |> Composer.distinctBy keyf |> Upcast.enumerable [] let sortBy keyf source = @@ -572,7 +572,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceBy keyf array array - Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedSort) + Upcast.enumerable (Composer.Array.createDelayedId delayedSort) [] let sort source = @@ -581,7 +581,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlace array array - Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedSort) + Upcast.enumerable (Composer.Array.createDelayedId delayedSort) [] let sortWith f source = @@ -590,7 +590,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.stableSortInPlaceWith f array array - Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedSort) + Upcast.enumerable (Composer.Array.createDelayedId delayedSort) [] let inline sortByDescending keyf source = @@ -639,27 +639,27 @@ namespace Microsoft.FSharp.Collections [] let inline sum (source:seq<'a>) : 'a = - source |> toComposer |> Composer.Seq.sum + source |> toComposer |> Composer.sum [] let inline sumBy (f : 'T -> ^U) (source: seq<'T>) : ^U = - source |> toComposer |> Composer.Seq.sumBy f + source |> toComposer |> Composer.sumBy f [] let inline average (source: seq< ^a>) : ^a = - source |> toComposer |> Composer.Seq.average + source |> toComposer |> Composer.average [] let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = - source |> toComposer |> Composer.Seq.averageBy f + source |> toComposer |> Composer.averageBy f [] let inline min (source: seq<'T>): 'T when 'T : comparison = - source |> toComposer |> Composer.Seq.min + source |> toComposer |> Composer.min [] let inline minBy (projection: 'T -> 'U when 'U:comparison) (source: seq<'T>) : 'T = - source |> toComposer |> Composer.Seq.minBy projection + source |> toComposer |> Composer.minBy projection (* [] let inline minValBy (f : 'T -> 'U) (source: seq<'T>) : 'U = @@ -679,11 +679,11 @@ namespace Microsoft.FSharp.Collections *) [] let inline max (source: seq<'T>) = - source |> toComposer |> Composer.Seq.max + source |> toComposer |> Composer.max [] let inline maxBy (projection: 'T -> 'U) (source: seq<'T>) : 'T = - source |> toComposer |> Composer.Seq.maxBy projection + source |> toComposer |> Composer.maxBy projection (* [] @@ -704,11 +704,11 @@ namespace Microsoft.FSharp.Collections *) [] let takeWhile predicate (source: seq<_>) = - source |> toComposer |> Composer.Seq.takeWhile predicate |> Upcast.enumerable + source |> toComposer |> Composer.takeWhile predicate |> Upcast.enumerable [] let skipWhile predicate (source: seq<_>) = - source |> toComposer |> Composer.Seq.skipWhile predicate |> Upcast.enumerable + source |> toComposer |> Composer.skipWhile predicate |> Upcast.enumerable [] let forall2 p (source1: seq<_>) (source2: seq<_>) = @@ -716,7 +716,7 @@ namespace Microsoft.FSharp.Collections checkNonNull "source2" source2 let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt p (source1|>toComposer, source2|>toComposer) - ||> Composer.Seq.forall2 (fun a b -> p.Invoke(a,b)) + ||> Composer.forall2 (fun a b -> p.Invoke(a,b)) [] let exists2 p (source1: seq<_>) (source2: seq<_>) = @@ -724,7 +724,7 @@ namespace Microsoft.FSharp.Collections checkNonNull "source2" source2 let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt p (source1|>toComposer, source2|>toComposer) - ||> Composer.Seq.exists2 (fun a b -> p.Invoke(a,b)) + ||> Composer.exists2 (fun a b -> p.Invoke(a,b)) [] let head (source : seq<_>) = @@ -734,11 +734,11 @@ namespace Microsoft.FSharp.Collections [] let tail (source: seq<'T>) = - source |> toComposer |> Composer.Seq.tail |> Upcast.enumerable + source |> toComposer |> Composer.tail (SR.GetString SR.notEnoughElements) |> Upcast.enumerable [] let tryLast (source : seq<_>) = - source |> toComposer |> Composer.Seq.tryLast + source |> toComposer |> Composer.tryLast [] let last (source : seq<_>) = @@ -748,7 +748,7 @@ namespace Microsoft.FSharp.Collections [] let exactlyOne (source : seq<_>) = - source |> toComposer |> Composer.Seq.exactlyOne + source |> toComposer |> Composer.exactlyOne (SR.GetString(SR.inputSequenceTooLong)) member this.OnComplete _ = if this.Value._1 then @@ -764,7 +764,7 @@ namespace Microsoft.FSharp.Collections let array = source |> toArray Array.Reverse array array - Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedReverse) + Upcast.enumerable (Composer.Array.createDelayedId delayedReverse) [] let permute f (source:seq<_>) = @@ -773,7 +773,7 @@ namespace Microsoft.FSharp.Collections source |> toArray |> Array.permute f - Upcast.enumerable (Composer.Seq.Array.createDelayedId delayedPermute) + Upcast.enumerable (Composer.Array.createDelayedId delayedPermute) [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = @@ -792,7 +792,7 @@ namespace Microsoft.FSharp.Collections let except (itemsToExclude: seq<'T>) (source: seq<'T>) = checkNonNull "itemsToExclude" itemsToExclude if isEmpty itemsToExclude then source else - source |> toComposer |> Composer.Seq.except itemsToExclude |> Upcast.enumerable + source |> toComposer |> Composer.except itemsToExclude |> Upcast.enumerable [] let chunkBySize chunkSize (source : seq<_>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 01e7b138456..bbc6ab3cdf9 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -151,1425 +151,1420 @@ namespace Microsoft.FSharp.Collections let inline enumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline iCompletionChain (t:#ICompletionChain) : ICompletionChain = (# "" t : ICompletionChain #) - module internal Seq = - type ComposedFactory<'T,'U,'V> private (first:SeqFactory<'T,'U>, second:SeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = - inherit SeqFactory<'T,'V>() - override __.PipeIdx = - secondPipeIdx + type ComposedFactory<'T,'U,'V> private (first:SeqFactory<'T,'U>, second:SeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = + inherit SeqFactory<'T,'V>() + + override __.PipeIdx = + secondPipeIdx + + override this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'V,'W>) : Consumer<'T,'W> = + first.Create outOfBand pipeIdx (second.Create outOfBand secondPipeIdx next) + + static member Combine (first:SeqFactory<'T,'U>) (second:SeqFactory<'U,'V>) : SeqFactory<'T,'V> = + upcast ComposedFactory(first, second, first.PipeIdx+1) + + and IdentityFactory<'T> () = + inherit SeqFactory<'T,'T> () + static let singleton : SeqFactory<'T,'T> = upcast (IdentityFactory<'T>()) + override __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next + static member Instance = singleton + + and ISkipping = + // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip + // and it can only do it at the start of a sequence + abstract Skipping : unit -> bool + + type SeqProcessNextStates = + | InProcess = 0 + | NotStarted = 1 + | Finished = 2 + + type Result<'T>() = + let mutable haltedIdx = 0 + + member val Current = Unchecked.defaultof<'T> with get, set + member val SeqState = SeqProcessNextStates.NotStarted with get, set + member __.HaltedIdx = haltedIdx + + interface IOutOfBand with + member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx + + // SetResult<> is used at the end of the chain of SeqComponents to assign the final value + type SetResult<'T> (result:Result<'T>) = + inherit Consumer<'T,'T>() + + override __.ProcessNext (input:'T) : bool = + result.Current <- input + true + + type OutOfBand() = + let mutable haltedIdx = 0 + interface IOutOfBand with member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx + member __.HaltedIdx = haltedIdx + + module ForEach = + let enumerable (enumerable:IEnumerable<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + use enumerator = enumerable.GetEnumerator () + while (outOfBand.HaltedIdx = 0) && (enumerator.MoveNext ()) do + consumer.ProcessNext enumerator.Current |> ignore + + let array (array:array<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + let mutable idx = 0 + while (outOfBand.HaltedIdx = 0) && (idx < array.Length) do + consumer.ProcessNext array.[idx] |> ignore + idx <- idx + 1 + + let list (alist:list<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + let rec iterate lst = + match outOfBand.HaltedIdx, lst with + | 0, hd :: tl -> + consumer.ProcessNext hd |> ignore + iterate tl + | _ -> () + iterate alist + + let unfold (generator:'S->option<'T*'S>) state (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + let rec iterate current = + match outOfBand.HaltedIdx, generator current with + | 0, Some (item, next) -> + consumer.ProcessNext item |> ignore + iterate next + | _ -> () + + iterate state + + let makeIsSkipping (consumer:Consumer<'T,'U>) = + match box consumer with + | :? ISkipping as skip -> skip.Skipping + | _ -> fun () -> false + + let init f (terminatingIdx:int) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + let mutable idx = -1 + let isSkipping = makeIsSkipping consumer + let mutable maybeSkipping = true + while (outOfBand.HaltedIdx = 0) && (idx < terminatingIdx) do + if maybeSkipping then + maybeSkipping <- isSkipping () + + if not maybeSkipping then + consumer.ProcessNext (f (idx+1)) |> ignore + + idx <- idx + 1 + + let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:SeqFactory<'T,'U>) executeOn = + let pipeline = OutOfBand() + let result = f (fun () -> (pipeline:>IOutOfBand).StopFurtherProcessing (current.PipeIdx+1)) + let consumer = current.Build pipeline result + try + executeOn pipeline consumer + let mutable stopTailCall = () + (Upcast.iCompletionChain consumer).ChainComplete (&stopTailCall, pipeline.HaltedIdx) + result + finally + let mutable stopTailCall = () + (Upcast.iCompletionChain consumer).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 - override this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'V,'W>) : Consumer<'T,'W> = - first.Create outOfBand pipeIdx (second.Create outOfBand secondPipeIdx next) - - static member Combine (first:SeqFactory<'T,'U>) (second:SeqFactory<'U,'V>) : SeqFactory<'T,'V> = - upcast ComposedFactory(first, second, first.PipeIdx+1) - - and IdentityFactory<'T> () = - inherit SeqFactory<'T,'T> () - static let singleton : SeqFactory<'T,'T> = upcast (IdentityFactory<'T>()) - override __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next - static member Instance = singleton - - and ISkipping = - // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip - // and it can only do it at the start of a sequence - abstract Skipping : unit -> bool - - type SeqProcessNextStates = - | InProcess = 0 - | NotStarted = 1 - | Finished = 2 - - type Result<'T>() = - let mutable haltedIdx = 0 - - member val Current = Unchecked.defaultof<'T> with get, set - member val SeqState = SeqProcessNextStates.NotStarted with get, set - member __.HaltedIdx = haltedIdx - - interface IOutOfBand with - member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx - - // SetResult<> is used at the end of the chain of SeqComponents to assign the final value - type SetResult<'T> (result:Result<'T>) = - inherit Consumer<'T,'T>() - - override __.ProcessNext (input:'T) : bool = - result.Current <- input - true - - type OutOfBand() = - let mutable haltedIdx = 0 - interface IOutOfBand with member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx - member __.HaltedIdx = haltedIdx - - module ForEach = - let enumerable (enumerable:IEnumerable<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = - use enumerator = enumerable.GetEnumerator () - while (outOfBand.HaltedIdx = 0) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - - let array (array:array<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = - let mutable idx = 0 - while (outOfBand.HaltedIdx = 0) && (idx < array.Length) do - consumer.ProcessNext array.[idx] |> ignore - idx <- idx + 1 - - let list (alist:list<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = - let rec iterate lst = - match outOfBand.HaltedIdx, lst with - | 0, hd :: tl -> - consumer.ProcessNext hd |> ignore - iterate tl - | _ -> () - iterate alist - - let unfold (generator:'S->option<'T*'S>) state (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = - let rec iterate current = - match outOfBand.HaltedIdx, generator current with - | 0, Some (item, next) -> - consumer.ProcessNext item |> ignore - iterate next - | _ -> () - - iterate state - - let makeIsSkipping (consumer:Consumer<'T,'U>) = - match box consumer with - | :? ISkipping as skip -> skip.Skipping - | _ -> fun () -> false - - let init f (terminatingIdx:int) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = - let mutable idx = -1 - let isSkipping = makeIsSkipping consumer - let mutable maybeSkipping = true - while (outOfBand.HaltedIdx = 0) && (idx < terminatingIdx) do - if maybeSkipping then - maybeSkipping <- isSkipping () - - if not maybeSkipping then - consumer.ProcessNext (f (idx+1)) |> ignore - - idx <- idx + 1 - - let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:SeqFactory<'T,'U>) executeOn = - let pipeline = OutOfBand() - let result = f (fun () -> (pipeline:>IOutOfBand).StopFurtherProcessing (current.PipeIdx+1)) - let consumer = current.Build pipeline result - try - executeOn pipeline consumer - let mutable stopTailCall = () - (Upcast.iCompletionChain consumer).ChainComplete (&stopTailCall, pipeline.HaltedIdx) - result - finally + [] + type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ICompletionChain) = + interface IDisposable with + member __.Dispose() : unit = let mutable stopTailCall = () - (Upcast.iCompletionChain consumer).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>, seqComponent:ICompletionChain) = - interface IDisposable with - member __.Dispose() : unit = - let mutable stopTailCall = () - seqComponent.ChainDispose (&stopTailCall) + seqComponent.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 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.Current - else - match result.SeqState with - | SeqProcessNextStates.NotStarted -> notStarted() - | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> failwith "library implementation error: all states should have been handled" + interface IEnumerator<'T> with + member __.Current = + if result.SeqState = SeqProcessNextStates.InProcess then result.Current + 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)" + and [] EnumerableBase<'T> () = + let derivedClassShouldImplement () = + failwith "library implementation error: derived class should implement (should be abstract)" - abstract member Append : (seq<'T>) -> IEnumerable<'T> + abstract member Append : (seq<'T>) -> IEnumerable<'T> - default this.Append source = Upcast.enumerable (AppendEnumerable [this; source]) + default this.Append source = Upcast.enumerable (AppendEnumerable [this; source]) - interface IEnumerable with - member this.GetEnumerator () : IEnumerator = - let genericEnumerable = Upcast.enumerable this - let genericEnumerator = genericEnumerable.GetEnumerator () - Upcast.enumeratorNonGeneric genericEnumerator + 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 IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () - interface ISeq<'T> with - member __.Compose _ = derivedClassShouldImplement () - member __.ForEach _ = derivedClassShouldImplement () + interface ISeq<'T> with + member __.Compose _ = derivedClassShouldImplement () + member __.ForEach _ = derivedClassShouldImplement () - and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, seqComponent) + and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + inherit EnumeratorBase<'U>(result, seqComponent) - let rec moveNext () = - if (result.HaltedIdx = 0) && source.MoveNext () then - if seqComponent.ProcessNext source.Current then - true - else - moveNext () + let rec moveNext () = + if (result.HaltedIdx = 0) && source.MoveNext () then + if seqComponent.ProcessNext source.Current then + true else - result.SeqState <- SeqProcessNextStates.Finished - let mutable stopTailCall = () - (Upcast.iCompletionChain seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess moveNext () + else + result.SeqState <- SeqProcessNextStates.Finished + let mutable stopTailCall = () + (Upcast.iCompletionChain seqComponent).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 = () + (Upcast.iCompletionChain seqComponent).ChainDispose (&stopTailCall) - interface IDisposable with - member __.Dispose() = - try - source.Dispose () - finally - let mutable stopTailCall = () - (Upcast.iCompletionChain seqComponent).ChainDispose (&stopTailCall) + and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqFactory<'T,'U>) = + inherit EnumerableBase<'U>() - and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqFactory<'T,'U>) = - inherit EnumerableBase<'U>() + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Build result (SetResult<'U> result), result)) - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Build result (SetResult<'U> result), result)) + interface ISeq<'U> with + member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) - interface ISeq<'U> with - member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.enumerable enumerable) - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.enumerable enumerable) + and ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = + let mutable state = SeqProcessNextStates.NotStarted + let main = sources.GetEnumerator () - 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 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 - let rec moveNext () = - if active.MoveNext () then - true - elif main.MoveNext () then - active.Dispose () - active <- main.Current.GetEnumerator () - moveNext () + interface IEnumerator<'T> with + member __.Current = + if state = SeqProcessNextStates.InProcess then active.Current else - state <- SeqProcessNextStates.Finished - false + match state with + | SeqProcessNextStates.NotStarted -> notStarted() + | SeqProcessNextStates.Finished -> alreadyFinished() + | _ -> failwith "library implementation error: all states should have been handled" - 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 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 () + interface IDisposable with + member __.Dispose() = + main.Dispose () + active.Dispose () - and AppendEnumerable<'T> (sources:list>) = - inherit EnumerableBase<'T>() + and AppendEnumerable<'T> (sources:list>) = + inherit EnumerableBase<'T>() - interface IEnumerable<'T> with - member this.GetEnumerator () : IEnumerator<'T> = - Upcast.enumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = + Upcast.enumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) - override this.Append source = - Upcast.enumerable (AppendEnumerable (source :: sources)) + override this.Append source = + Upcast.enumerable (AppendEnumerable (source :: sources)) - interface ISeq<'T> with - member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable<'T,'V>(this, next)) + interface ISeq<'T> with + member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (Enumerable<'T,'V>(this, next)) - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) - and ConcatEnumerable<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = - inherit EnumerableBase<'T>() + 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 IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = + Upcast.enumerator (new ConcatEnumerator<_,_> (sources)) - interface ISeq<'T> with - member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable<'T,'V>(this, next)) + interface ISeq<'T> with + member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (Enumerable<'T,'V>(this, next)) - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) - let create enumerable current = - Upcast.seq (Enumerable(enumerable, current)) + let create enumerable current = + Upcast.seq (Enumerable(enumerable, current)) - module EmptyEnumerable = - type Enumerable<'T> () = - inherit Enumerable.EnumerableBase<'T>() + module EmptyEnumerable = + type Enumerable<'T> () = + inherit Enumerable.EnumerableBase<'T>() - static let singleton = Enumerable<'T>() :> ISeq<'T> - static member Instance = singleton + static let singleton = Enumerable<'T>() :> ISeq<'T> + static member Instance = singleton - interface IEnumerable<'T> with - member this.GetEnumerator () : IEnumerator<'T> = IEnumerator.Empty<'T>() + interface IEnumerable<'T> with + member this.GetEnumerator () : IEnumerator<'T> = IEnumerator.Empty<'T>() - override this.Append source = - Upcast.enumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) + override this.Append source = + Upcast.enumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) - interface ISeq<'T> with - member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable.Enumerable<'T,'V>(this, next)) + interface ISeq<'T> with + member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (Enumerable.Enumerable<'T,'V>(this, next)) - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) - module Array = - type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) + module Array = + type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) - let mutable idx = 0 - let mutable array = Unchecked.defaultof<_> + let mutable idx = 0 + let mutable array = Unchecked.defaultof<_> - let mutable initMoveNext = Unchecked.defaultof<_> - do - initMoveNext <- - fun () -> - result.SeqState <- SeqProcessNextStates.InProcess - array <- delayedArray () - initMoveNext <- ignore + let mutable initMoveNext = Unchecked.defaultof<_> + do + initMoveNext <- + fun () -> + result.SeqState <- SeqProcessNextStates.InProcess + array <- delayedArray () + initMoveNext <- ignore - let rec moveNext () = - if (result.HaltedIdx = 0) && idx < array.Length then - idx <- idx+1 - if seqComponent.ProcessNext array.[idx-1] then - true - else - moveNext () + let rec moveNext () = + if (result.HaltedIdx = 0) && idx < array.Length then + idx <- idx+1 + if seqComponent.ProcessNext array.[idx-1] then + true else - result.SeqState <- SeqProcessNextStates.Finished - let mutable stopTailCall = () - (Upcast.iCompletionChain seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) - false - - interface IEnumerator with - member __.MoveNext () = - initMoveNext () moveNext () + else + result.SeqState <- SeqProcessNextStates.Finished + let mutable stopTailCall = () + (Upcast.iCompletionChain seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) + false - type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqFactory<'T,'U>) = - inherit Enumerable.EnumerableBase<'U>() + interface IEnumerator with + member __.MoveNext () = + initMoveNext () + moveNext () - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Build result (SetResult<'U> result), result)) + type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqFactory<'T,'U>) = + inherit Enumerable.EnumerableBase<'U>() - interface ISeq<'U> with - member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Build result (SetResult<'U> result), result)) - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.array (delayedArray ())) + interface ISeq<'U> with + member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) - let createDelayed (delayedArray:unit->array<'T>) (current:SeqFactory<'T,'U>) = - Upcast.seq (Enumerable(delayedArray, current)) + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.array (delayedArray ())) - let create (array:array<'T>) (current:SeqFactory<'T,'U>) = - createDelayed (fun () -> array) current + let createDelayed (delayedArray:unit->array<'T>) (current:SeqFactory<'T,'U>) = + Upcast.seq (Enumerable(delayedArray, current)) - let createDelayedId (delayedArray:unit -> array<'T>) = - createDelayed delayedArray IdentityFactory.Instance + let create (array:array<'T>) (current:SeqFactory<'T,'U>) = + createDelayed (fun () -> array) current - let createId (array:array<'T>) = - create array IdentityFactory.Instance + let createDelayedId (delayedArray:unit -> array<'T>) = + createDelayed delayedArray IdentityFactory.Instance - module List = - type Enumerator<'T,'U>(alist:list<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) + let createId (array:array<'T>) = + create array IdentityFactory.Instance - let mutable list = alist + module List = + type Enumerator<'T,'U>(alist:list<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) - let rec moveNext current = - match result.HaltedIdx, current with - | 0, head::tail -> - if seqComponent.ProcessNext head then - list <- tail - true - else - moveNext tail - | _ -> - result.SeqState <- SeqProcessNextStates.Finished - let mutable stopTailCall = () - (Upcast.iCompletionChain seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) - false + let mutable list = alist - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess - moveNext list + let rec moveNext current = + match result.HaltedIdx, current with + | 0, head::tail -> + if seqComponent.ProcessNext head then + list <- tail + true + else + moveNext tail + | _ -> + result.SeqState <- SeqProcessNextStates.Finished + let mutable stopTailCall = () + (Upcast.iCompletionChain seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) + false - type Enumerable<'T,'U>(alist:list<'T>, current:SeqFactory<'T,'U>) = - inherit Enumerable.EnumerableBase<'U>() + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext list - interface IEnumerable<'U> with - member this.GetEnumerator () : IEnumerator<'U> = - let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Build result (SetResult<'U> result), result)) + type Enumerable<'T,'U>(alist:list<'T>, current:SeqFactory<'T,'U>) = + inherit Enumerable.EnumerableBase<'U>() - interface ISeq<'U> with - member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) + interface IEnumerable<'U> with + member this.GetEnumerator () : IEnumerator<'U> = + let result = Result<'U> () + Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Build result (SetResult<'U> result), result)) - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.list alist) + interface ISeq<'U> with + member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) - let create alist current = - Upcast.seq (Enumerable(alist, current)) + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.list alist) - module Unfold = - type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) + let create alist current = + Upcast.seq (Enumerable(alist, current)) - let mutable current = state + module Unfold = + type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) - let rec moveNext () = - match result.HaltedIdx, generator current with - | 0, Some (item, nextState) -> - current <- nextState - if seqComponent.ProcessNext item then - true - else - moveNext () - | _ -> false + let mutable current = state - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess + let rec moveNext () = + match result.HaltedIdx, generator current with + | 0, Some (item, nextState) -> + current <- nextState + if seqComponent.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, current:SeqFactory<'T,'U>) = + 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, current.Build result (SetResult<'U> result), result)) + + interface ISeq<'U> with + member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) + + member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + ForEach.execute f current (ForEach.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, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) + + let isSkipping = + ForEach.makeIsSkipping seqComponent + + 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 - type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:SeqFactory<'T,'U>) = - 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, current.Build result (SetResult<'U> result), result)) - - interface ISeq<'U> with - member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) - - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = - ForEach.execute f current (ForEach.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, seqComponent:Consumer<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) - - let isSkipping = - ForEach.makeIsSkipping seqComponent - - 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 + // 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 seqComponent.ProcessNext (f idx) then - true - else - moveNext () - elif (result.HaltedIdx = 0) && idx = System.Int32.MaxValue then - raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + if maybeSkipping then + moveNext () + elif seqComponent.ProcessNext (f idx) then + true else - result.SeqState <- SeqProcessNextStates.Finished - let mutable stopTailCall = () - (Upcast.iCompletionChain seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) - false - - interface IEnumerator with - member __.MoveNext () = - result.SeqState <- SeqProcessNextStates.InProcess moveNext () - - type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqFactory<'T,'U>) = - 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, current.Build result (SetResult<'U> result), result)) - - interface ISeq<'U> with - member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) - - member this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = - let terminatingIdx = getTerminatingIdx count - ForEach.execute createResult current (ForEach.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 + elif (result.HaltedIdx = 0) && idx = System.Int32.MaxValue then + raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) + else + result.SeqState <- SeqProcessNextStates.Finished + let mutable stopTailCall = () + (Upcast.iCompletionChain seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) + false + + interface IEnumerator with + member __.MoveNext () = + result.SeqState <- SeqProcessNextStates.InProcess + moveNext () + + type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqFactory<'T,'U>) = + 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, current.Build result (SetResult<'U> result), result)) + + interface ISeq<'U> with + member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = + Upcast.seq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) + + member this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = + let terminatingIdx = getTerminatingIdx count + ForEach.execute createResult current (ForEach.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 - elif !index = unstarted then - setIndex 0 + else + setIndex (!index + 1) true - else ( - if !index = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) - if !index = finalIndex then - false - else - setIndex (!index + 1) - true - ) - member self.Reset() = noReset() - interface System.IDisposable with - member x.Dispose() = () } - - type EnumerableDecider<'T>(count:Nullable, f:int->'T) = - 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 + ) + member self.Reset() = noReset() + interface System.IDisposable with + member x.Dispose() = () } + + type EnumerableDecider<'T>(count:Nullable, f:int->'T) = + 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.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (Enumerable<'T,'V>(count, f, next)) + + member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (Upcast.enumerable this)) + + + [] + let toComposer (source:seq<'T>) : ISeq<'T> = + match source with + | :? ISeq<'T> as s -> s + | :? array<'T> as a -> Upcast.seq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) + | :? list<'T> as a -> Upcast.seq (List.Enumerable(a, IdentityFactory.Instance)) + | null -> nullArg "source" + | _ -> Upcast.seq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) + + + let inline foreach f (source:ISeq<_>) = source.ForEach f + let inline compose (factory:#SeqFactory<_,_>) (source:ISeq<'T>) = source.Compose factory + + [] + let 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) = + source + |> foreach (fun _ -> + { new FolderWithOnComplete< ^T, Values< ^T, int>> (Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + override this.ProcessNext value = + this.Value._1 <- Checked.(+) this.Value._1 value + this.Value._2 <- this.Value._2 + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + override this.OnComplete _ = + if this.Value._2 = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) + |> fun total -> LanguagePrimitives.DivideByInt< ^T> total.Value._1 total.Value._2 + + + [] + let 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) = + source + |> foreach (fun _ -> + { new FolderWithOnComplete<'T,Values<'U, int>>(Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + override this.ProcessNext value = + this.Value._1 <- Checked.(+) this.Value._1 (f value) + this.Value._2 <- this.Value._2 + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + override this.OnComplete _ = + if this.Value._2 = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) + |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.Value._1 total.Value._2 + + + [] + let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance + + + [] + let inline exactlyOne errorString (source : ISeq<'T>) : 'T = + source + |> foreach (fun halt -> + { new FolderWithOnComplete<'T, Values>(Values(true, Unchecked.defaultof<'T>, false)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + else + this.Value._3 <- true + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + override this.OnComplete _ = + if this.Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + elif this.Value._3 then + invalidArg "source" errorString }) + |> fun one -> one.Value._2 + + + [] + let inline fold<'T,'State> (f:'State->'T->'State) (seed:'State) (source:ISeq<'T>) : 'State = + source + |> foreach (fun _ -> + { new Folder<'T,'State>(seed) with + override this.ProcessNext value = + this.Value <- f this.Value value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + }) + |> fun folded -> folded.Value + + + [] + let inline fold2<'T1,'T2,'State> (folder:'State->'T1->'T2->'State) (state:'State) (source1: ISeq<'T1>) (source2: ISeq<'T2>) = + source1 + |> foreach (fun halt -> + { new FolderWithOnComplete<_,Values<'State,IEnumerator<'T2>>>(Values<_,_>(state,source2.GetEnumerator())) with + override self.ProcessNext value = + if self.Value._2.MoveNext() then + self.Value._1 <- folder self.Value._1 value self.Value._2.Current + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) - interface ISeq<'T> with - member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable<'T,'V>(count, f, next)) + override self.OnComplete _ = + self.Value._2.Dispose() + }) + |> fun fold -> fold.Value._1 - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (Upcast.enumerable this)) + [] + let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = + Upcast.seq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) - [] - let toComposer (source:seq<'T>) : ISeq<'T> = - match source with - | :? ISeq<'T> as s -> s - | :? array<'T> as a -> Upcast.seq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) - | :? list<'T> as a -> Upcast.seq (List.Enumerable(a, IdentityFactory.Instance)) - | null -> nullArg "source" - | _ -> Upcast.seq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) + [] + let initInfinite<'T> (f:int->'T) : ISeq<'T> = + Upcast.seq (new Init.EnumerableDecider<'T>(Nullable (), f)) - let inline foreach f (source:ISeq<_>) = - source.ForEach f + [] + 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)) - let inline compose (factory:#SeqFactory<_,_>) (source:ISeq<'T>) = - source.Compose factory + [] + let iter f (source:ISeq<'T>) = + source + |> foreach (fun _ -> + { new Consumer<'T,'T> () with + override this.ProcessNext value = + f value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> ignore - [] - let 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) = - source - |> foreach (fun _ -> - { new FolderWithOnComplete< ^T, Values< ^T, int>> (Values<_,_>(LanguagePrimitives.GenericZero, 0)) with - override this.ProcessNext value = - this.Value._1 <- Checked.(+) this.Value._1 value - this.Value._2 <- this.Value._2 + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - - member this.OnComplete _ = - if this.Value._2 = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - |> fun total -> LanguagePrimitives.DivideByInt< ^T> total.Value._1 total.Value._2 - - - [] - let 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) = - source - |> foreach (fun _ -> - { new FolderWithOnComplete<'T,Values<'U, int>>(Values<_,_>(LanguagePrimitives.GenericZero, 0)) with - override this.ProcessNext value = - this.Value._1 <- Checked.(+) this.Value._1 (f value) - this.Value._2 <- this.Value._2 + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - member this.OnComplete _ = - if this.Value._2 = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.Value._1 total.Value._2 + [] + let inline iter2 (f:'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = + source1 + |> foreach (fun halt -> + { new FolderWithOnComplete<'T,IEnumerator<'U>> (source2.GetEnumerator()) with + override self.ProcessNext value = + if self.Value.MoveNext() then + f value self.Value.Current + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + override self.OnComplete _ = + self.Value.Dispose() + }) + |> ignore + + + [] + let inline iteri2 (f:int->'T->'U->unit) (source1:ISeq<'T>) (source2:seq<'U>) : unit = + source1 + |> foreach (fun halt -> + { new FolderWithOnComplete<'T,Values>>(Values<_,_>(-1,source2.GetEnumerator())) with + override self.ProcessNext value = + if self.Value._2.MoveNext() then + f self.Value._1 value self.Value._2.Current + self.Value._1 <- self.Value._1 + 1 + Unchecked.defaultof<_> + else + halt() + Unchecked.defaultof<_> + + override self.OnComplete _ = + self.Value._2.Dispose() + + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> ignore + + + [] + let tryHead (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, Option<'T>> (None) with + override this.ProcessNext value = + this.Value <- Some value + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun head -> head.Value + + + [] + let iteri f (source:ISeq<'T>) = + source + |> foreach (fun _ -> + { new Folder<'T, int> (0) with + override this.ProcessNext value = + f this.Value value + this.Value <- this.Value + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> ignore + + [] + let inline except (itemsToExclude: seq<'T>) (source:ISeq<'T>) : ISeq<'T> when 'T:equality = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { new ConsumerChainedWithState<'T,'V,Lazy>> + (Upcast.iCompletionChain next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with + override this.ProcessNext (input:'T) : bool = + if this.Value.Value.Add input then TailCall.avoid (next.ProcessNext input) + else false + }} + + + [] + let exists f (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, bool> (false) with + override this.ProcessNext value = + if f value then + this.Value <- true + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun exists -> exists.Value + + + [] + let exists2 (predicate:'T->'U->bool) (source1: ISeq<'T>) (source2: ISeq<'U>) : bool = + source1 + |> foreach (fun halt -> + { new FolderWithOnComplete<'T,Values>>(Values<_,_>(false,source2.GetEnumerator())) with + override self.ProcessNext value = + if self.Value._2.MoveNext() then + if predicate value self.Value._2.Current then + self.Value._1 <- true + halt() + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + override self.OnComplete _ = + self.Value._2.Dispose() - [] - let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance + }) + |> fun exists -> exists.Value._1 - [] - let inline exactlyOne (source : ISeq<'T>) : 'T = - source - |> foreach (fun halt -> - { new FolderWithOnComplete<'T, Values>(Values(true, Unchecked.defaultof<'T>, false)) with - override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - else - this.Value._3 <- true - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - elif this.Value._3 then - invalidArg "source" (SR.GetString(SR.inputSequenceTooLong)) }) - |> fun one -> one.Value._2 - - - [] - let inline fold<'T,'State> (f:'State->'T->'State) (seed:'State) (source:ISeq<'T>) : 'State = - source - |> foreach (fun _ -> - { new Folder<'T,'State>(seed) with - override this.ProcessNext value = - this.Value <- f this.Value value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - }) - |> fun folded -> folded.Value - - - [] - let inline fold2<'T1,'T2,'State> (folder:'State->'T1->'T2->'State) (state:'State) (source1: ISeq<'T1>) (source2: ISeq<'T2>) = - source1 - |> foreach (fun halt -> - { new FolderWithOnComplete<_,Values<'State,IEnumerator<'T2>>>(Values<_,_>(state,source2.GetEnumerator())) with - override self.ProcessNext value = - if self.Value._2.MoveNext() then - self.Value._1 <- folder self.Value._1 value self.Value._2.Current - else + [] + let inline contains element (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, bool> (false) with + override this.ProcessNext value = + if element = value then + this.Value <- true + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun contains -> contains.Value + + + [] + let forall predicate (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, bool> (true) with + override this.ProcessNext value = + if not (predicate value) then + this.Value <- false + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun forall -> forall.Value + + + [] + let inline forall2 predicate (source1:ISeq<'T>) (source2:ISeq<'U>) : bool = + source1 + |> foreach (fun halt -> + { new FolderWithOnComplete<'T,Values>>(Values<_,_>(true,source2.GetEnumerator())) with + override self.ProcessNext value = + if self.Value._2.MoveNext() then + if not (predicate value self.Value._2.Current) then + self.Value._1 <- false halt() - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + else + halt() + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + override self.OnComplete _ = + self.Value._2.Dispose() + }) + |> fun all -> all.Value._1 + + + [] + let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with + member __.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 |> compose { new SeqFactory<'T,'U>() with + member __.Create _ _ next = + upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with + member __.ProcessNext input = + TailCall.avoid (next.ProcessNext (f input)) } } + + + [] + let inline mapi f source = + source |> compose { new SeqFactory<'T,'U>() with + member __.Create _ _ next = + upcast { new ConsumerChainedWithState<'T,'V,int>(Upcast.iCompletionChain next, -1) with + override this.ProcessNext (input:'T) : bool = + this.Value <- this.Value + 1 + TailCall.avoid (next.ProcessNext (f this.Value input)) } } + + + [] + let inline map2<'First,'Second,'U> (map:'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = + source1 |> compose { new SeqFactory<'First,'U>() with + member __.Create<'V> outOfBand pipeIdx next = + upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, IEnumerator<'Second>>(Upcast.iCompletionChain next, (source2.GetEnumerator ())) with + member self.ProcessNext input = + if self.Value.MoveNext () then + TailCall.avoid (next.ProcessNext (map input self.Value.Current)) + else + outOfBand.StopFurtherProcessing pipeIdx + false + override self.OnDispose () = () override self.OnComplete _ = - self.Value._2.Dispose() - }) - |> fun fold -> fold.Value._1 - - - [] - let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = - Upcast.seq (new Unfold.Enumerable<'T,'T,'State>(generator, state, IdentityFactory.Instance)) - - - [] - let initInfinite<'T> (f:int->'T) : ISeq<'T> = - Upcast.seq (new Init.EnumerableDecider<'T>(Nullable (), f)) + self.Value.Dispose () } } - [] - 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)) - - - [] - let iter f (source:ISeq<'T>) = - source - |> foreach (fun _ -> - { new Consumer<'T,'T> () with - override this.ProcessNext value = - f value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> ignore - - - [] - let inline iter2 (f:'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = - source1 - |> foreach (fun halt -> - { new FolderWithOnComplete<'T,IEnumerator<'U>> (source2.GetEnumerator()) with - override self.ProcessNext value = - if self.Value.MoveNext() then - f value self.Value.Current + [] + let inline mapi2<'First,'Second,'U> (map:int -> 'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = + source1 |> compose { new SeqFactory<'First,'U>() with + member __.Create<'V> outOfBand pipeIdx next = + upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values>> + (Upcast.iCompletionChain next, Values<_,_>(-1, source2.GetEnumerator ())) with + member self.ProcessNext input = + if self.Value._2.MoveNext () then + self.Value._1 <- self.Value._1 + 1 + TailCall.avoid (next.ProcessNext (map self.Value._1 input self.Value._2.Current)) else - halt() - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + outOfBand.StopFurtherProcessing pipeIdx + false + override self.OnDispose () = () override self.OnComplete _ = - self.Value.Dispose() - }) - |> ignore - - - [] - let inline iteri2 (f:int->'T->'U->unit) (source1:ISeq<'T>) (source2:seq<'U>) : unit = - source1 - |> foreach (fun halt -> - { new FolderWithOnComplete<'T,Values>>(Values<_,_>(-1,source2.GetEnumerator())) with - override self.ProcessNext value = - if self.Value._2.MoveNext() then - f self.Value._1 value self.Value._2.Current - self.Value._1 <- self.Value._1 + 1 - Unchecked.defaultof<_> + self.Value._2.Dispose () } } + + + [] + let inline map3<'First,'Second,'Third,'U> + (map:'First->'Second->'Third->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) (source3:ISeq<'Third>) : ISeq<'U> = + source1 |> compose { new SeqFactory<'First,'U>() with + member __.Create<'V> outOfBand pipeIdx next = + upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values,IEnumerator<'Third>>> + (Upcast.iCompletionChain next, Values<_,_>(source2.GetEnumerator(),source3.GetEnumerator())) with + member self.ProcessNext input = + if self.Value._1.MoveNext() && self.Value._2.MoveNext () then + TailCall.avoid (next.ProcessNext (map input self.Value._1 .Current self.Value._2.Current)) else - halt() - Unchecked.defaultof<_> + outOfBand.StopFurtherProcessing pipeIdx + false + override self.OnDispose () = () override self.OnComplete _ = - self.Value._2.Dispose() - - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> ignore - - - [] - let tryHead (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, Option<'T>> (None) with - override this.ProcessNext value = - this.Value <- Some value + self.Value._1.Dispose () + self.Value._2.Dispose () } } + + + [] + let inline compareWith (f:'T -> 'T -> int) (source1 :ISeq<'T>) (source2:ISeq<'T>) : int = + source1 + |> foreach (fun halt -> + { new FolderWithOnComplete<'T,Values>>(Values<_,_>(0,source2.GetEnumerator())) with + override self.ProcessNext value = + if not (self.Value._2.MoveNext()) then + self.Value._1 <- 1 halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun head -> head.Value - - - [] - let iteri f (source:ISeq<'T>) = - source - |> foreach (fun _ -> - { new Folder<'T, int> (0) with - override this.ProcessNext value = - f this.Value value - this.Value <- this.Value + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> ignore - - [] - let inline except (itemsToExclude: seq<'T>) (source:ISeq<'T>) : ISeq<'T> when 'T:equality = - source |> compose { new SeqFactory<'T,'T>() with - member __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,Lazy>> - (Upcast.iCompletionChain next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with - override this.ProcessNext (input:'T) : bool = - if this.Value.Value.Add input then TailCall.avoid (next.ProcessNext input) - else false - }} - - - [] - let exists f (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, bool> (false) with - override this.ProcessNext value = - if f value then - this.Value <- true + else + let c = f value self.Value._2.Current + if c <> 0 then + self.Value._1 <- c halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun exists -> exists.Value - - - [] - let exists2 (predicate:'T->'U->bool) (source1: ISeq<'T>) (source2: ISeq<'U>) : bool = - source1 - |> foreach (fun halt -> - { new FolderWithOnComplete<'T,Values>>(Values<_,_>(false,source2.GetEnumerator())) with - override self.ProcessNext value = - if self.Value._2.MoveNext() then - if predicate value self.Value._2.Current then - self.Value._1 <- true - halt() - else - halt() - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + override self.OnComplete _ = + if self.Value._1 = 0 && self.Value._2.MoveNext() then + self.Value._1 <- -1 + self.Value._2.Dispose() + }) + |> fun compare -> compare.Value._1 + + [] + let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = + source |> compose { new SeqFactory<'T,'U>() with + member __.Create _ _ next = + upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with + member __.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 |> compose { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { new ConsumerChainedWithState<'T,'V,HashSet<'T>> + (Upcast.iCompletionChain next,(HashSet<'T>(HashIdentity.Structural<'T>))) with + override this.ProcessNext (input:'T) : bool = + if this.Value.Add input then TailCall.avoid (next.ProcessNext input) + else false } } + + + [] + let inline distinctBy (keyf:'T->'Key) (source:ISeq<'T>) :ISeq<'T> when 'Key:equality = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { new ConsumerChainedWithState<'T,'V,HashSet<'Key>> + (Upcast.iCompletionChain next,(HashSet<'Key>(HashIdentity.Structural<'Key>))) with + override this.ProcessNext (input:'T) : bool = + if this.Value.Add (keyf input) then TailCall.avoid (next.ProcessNext input) + else false } } + + + [] + let inline max (source: ISeq<'T>) : 'T when 'T:comparison = + source + |> foreach (fun _ -> + { new FolderWithOnComplete<'T,Values>(Values<_,_>(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + elif value > this.Value._2 then + this.Value._2 <- value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + override this.OnComplete _ = + if this.Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun max -> max.Value._2 + + + [] + let inline maxBy (f :'T -> 'U) (source: ISeq<'T>) : 'T when 'U:comparison = + source + |> foreach (fun _ -> + { new FolderWithOnComplete<'T,Values>(Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + match this.Value._1, f value with + | true, valueU -> + this.Value._1 <- false + this.Value._2 <- valueU + this.Value._3 <- value + | false, valueU when valueU > this.Value._2 -> + this.Value._2 <- valueU + this.Value._3 <- value + | _ -> () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + override this.OnComplete _ = + if this.Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun min -> min.Value._3 + + + [] + let inline min (source: ISeq< 'T>) : 'T when 'T:comparison = + source + |> foreach (fun _ -> + { new FolderWithOnComplete<'T,Values>(Values<_,_>(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + elif value < this.Value._2 then + this.Value._2 <- value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + override this.OnComplete _ = + if this.Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun min -> min.Value._2 + + + [] + let inline minBy (f : 'T -> 'U) (source: ISeq<'T>) : 'T = + source + |> foreach (fun _ -> + { new FolderWithOnComplete< 'T,Values>(Values<_,_,_>(true,Unchecked.defaultof< 'U>,Unchecked.defaultof< 'T>)) with + override this.ProcessNext value = + match this.Value._1, f value with + | true, valueU -> + this.Value._1 <- false + this.Value._2 <- valueU + this.Value._3 <- value + | false, valueU when valueU < this.Value._2 -> + this.Value._2 <- valueU + this.Value._3 <- value + | _ -> () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + + override this.OnComplete _ = + if this.Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun min -> min.Value._3 + + + [] + let inline pairwise (source:ISeq<'T>) : ISeq<'T * 'T> = + source |> compose { new SeqFactory<'T,'T * 'T>() with + member __.Create _ _ next = + upcast { new ConsumerChainedWithState<'T,'U,Values> + ( Upcast.iCompletionChain next + , Values + ((* isFirst = _1*) true + ,(* lastValue = _2*) Unchecked.defaultof<'T> + ) + ) with + override self.ProcessNext (input:'T) : bool = + if (*isFirst*) self.Value._1 then + self.Value._2 (*lastValue*)<- input + self.Value._1 (*isFirst*)<- false + false + else + let currentPair = self.Value._2, input + self.Value._2 (*lastValue*)<- input + TailCall.avoid (next.ProcessNext currentPair) + }} + + + [] + let inline reduce (f:'T->'T->'T) (source : ISeq<'T>) : 'T = + source + |> foreach (fun _ -> + { new FolderWithOnComplete<'T, Values>(Values<_,_>(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + else + this.Value._2 <- f this.Value._2 value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) - override self.OnComplete _ = - self.Value._2.Dispose() + override this.OnComplete _ = + if this.Value._1 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + }) + |> fun reduced -> reduced.Value._2 - }) - |> fun exists -> exists.Value._1 + [] + let inline scan (folder:'State->'T->'State) (initialState: 'State) (source:ISeq<'T>) :ISeq<'State> = + source |> compose { new SeqFactory<'T,'State>() with + member __.Create _ _ next = + upcast { new ConsumerChainedWithState<'T,'V,'State>(Upcast.iCompletionChain next, initialState) with + override this.ProcessNext (input:'T) : bool = + this.Value <- folder this.Value input + TailCall.avoid (next.ProcessNext this.Value) } } - [] - let inline contains element (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, bool> (false) with - override this.ProcessNext value = - if element = value then - this.Value <- true - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun contains -> contains.Value - - - [] - let forall predicate (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, bool> (true) with - override this.ProcessNext value = - if not (predicate value) then - this.Value <- false - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun forall -> forall.Value - - - [] - let inline forall2 predicate (source1:ISeq<'T>) (source2:ISeq<'U>) : bool = - source1 - |> foreach (fun halt -> - { new FolderWithOnComplete<'T,Values>>(Values<_,_>(true,source2.GetEnumerator())) with - override self.ProcessNext value = - if self.Value._2.MoveNext() then - if not (predicate value self.Value._2.Current) then - self.Value._1 <- false - halt() - else - halt() - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - override self.OnComplete _ = - self.Value._2.Dispose() - }) - |> fun all -> all.Value._1 - - - [] - let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source |> compose { new SeqFactory<'T,'T>() with - member __.Create _ _ next = - upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with - member __.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 |> compose { new SeqFactory<'T,'U>() with - member __.Create _ _ next = - upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with - member __.ProcessNext input = - TailCall.avoid (next.ProcessNext (f input)) } } - - - [] - let inline mapi f source = - source |> compose { new SeqFactory<'T,'U>() with - member __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,int>(Upcast.iCompletionChain next, -1) with - override this.ProcessNext (input:'T) : bool = - this.Value <- this.Value + 1 - TailCall.avoid (next.ProcessNext (f this.Value input)) } } - - - [] - let inline map2<'First,'Second,'U> (map:'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = - source1 |> compose { new SeqFactory<'First,'U>() with - member __.Create<'V> outOfBand pipeIdx next = - upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, IEnumerator<'Second>>(Upcast.iCompletionChain next, (source2.GetEnumerator ())) with - member self.ProcessNext input = - if self.Value.MoveNext () then - TailCall.avoid (next.ProcessNext (map input self.Value.Current)) - else - outOfBand.StopFurtherProcessing pipeIdx + [] + let inline skip (errorString:string) (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { + new ConsumerChainedWithStateAndCleanup<'T,'U,int>(Upcast.iCompletionChain next,(*count*)0) with + + override self.ProcessNext (input:'T) : bool = + if (*count*) self.Value < skipCount then + self.Value <- self.Value + 1 false + else + TailCall.avoid (next.ProcessNext input) override self.OnDispose () = () override self.OnComplete _ = - self.Value.Dispose () } } - - - [] - let inline mapi2<'First,'Second,'U> (map:int -> 'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = - source1 |> compose { new SeqFactory<'First,'U>() with - member __.Create<'V> outOfBand pipeIdx next = - upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values>> - (Upcast.iCompletionChain next, Values<_,_>(-1, source2.GetEnumerator ())) with - member self.ProcessNext input = - if self.Value._2.MoveNext () then - self.Value._1 <- self.Value._1 + 1 - TailCall.avoid (next.ProcessNext (map self.Value._1 input self.Value._2.Current)) + if (*count*) self.Value < skipCount then + let x = skipCount - self.Value + invalidOpFmt "{0}\ntried to skip {1} {2} past the end of the seq" + [|errorString; x; (if x=1 then "element" else "elements")|] + + interface ISkipping with + member self.Skipping () = + let self = self :?> ConsumerChainedWithState<'T,'U,int> + if (*count*) self.Value < skipCount then + self.Value <- self.Value + 1 + true else - outOfBand.StopFurtherProcessing pipeIdx false + }} - override self.OnDispose () = () - override self.OnComplete _ = - self.Value._2.Dispose () } } - - - [] - let inline map3<'First,'Second,'Third,'U> - (map:'First->'Second->'Third->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) (source3:ISeq<'Third>) : ISeq<'U> = - source1 |> compose { new SeqFactory<'First,'U>() with - member __.Create<'V> outOfBand pipeIdx next = - upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values,IEnumerator<'Third>>> - (Upcast.iCompletionChain next, Values<_,_>(source2.GetEnumerator(),source3.GetEnumerator())) with - member self.ProcessNext input = - if self.Value._1.MoveNext() && self.Value._2.MoveNext () then - TailCall.avoid (next.ProcessNext (map input self.Value._1 .Current self.Value._2.Current)) + + [] + let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { new ConsumerChainedWithState<'T,'V,bool>(Upcast.iCompletionChain next,true) with + override self.ProcessNext (input:'T) : bool = + if self.Value (*skip*) then + self.Value <- predicate input + if self.Value (*skip*) then + false else - outOfBand.StopFurtherProcessing pipeIdx + TailCall.avoid (next.ProcessNext input) + else + TailCall.avoid (next.ProcessNext input) }} + + + [] + let inline sum (source:ISeq< ^T>) : ^T + when ^T:(static member Zero : ^T) + and ^T:(static member (+) : ^T * ^T -> ^T) = + source + |> foreach (fun _ -> + { new Folder< ^T,^T> (LanguagePrimitives.GenericZero) with + override this.ProcessNext value = + this.Value <- Checked.(+) this.Value value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun sum -> sum.Value + + + [] + let inline sumBy (f : 'T -> ^U) (source: ISeq<'T>) : ^U + when ^U:(static member Zero : ^U) + and ^U:(static member (+) : ^U * ^U -> ^U) = + source + |> foreach (fun _ -> + { new Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + override this.ProcessNext value = + this.Value <- Checked.(+) this.Value (f value) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun sum -> sum.Value + + + [] + let inline take (errorString:string) (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create outOfBand pipelineIdx next = + upcast { + new ConsumerChainedWithStateAndCleanup<'T,'U,int>(Upcast.iCompletionChain next,(*count*)0) with + override self.ProcessNext (input:'T) : bool = + if (*count*) self.Value < takeCount then + self.Value <- self.Value + 1 + if self.Value = takeCount then + outOfBand.StopFurtherProcessing pipelineIdx + TailCall.avoid (next.ProcessNext input) + else + outOfBand.StopFurtherProcessing pipelineIdx false - override self.OnDispose () = () - override self.OnComplete _ = - self.Value._1.Dispose () - self.Value._2.Dispose () } } - - - [] - let inline compareWith (f:'T -> 'T -> int) (source1 :ISeq<'T>) (source2:ISeq<'T>) : int = - source1 - |> foreach (fun halt -> - { new FolderWithOnComplete<'T,Values>>(Values<_,_>(0,source2.GetEnumerator())) with - override self.ProcessNext value = - if not (self.Value._2.MoveNext()) then - self.Value._1 <- 1 - halt () + override this.OnDispose () = () + override this.OnComplete terminatingIdx = + if terminatingIdx < pipelineIdx && this.Value < takeCount then + let x = takeCount - this.Value + invalidOpFmt "tried to take {0} {1} past the end of the seq" + [|errorString; x; (if x=1 then "element" else "elements")|] + }} + + + [] + let inline takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create outOfBand pipeIdx next = + upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with + override __.ProcessNext (input:'T) : bool = + if predicate input then + TailCall.avoid (next.ProcessNext input) else - let c = f value self.Value._2.Current - if c <> 0 then - self.Value._1 <- c - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + outOfBand.StopFurtherProcessing pipeIdx + false + }} + + + [] + let inline tail errorString (source:ISeq<'T>) :ISeq<'T> = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create _ _ next = + upcast { new ConsumerChainedWithStateAndCleanup<'T,'V,bool>(Upcast.iCompletionChain next,(*first*) true) with + override self.ProcessNext (input:'T) : bool = + if (*first*) self.Value then + self.Value <- false + false + else + TailCall.avoid (next.ProcessNext input) + override self.OnDispose () = () override self.OnComplete _ = - if self.Value._1 = 0 && self.Value._2.MoveNext() then - self.Value._1 <- -1 - self.Value._2.Dispose() - }) - |> fun compare -> compare.Value._1 - - [] - let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = - source |> compose { new SeqFactory<'T,'U>() with - member __.Create _ _ next = - upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with - member __.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 |> compose { new SeqFactory<'T,'T>() with - member __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,HashSet<'T>> - (Upcast.iCompletionChain next,(HashSet<'T>(HashIdentity.Structural<'T>))) with - override this.ProcessNext (input:'T) : bool = - if this.Value.Add input then TailCall.avoid (next.ProcessNext input) - else false } } - - - [] - let inline distinctBy (keyf:'T->'Key) (source:ISeq<'T>) :ISeq<'T> when 'Key:equality = - source |> compose { new SeqFactory<'T,'T>() with - member __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,HashSet<'Key>> - (Upcast.iCompletionChain next,(HashSet<'Key>(HashIdentity.Structural<'Key>))) with - override this.ProcessNext (input:'T) : bool = - if this.Value.Add (keyf input) then TailCall.avoid (next.ProcessNext input) - else false } } - - - [] - let inline max (source: ISeq<'T>) : 'T when 'T:comparison = - source - |> foreach (fun _ -> - { new FolderWithOnComplete<'T,Values>(Values<_,_>(true, Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - elif value > this.Value._2 then - this.Value._2 <- value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun max -> max.Value._2 - - - [] - let inline maxBy (f :'T -> 'U) (source: ISeq<'T>) : 'T when 'U:comparison = - source - |> foreach (fun _ -> - { new FolderWithOnComplete<'T,Values>(Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - match this.Value._1, f value with - | true, valueU -> - this.Value._1 <- false - this.Value._2 <- valueU - this.Value._3 <- value - | false, valueU when valueU > this.Value._2 -> - this.Value._2 <- valueU - this.Value._3 <- value - | _ -> () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun min -> min.Value._3 - - - [] - let inline min (source: ISeq< 'T>) : 'T when 'T:comparison = - source - |> foreach (fun _ -> - { new FolderWithOnComplete<'T,Values>(Values<_,_>(true, Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - elif value < this.Value._2 then - this.Value._2 <- value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun min -> min.Value._2 - - - [] - let inline minBy (f : 'T -> 'U) (source: ISeq<'T>) : 'T = - source - |> foreach (fun _ -> - { new FolderWithOnComplete< 'T,Values>(Values<_,_,_>(true,Unchecked.defaultof< 'U>,Unchecked.defaultof< 'T>)) with - override this.ProcessNext value = - match this.Value._1, f value with - | true, valueU -> - this.Value._1 <- false - this.Value._2 <- valueU - this.Value._3 <- value - | false, valueU when valueU < this.Value._2 -> - this.Value._2 <- valueU - this.Value._3 <- value - | _ -> () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun min -> min.Value._3 - - - [] - let inline pairwise (source:ISeq<'T>) : ISeq<'T * 'T> = - source |> compose { new SeqFactory<'T,'T * 'T>() with - member __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'U,Values> - ( Upcast.iCompletionChain next - , Values - ((* isFirst = _1*) true - ,(* lastValue = _2*) Unchecked.defaultof<'T> - ) - ) with - override self.ProcessNext (input:'T) : bool = - if (*isFirst*) self.Value._1 then - self.Value._2 (*lastValue*)<- input - self.Value._1 (*isFirst*)<- false - false - else - let currentPair = self.Value._2, input - self.Value._2 (*lastValue*)<- input - TailCall.avoid (next.ProcessNext currentPair) - }} - - - [] - let inline reduce (f:'T->'T->'T) (source : ISeq<'T>) : 'T = - source - |> foreach (fun _ -> - { new FolderWithOnComplete<'T, Values>(Values<_,_>(true, Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - else - this.Value._2 <- f this.Value._2 value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun reduced -> reduced.Value._2 - - - [] - let inline scan (folder:'State->'T->'State) (initialState: 'State) (source:ISeq<'T>) :ISeq<'State> = - source |> compose { new SeqFactory<'T,'State>() with - member __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,'State>(Upcast.iCompletionChain next, initialState) with - override this.ProcessNext (input:'T) : bool = - this.Value <- folder this.Value input - TailCall.avoid (next.ProcessNext this.Value) } } - - - [] - let inline skip (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = - source |> compose { new SeqFactory<'T,'T>() with - member __.Create _ _ next = - upcast { - new ConsumerChainedWithStateAndCleanup<'T,'U,int>(Upcast.iCompletionChain next,(*count*)0) with - - override self.ProcessNext (input:'T) : bool = - if (*count*) self.Value < skipCount then - self.Value <- self.Value + 1 - false - else - TailCall.avoid (next.ProcessNext input) - - override self.OnDispose () = () - override self.OnComplete _ = - if (*count*) self.Value < skipCount then - let x = skipCount - self.Value - 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")|] - - interface ISkipping with - member self.Skipping () = - let self = self :?> ConsumerChainedWithState<'T,'U,int> - if (*count*) self.Value < skipCount then - self.Value <- self.Value + 1 - true - else - false - }} + if (*first*) self.Value then + invalidArg "source" errorString + }} - [] - let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source |> compose { new SeqFactory<'T,'T>() with - member __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,bool>(Upcast.iCompletionChain next,true) with + [] + let inline truncate (truncateCount:int) (source:ISeq<'T>) : ISeq<'T> = + source |> compose { new SeqFactory<'T,'T>() with + member __.Create outOfBand pipeIdx next = + upcast { + new ConsumerChainedWithState<'T,'U,int>(Upcast.iCompletionChain next,(*count*)0) with override self.ProcessNext (input:'T) : bool = - if self.Value (*skip*) then - self.Value <- predicate input - if self.Value (*skip*) then - false - else - TailCall.avoid (next.ProcessNext input) - else - TailCall.avoid (next.ProcessNext input) }} - - - [] - let inline sum (source:ISeq< ^T>) : ^T - when ^T:(static member Zero : ^T) - and ^T:(static member (+) : ^T * ^T -> ^T) = - source - |> foreach (fun _ -> - { new Folder< ^T,^T> (LanguagePrimitives.GenericZero) with - override this.ProcessNext value = - this.Value <- Checked.(+) this.Value value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun sum -> sum.Value - - - [] - let inline sumBy (f : 'T -> ^U) (source: ISeq<'T>) : ^U - when ^U:(static member Zero : ^U) - and ^U:(static member (+) : ^U * ^U -> ^U) = - source - |> foreach (fun _ -> - { new Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with - override this.ProcessNext value = - this.Value <- Checked.(+) this.Value (f value) - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun sum -> sum.Value - - - [] - let inline take (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = - source |> compose { new SeqFactory<'T,'T>() with - member __.Create outOfBand pipelineIdx next = - upcast { - new ConsumerChainedWithStateAndCleanup<'T,'U,int>(Upcast.iCompletionChain next,(*count*)0) with - override self.ProcessNext (input:'T) : bool = - if (*count*) self.Value < takeCount then - self.Value <- self.Value + 1 - if self.Value = takeCount then - outOfBand.StopFurtherProcessing pipelineIdx - TailCall.avoid (next.ProcessNext input) - else - outOfBand.StopFurtherProcessing pipelineIdx - false - - override this.OnDispose () = () - override this.OnComplete terminatingIdx = - if terminatingIdx < pipelineIdx && this.Value < takeCount then - let x = takeCount - this.Value - invalidOpFmt "tried to take {0} {1} past the end of the seq" - [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] - }} - - - [] - let inline takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source |> compose { new SeqFactory<'T,'T>() with - member __.Create outOfBand pipeIdx next = - upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with - override __.ProcessNext (input:'T) : bool = - if predicate input then + if (*count*) self.Value < truncateCount then + self.Value <- self.Value + 1 + if self.Value = truncateCount then + outOfBand.StopFurtherProcessing pipeIdx TailCall.avoid (next.ProcessNext input) else outOfBand.StopFurtherProcessing pipeIdx false - }} + }} - [] - let inline tail (source:ISeq<'T>) :ISeq<'T> = - source |> compose { new SeqFactory<'T,'T>() with - member __.Create _ _ next = - upcast { new ConsumerChainedWithStateAndCleanup<'T,'V,bool>(Upcast.iCompletionChain next,(*first*) true) with - override self.ProcessNext (input:'T) : bool = - if (*first*) self.Value then - self.Value <- false - false - else - TailCall.avoid (next.ProcessNext input) - - override self.OnDispose () = () - override self.OnComplete _ = - if (*first*) self.Value then - invalidArg "source" (SR.GetString(SR.notEnoughElements)) - }} - - - [] - let inline truncate (truncateCount:int) (source:ISeq<'T>) : ISeq<'T> = - source |> compose { new SeqFactory<'T,'T>() with - member __.Create outOfBand pipeIdx next = - upcast { - new ConsumerChainedWithState<'T,'U,int>(Upcast.iCompletionChain next,(*count*)0) with - override self.ProcessNext (input:'T) : bool = - if (*count*) self.Value < truncateCount then - self.Value <- self.Value + 1 - if self.Value = truncateCount then - outOfBand.StopFurtherProcessing pipeIdx - TailCall.avoid (next.ProcessNext input) - else - outOfBand.StopFurtherProcessing pipeIdx - false - }} + [] + let inline indexed source = + mapi (fun i x -> i,x) source - [] - let inline indexed source = - mapi (fun i x -> i,x) source + [] + let tryItem (errorString:string) index (source:ISeq<'T>) = + if index < 0 then None else + source |> skip errorString index |> tryHead - [] - let tryItem index (source:ISeq<'T>) = - if index < 0 then None else - source |> skip index |> tryHead + [] + let tryPick f (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, Option<'U>> (None) with + override this.ProcessNext value = + match f value with + | (Some _) as some -> + this.Value <- some + halt () + | None -> () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun pick -> pick.Value + + + [] + let tryFind f (source:ISeq<'T>) = + source + |> foreach (fun halt -> + { new Folder<'T, Option<'T>> (None) with + override this.ProcessNext value = + if f value then + this.Value <- Some value + halt () + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun find -> find.Value + + + [] + let inline tryFindIndex (predicate:'T->bool) (source:ISeq<'T>) : int option = + source + |> foreach (fun halt -> + { new Folder<'T, Values, int>>(Values<_,_>(None, 0)) with + override this.ProcessNext value = + if predicate value then + this.Value._1 <- Some(this.Value._2) + halt () + else + this.Value._2 <- this.Value._2 + 1 + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun tried -> tried.Value._1 + + [] + let inline tryLast (source :ISeq<'T>) : 'T option = + source + |> foreach (fun _ -> + { new Folder<'T, Values>(Values(true, Unchecked.defaultof<'T>)) with + override this.ProcessNext value = + if this.Value._1 then + this.Value._1 <- false + this.Value._2 <- value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + |> fun tried -> + if tried.Value._1 then + None + else + Some tried.Value._2 + + + [] + let inline windowed (windowSize:int) (source:ISeq<'T>) : ISeq<'T[]> = + source |> compose { new SeqFactory<'T,'T[]>() with + member __.Create outOfBand pipeIdx next = + upcast { + new ConsumerChainedWithState<'T,'U,Values<'T[],int,int>> + ( Upcast.iCompletionChain next + , Values<'T[],int,int> + ((*circularBuffer = _1 *) Array.zeroCreateUnchecked windowSize + ,(* idx = _2 *) 0 + ,(* priming = _3 *) windowSize-1 + ) + ) with + override self.ProcessNext (input:'T) : bool = + self.Value._1.[(* idx *)self.Value._2] <- input + self.Value._2 <- (* idx *)self.Value._2 + 1 + if (* idx *) self.Value._2 = windowSize then + self.Value._2 <- 0 - [] - let tryPick f (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, Option<'U>> (None) with - override this.ProcessNext value = - match f value with - | (Some _) as some -> - this.Value <- some - halt () - | None -> () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun pick -> pick.Value - - - [] - let tryFind f (source:ISeq<'T>) = - source - |> foreach (fun halt -> - { new Folder<'T, Option<'T>> (None) with - override this.ProcessNext value = - if f value then - this.Value <- Some value - halt () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun find -> find.Value - - - [] - let inline tryFindIndex (predicate:'T->bool) (source:ISeq<'T>) : int option = - source - |> foreach (fun halt -> - { new Folder<'T, Values, int>>(Values<_,_>(None, 0)) with - override this.ProcessNext value = - if predicate value then - this.Value._1 <- Some(this.Value._2) - halt () - else - this.Value._2 <- this.Value._2 + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun tried -> tried.Value._1 - - [] - let inline tryLast (source :ISeq<'T>) : 'T option = - source - |> foreach (fun _ -> - { new Folder<'T, Values>(Values(true, Unchecked.defaultof<'T>)) with - override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun tried -> - if tried.Value._1 then - None - else - Some tried.Value._2 - - - [] - let inline windowed (windowSize:int) (source:ISeq<'T>) : ISeq<'T[]> = - source |> compose { new SeqFactory<'T,'T[]>() with - member __.Create outOfBand pipeIdx next = - upcast { - new ConsumerChainedWithState<'T,'U,Values<'T[],int,int>> - ( Upcast.iCompletionChain next - , Values<'T[],int,int> - ((*circularBuffer = _1 *) Array.zeroCreateUnchecked windowSize - ,(* idx = _2 *) 0 - ,(* priming = _3 *) windowSize-1 - ) - ) with - override self.ProcessNext (input:'T) : bool = - self.Value._1.[(* idx *)self.Value._2] <- input - - self.Value._2 <- (* idx *)self.Value._2 + 1 - if (* idx *) self.Value._2 = windowSize then - self.Value._2 <- 0 - - if (* priming *) self.Value._3 > 0 then - self.Value._3 <- self.Value._3 - 1 - false + if (* priming *) self.Value._3 > 0 then + self.Value._3 <- self.Value._3 - 1 + false + else + if windowSize < 32 then + let window :'T [] = Array.init windowSize (fun i -> self.Value._1.[((* idx *)self.Value._2+i) % windowSize]: 'T) + TailCall.avoid (next.ProcessNext window) else - if windowSize < 32 then - let window :'T [] = Array.init windowSize (fun i -> self.Value._1.[((* idx *)self.Value._2+i) % windowSize]: 'T) - TailCall.avoid (next.ProcessNext window) - else - let window = Array.zeroCreateUnchecked windowSize - Array.Copy((*circularBuffer*)self.Value._1, (* idx *)self.Value._2, window, 0, windowSize - (* idx *)self.Value._2) - Array.Copy((*circularBuffer*)self.Value._1, 0, window, windowSize - (* idx *)self.Value._2, (* idx *)self.Value._2) - TailCall.avoid (next.ProcessNext window) - - }} + let window = Array.zeroCreateUnchecked windowSize + Array.Copy((*circularBuffer*)self.Value._1, (* idx *)self.Value._2, window, 0, windowSize - (* idx *)self.Value._2) + Array.Copy((*circularBuffer*)self.Value._1, 0, window, windowSize - (* idx *)self.Value._2, (* idx *)self.Value._2) + TailCall.avoid (next.ProcessNext window) + + }} diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index db61c6c6acf..c4f352f0988 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -124,450 +124,449 @@ namespace Microsoft.FSharp.Collections open Core - module internal Seq = - type ComposedFactory<'T,'U,'V> = - class - inherit SeqFactory<'T,'V> - private new : first: SeqFactory<'T,'U> * - second: SeqFactory<'U,'V> * - secondPipeIdx: PipeIdx -> - ComposedFactory<'T,'U,'V> - static member - Combine : first: SeqFactory<'T,'U> -> - second: SeqFactory<'U,'V> -> - SeqFactory<'T,'V> - end - and IdentityFactory<'T> = - class - inherit SeqFactory<'T,'T> - new : unit -> IdentityFactory<'T> - static member Instance : SeqFactory<'T,'T> - end - - and ISkipping = - interface - abstract member Skipping : unit -> bool - end - - type SeqProcessNextStates = - | InProcess = 0 - | NotStarted = 1 - | Finished = 2 - type Result<'T> = - class - interface IOutOfBand - new : unit -> Result<'T> - member Current : 'T - member HaltedIdx : int - member SeqState : SeqProcessNextStates - member Current : 'T with set - member SeqState : SeqProcessNextStates with set - end - type SetResult<'T> = - class - inherit Consumer<'T,'T> - new : result: Result<'T> -> SetResult<'T> - override ProcessNext : input:'T -> bool - end - type OutOfBand = - class - interface IOutOfBand - new : unit -> OutOfBand - member HaltedIdx : int - end - module ForEach = begin - val enumerable : + type ComposedFactory<'T,'U,'V> = + class + inherit SeqFactory<'T,'V> + private new : first: SeqFactory<'T,'U> * + second: SeqFactory<'U,'V> * + secondPipeIdx: PipeIdx -> + ComposedFactory<'T,'U,'V> + static member + Combine : first: SeqFactory<'T,'U> -> + second: SeqFactory<'U,'V> -> + SeqFactory<'T,'V> + end + and IdentityFactory<'T> = + class + inherit SeqFactory<'T,'T> + new : unit -> IdentityFactory<'T> + static member Instance : SeqFactory<'T,'T> + end + + and ISkipping = + interface + abstract member Skipping : unit -> bool + end + + type SeqProcessNextStates = + | InProcess = 0 + | NotStarted = 1 + | Finished = 2 + type Result<'T> = + class + interface IOutOfBand + new : unit -> Result<'T> + member Current : 'T + member HaltedIdx : int + member SeqState : SeqProcessNextStates + member Current : 'T with set + member SeqState : SeqProcessNextStates with set + end + type SetResult<'T> = + class + inherit Consumer<'T,'T> + new : result: Result<'T> -> SetResult<'T> + override ProcessNext : input:'T -> bool + end + type OutOfBand = + class + interface IOutOfBand + new : unit -> OutOfBand + member HaltedIdx : int + end + module ForEach = begin + val enumerable : enumerable:IEnumerable<'T> -> - outOfBand: OutOfBand -> - consumer: Consumer<'T,'U> -> unit - val array : + outOfBand: OutOfBand -> + consumer: Consumer<'T,'U> -> unit + val array : array:'T array -> - outOfBand: OutOfBand -> - consumer: Consumer<'T,'U> -> unit - val list : + outOfBand: OutOfBand -> + consumer: Consumer<'T,'U> -> unit + val list : alist:'T list -> - outOfBand: OutOfBand -> - consumer: Consumer<'T,'U> -> unit - val unfold : + outOfBand: OutOfBand -> + consumer: Consumer<'T,'U> -> unit + val unfold : generator:('S -> ('T * 'S) option) -> - state:'S -> - outOfBand: OutOfBand -> - consumer: Consumer<'T,'U> -> unit - val makeIsSkipping : + state:'S -> + outOfBand: OutOfBand -> + consumer: Consumer<'T,'U> -> unit + val makeIsSkipping : consumer: Consumer<'T,'U> -> (unit -> bool) - val init : + val init : f:(int -> 'T) -> - terminatingIdx:int -> - outOfBand: OutOfBand -> - consumer: Consumer<'T,'U> -> unit - val execute : + terminatingIdx:int -> + outOfBand: OutOfBand -> + consumer: Consumer<'T,'U> -> unit + val execute : f:((unit -> unit) -> 'a) -> - current: SeqFactory<'T,'U> -> - executeOn:( OutOfBand -> Consumer<'T,'U> -> - unit) -> 'a when 'a :> Consumer<'U,'U> - end - module Enumerable = begin - type Empty<'T> = + current: SeqFactory<'T,'U> -> + executeOn:( OutOfBand -> Consumer<'T,'U> -> + unit) -> 'a when 'a :> Consumer<'U,'U> + end + module Enumerable = begin + type Empty<'T> = class - interface IDisposable - interface IEnumerator - interface IEnumerator<'T> - new : unit -> Empty<'T> - end - type EmptyEnumerators<'T> = + interface IDisposable + interface IEnumerator + interface IEnumerator<'T> + new : unit -> Empty<'T> + end + type EmptyEnumerators<'T> = class - new : unit -> EmptyEnumerators<'T> - static member Element : IEnumerator<'T> - end - [] - type EnumeratorBase<'T> = + new : unit -> EmptyEnumerators<'T> + static member Element : IEnumerator<'T> + end + [] + type EnumeratorBase<'T> = class - interface IEnumerator<'T> - interface IEnumerator - interface IDisposable - new : result: Result<'T> * - seqComponent: ICompletionChain -> - EnumeratorBase<'T> - end - and [] EnumerableBase<'T> = + interface IEnumerator<'T> + interface IEnumerator + interface IDisposable + new : result: Result<'T> * + seqComponent: ICompletionChain -> + EnumeratorBase<'T> + end + and [] EnumerableBase<'T> = class - interface ISeq<'T> - interface IEnumerable<'T> - interface IEnumerable - new : unit -> EnumerableBase<'T> - abstract member + interface ISeq<'T> + interface IEnumerable<'T> + interface IEnumerable + new : unit -> EnumerableBase<'T> + abstract member Append : seq<'T> -> IEnumerable<'T> - override + override Append : source:seq<'T> -> IEnumerable<'T> - end - and Enumerator<'T,'U> = + end + and Enumerator<'T,'U> = class - inherit EnumeratorBase<'U> - interface IDisposable - interface IEnumerator - new : source:IEnumerator<'T> * - seqComponent: Consumer<'T,'U> * - result: Result<'U> -> - Enumerator<'T,'U> - end - and Enumerable<'T,'U> = + inherit EnumeratorBase<'U> + interface IDisposable + interface IEnumerator + new : source:IEnumerator<'T> * + seqComponent: Consumer<'T,'U> * + result: Result<'U> -> + Enumerator<'T,'U> + end + and Enumerable<'T,'U> = class - inherit EnumerableBase<'U> - interface ISeq<'U> - interface IEnumerable<'U> - new : enumerable:IEnumerable<'T> * - current: SeqFactory<'T,'U> -> - Enumerable<'T,'U> - end - and ConcatEnumerator<'T,'Collection when 'Collection :> seq<'T>> = + inherit EnumerableBase<'U> + interface ISeq<'U> + interface IEnumerable<'U> + new : enumerable:IEnumerable<'T> * + current: SeqFactory<'T,'U> -> + Enumerable<'T,'U> + end + and ConcatEnumerator<'T,'Collection when 'Collection :> seq<'T>> = class - interface IDisposable - interface IEnumerator - interface IEnumerator<'T> - new : sources:seq<'Collection> -> - ConcatEnumerator<'T,'Collection> - end - and AppendEnumerable<'T> = + interface IDisposable + interface IEnumerator + interface IEnumerator<'T> + new : sources:seq<'Collection> -> + ConcatEnumerator<'T,'Collection> + end + and AppendEnumerable<'T> = class - inherit EnumerableBase<'T> - interface ISeq<'T> - interface IEnumerable<'T> - new : sources:seq<'T> list -> AppendEnumerable<'T> - override + inherit EnumerableBase<'T> + interface ISeq<'T> + interface IEnumerable<'T> + new : sources:seq<'T> list -> AppendEnumerable<'T> + override Append : source:seq<'T> -> - IEnumerable<'T> - end - and ConcatEnumerable<'T,'Collection when 'Collection :> seq<'T>> = + IEnumerable<'T> + end + and ConcatEnumerable<'T,'Collection when 'Collection :> seq<'T>> = class - inherit EnumerableBase<'T> - interface ISeq<'T> - interface IEnumerable<'T> - new : sources:seq<'Collection> -> - ConcatEnumerable<'T,'Collection> - end - val create : - enumerable:IEnumerable<'a> -> - current: SeqFactory<'a,'b> -> ISeq<'b> + inherit EnumerableBase<'T> + interface ISeq<'T> + interface IEnumerable<'T> + new : sources:seq<'Collection> -> + ConcatEnumerable<'T,'Collection> end - module EmptyEnumerable = begin - type Enumerable<'T> = + val create : + enumerable:IEnumerable<'a> -> + current: SeqFactory<'a,'b> -> ISeq<'b> + end + module EmptyEnumerable = begin + type Enumerable<'T> = class - inherit Enumerable.EnumerableBase<'T> - interface ISeq<'T> - interface IEnumerable<'T> - new : unit -> Enumerable<'T> - override + inherit Enumerable.EnumerableBase<'T> + interface ISeq<'T> + interface IEnumerable<'T> + new : unit -> Enumerable<'T> + override Append : source:seq<'T> -> IEnumerable<'T> - static member Instance : ISeq<'T> - end + static member Instance : ISeq<'T> end - module Array = begin - type Enumerator<'T,'U> = + end + module Array = begin + type Enumerator<'T,'U> = class - inherit Enumerable.EnumeratorBase<'U> - interface IEnumerator - new : delayedArray:(unit -> 'T array) * - seqComponent: Consumer<'T,'U> * - result: Result<'U> -> Enumerator<'T,'U> - end - type Enumerable<'T,'U> = + inherit Enumerable.EnumeratorBase<'U> + interface IEnumerator + new : delayedArray:(unit -> 'T array) * + seqComponent: Consumer<'T,'U> * + result: Result<'U> -> Enumerator<'T,'U> + end + type Enumerable<'T,'U> = class - inherit Enumerable.EnumerableBase<'U> - interface ISeq<'U> - interface IEnumerable<'U> - new : delayedArray:(unit -> 'T array) * - current: SeqFactory<'T,'U> -> - Enumerable<'T,'U> - end - val createDelayed : + inherit Enumerable.EnumerableBase<'U> + interface ISeq<'U> + interface IEnumerable<'U> + new : delayedArray:(unit -> 'T array) * + current: SeqFactory<'T,'U> -> + Enumerable<'T,'U> + end + val createDelayed : delayedArray:(unit -> 'T array) -> - current: SeqFactory<'T,'U> -> ISeq<'U> - val create : + current: SeqFactory<'T,'U> -> ISeq<'U> + val create : array:'T array -> - current: SeqFactory<'T,'U> -> ISeq<'U> - val createDelayedId : + current: SeqFactory<'T,'U> -> ISeq<'U> + val createDelayedId : delayedArray:(unit -> 'T array) -> ISeq<'T> - val createId : array:'T array -> ISeq<'T> - end - module List = begin - type Enumerator<'T,'U> = + val createId : array:'T array -> ISeq<'T> + end + module List = begin + type Enumerator<'T,'U> = class - inherit Enumerable.EnumeratorBase<'U> - interface IEnumerator - new : alist:'T list * seqComponent: Consumer<'T,'U> * - result: Result<'U> -> Enumerator<'T,'U> - end - type Enumerable<'T,'U> = + inherit Enumerable.EnumeratorBase<'U> + interface IEnumerator + new : alist:'T list * seqComponent: Consumer<'T,'U> * + result: Result<'U> -> Enumerator<'T,'U> + end + type Enumerable<'T,'U> = class - inherit Enumerable.EnumerableBase<'U> - interface ISeq<'U> - interface IEnumerable<'U> - new : alist:'T list * current: SeqFactory<'T,'U> -> - Enumerable<'T,'U> - end - val create : - alist:'a list -> - current: SeqFactory<'a,'b> -> ISeq<'b> + inherit Enumerable.EnumerableBase<'U> + interface ISeq<'U> + interface IEnumerable<'U> + new : alist:'T list * current: SeqFactory<'T,'U> -> + Enumerable<'T,'U> end - module Unfold = begin - type Enumerator<'T,'U,'State> = + val create : + alist:'a list -> + current: SeqFactory<'a,'b> -> ISeq<'b> + end + module Unfold = begin + type Enumerator<'T,'U,'State> = class - inherit Enumerable.EnumeratorBase<'U> - interface IEnumerator - new : generator:('State -> ('T * 'State) option) * state:'State * - seqComponent: Consumer<'T,'U> * - result: Result<'U> -> - Enumerator<'T,'U,'State> - end - type Enumerable<'T,'U,'GeneratorState> = + inherit Enumerable.EnumeratorBase<'U> + interface IEnumerator + new : generator:('State -> ('T * 'State) option) * state:'State * + seqComponent: Consumer<'T,'U> * + result: Result<'U> -> + Enumerator<'T,'U,'State> + end + type Enumerable<'T,'U,'GeneratorState> = class - inherit Enumerable.EnumerableBase<'U> - interface ISeq<'U> - interface IEnumerable<'U> - new : generator:('GeneratorState -> ('T * 'GeneratorState) option) * - state:'GeneratorState * current: SeqFactory<'T,'U> -> - Enumerable<'T,'U,'GeneratorState> - end + inherit Enumerable.EnumerableBase<'U> + interface ISeq<'U> + interface IEnumerable<'U> + new : generator:('GeneratorState -> ('T * 'GeneratorState) option) * + state:'GeneratorState * current: SeqFactory<'T,'U> -> + Enumerable<'T,'U,'GeneratorState> end - module Init = begin - val getTerminatingIdx : count:Nullable -> int - type Enumerator<'T,'U> = + end + module Init = begin + val getTerminatingIdx : count:Nullable -> int + type Enumerator<'T,'U> = class - inherit Enumerable.EnumeratorBase<'U> - interface IEnumerator - new : count:Nullable * f:(int -> 'T) * - seqComponent: Consumer<'T,'U> * - result: Result<'U> -> Enumerator<'T,'U> - end - type Enumerable<'T,'U> = + inherit Enumerable.EnumeratorBase<'U> + interface IEnumerator + new : count:Nullable * f:(int -> 'T) * + seqComponent: Consumer<'T,'U> * + result: Result<'U> -> Enumerator<'T,'U> + end + type Enumerable<'T,'U> = class - inherit Enumerable.EnumerableBase<'U> - interface ISeq<'U> - interface IEnumerable<'U> - new : count:Nullable * f:(int -> 'T) * - current: SeqFactory<'T,'U> -> - Enumerable<'T,'U> - end - val upto : + inherit Enumerable.EnumerableBase<'U> + interface ISeq<'U> + interface IEnumerable<'U> + new : count:Nullable * f:(int -> 'T) * + current: SeqFactory<'T,'U> -> + Enumerable<'T,'U> + end + val upto : lastOption:int option -> - f:(int -> 'U) -> IEnumerator<'U> - type EnumerableDecider<'T> = + f:(int -> 'U) -> IEnumerator<'U> + type EnumerableDecider<'T> = class - inherit Enumerable.EnumerableBase<'T> - interface ISeq<'T> - interface IEnumerable<'T> - new : count:Nullable * f:(int -> 'T) -> - EnumerableDecider<'T> - end + inherit Enumerable.EnumerableBase<'T> + interface ISeq<'T> + interface IEnumerable<'T> + new : count:Nullable * f:(int -> 'T) -> + EnumerableDecider<'T> end + end - [] - val toComposer : source:seq<'T> -> ISeq<'T> + [] + val toComposer : source:seq<'T> -> ISeq<'T> - val inline foreach : f:((unit -> unit) -> 'a) -> source: ISeq<'b> -> 'a when 'a :> Consumer<'b,'b> + val inline foreach : f:((unit -> unit) -> 'a) -> source: ISeq<'b> -> 'a when 'a :> Consumer<'b,'b> - [] - 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 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 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 empty<'T> : ISeq<'T> - [] - val inline exactlyOne : source : ISeq<'T> -> 'T + [] + val inline exactlyOne : errorString:string -> source : ISeq<'T> -> 'T - [] - val inline fold<'T,'State> : f:('State->'T->'State) -> seed:'State -> source:ISeq<'T> -> 'State + [] + 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 inline fold2<'T1,'T2,'State> : folder:('State->'T1->'T2->'State) -> state:'State -> source1: ISeq<'T1> -> source2: ISeq<'T2> -> 'State - [] - val unfold : generator:('State -> ('T * 'State) option) -> state:'State -> ISeq<'T> + [] + val unfold : generator:('State -> ('T * 'State) option) -> state:'State -> ISeq<'T> - [] - val initInfinite : f:(int -> 'T) -> ISeq<'T> + [] + val initInfinite : f:(int -> 'T) -> ISeq<'T> - [] - val init : count:int -> f:(int -> 'T) -> ISeq<'T> + [] + val init : count:int -> f:(int -> 'T) -> ISeq<'T> - [] - val iter : f:('T -> unit) -> source: ISeq<'T> -> unit + [] + val iter : f:('T -> unit) -> source: ISeq<'T> -> unit - [] - val inline iter2 : f:('T->'U->unit) -> source1 : ISeq<'T> -> source2 : ISeq<'U> -> 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:seq<'U> -> unit + [] + val inline iteri2 : f:(int->'T->'U->unit) -> source1:ISeq<'T> -> source2:seq<'U> -> unit - [] - val tryHead : source: ISeq<'T> -> 'T option + [] + val tryHead : source: ISeq<'T> -> 'T option - [] - val iteri : f:(int -> 'T -> unit) -> source: ISeq<'T> -> unit + [] + val 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 except : itemsToExclude:seq<'T> -> source:ISeq<'T> -> ISeq<'T> when 'T:equality - [] - val exists : f:('T -> bool) -> source: ISeq<'T> -> bool + [] + val exists : f:('T -> bool) -> source: ISeq<'T> -> bool - [] - val exists2 : predicate:('T->'U->bool) -> source1:ISeq<'T> -> source2:ISeq<'U> -> bool + [] + val 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 contains : element:'T -> source: ISeq<'T> -> bool when 'T : equality - [] - val forall : f:('T -> bool) -> source: ISeq<'T> -> bool + [] + val forall : f:('T -> bool) -> source: ISeq<'T> -> bool - [] - val inline forall2 : predicate:('T->'U->bool) -> source1:ISeq<'T> -> source2:ISeq<'U> -> 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 filter : f:('T -> bool) -> source: ISeq<'T> -> ISeq<'T> - [] - val inline map : f:('T -> 'U) -> source: ISeq<'T> -> ISeq<'U> + [] + 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 mapi : f:(int->'a->'b) -> source: ISeq<'a> -> ISeq<'b> - [] - val inline map2<'First,'Second,'U> : map:('First->'Second->'U) -> source1:ISeq<'First> -> source2:ISeq<'Second> -> ISeq<'U> + [] + val inline map2<'First,'Second,'U> : map:('First->'Second->'U) -> source1:ISeq<'First> -> source2:ISeq<'Second> -> ISeq<'U> - [] - val inline mapi2<'First,'Second,'U> : map:(int -> 'First->'Second->'U) -> source1:ISeq<'First> -> source2:ISeq<'Second> -> ISeq<'U> + [] + val inline mapi2<'First,'Second,'U> : map:(int -> 'First->'Second->'U) -> source1:ISeq<'First> -> source2:ISeq<'Second> -> ISeq<'U> - [] - val inline map3<'First,'Second,'Third,'U> : map:('First->'Second->'Third->'U) -> source1:ISeq<'First> -> source2:ISeq<'Second> -> source3:ISeq<'Third> -> ISeq<'U> + [] + val inline map3<'First,'Second,'Third,'U> : map:('First->'Second->'Third->'U) -> source1:ISeq<'First> -> source2:ISeq<'Second> -> source3:ISeq<'Third> -> ISeq<'U> - [] - val inline compareWith : f:('T -> 'T -> int) -> source1 :ISeq<'T> -> source2:ISeq<'T> -> int + [] + 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 choose : f:('a->option<'b>) -> source: ISeq<'a> -> ISeq<'b> - [] - val inline distinct : source: ISeq<'T> -> ISeq<'T> when 'T:equality + [] + 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 distinctBy : keyf:('T->'Key) -> source: ISeq<'T> -> ISeq<'T> when 'Key:equality - [] - val inline max : source: ISeq<'T> -> 'T when 'T:comparison + [] + 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 maxBy : f:('T -> 'U) -> source: ISeq<'T> -> 'T when 'U:comparison - [] - val inline min : source: ISeq<'T> -> 'T when 'T: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 inline minBy : f:('T -> 'U) -> source: ISeq<'T> -> 'T when 'U:comparison - [] - val inline pairwise : source:ISeq<'T> -> ISeq<'T * 'T> + [] + val inline pairwise : source:ISeq<'T> -> ISeq<'T * 'T> - [] - val inline reduce : f:('T->'T->'T) -> source: 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 inline scan : folder:('State->'T->'State) -> initialState:'State -> source:ISeq<'T> -> ISeq<'State> - [] - val inline skip : skipCount:int -> source:ISeq<'T> -> ISeq<'T> + [] + val inline skip : errorString:string -> skipCount:int -> source:ISeq<'T> -> ISeq<'T> - [] - val inline skipWhile : predicate:('T->bool) -> 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 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 inline sumBy : f :('T -> ^U) -> source: ISeq<'T> -> ^U + when ^U:(static member Zero : ^U) + and ^U:(static member (+) : ^U * ^U -> ^U) - [] - val inline take : takeCount:int -> source:ISeq<'T> -> ISeq<'T> + [] + val inline take : errorString:string -> takeCount:int -> source:ISeq<'T> -> ISeq<'T> - [] - val inline takeWhile : predicate:('T->bool) -> source:ISeq<'T> -> ISeq<'T> + [] + val inline takeWhile : predicate:('T->bool) -> source:ISeq<'T> -> ISeq<'T> - [] - val inline tail : source:ISeq<'T> -> ISeq<'T> + [] + val inline tail : errorString:string -> source:ISeq<'T> -> ISeq<'T> - [] - val inline truncate : truncateCount:int -> source:ISeq<'T> -> ISeq<'T> + [] + val inline truncate : truncateCount:int -> source:ISeq<'T> -> ISeq<'T> - [] - val inline indexed : source: ISeq<'a> -> ISeq + [] + val inline indexed : source: ISeq<'a> -> ISeq - [] - val tryItem : index:int -> source: ISeq<'T> -> 'T option + [] + val tryItem : errorString:string -> index:int -> source: ISeq<'T> -> 'T option - [] - val tryPick : f:('T -> 'U option) -> source: ISeq<'T> -> Option<'U> + [] + val tryPick : f:('T -> 'U option) -> source: ISeq<'T> -> Option<'U> - [] - val tryFind : f:('T -> bool) -> source: ISeq<'T> -> Option<'T> + [] + val tryFind : f:('T -> bool) -> source: ISeq<'T> -> Option<'T> - [] - val inline tryFindIndex: preidcate:('T->bool) -> source:ISeq<'T> -> int option + [] + val inline tryFindIndex: preidcate:('T->bool) -> source:ISeq<'T> -> int option - [] - val inline tryLast : source:ISeq<'T> -> 'T option + [] + val inline tryLast : source:ISeq<'T> -> 'T option - [] - val inline windowed : windowSize:int -> source:ISeq<'T> -> ISeq<'T[]> + [] + val inline windowed : windowSize:int -> source:ISeq<'T> -> ISeq<'T[]> From 220addff66fe511283fa29c1a8eb1ecd4ce2e0c8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 15 Dec 2016 19:17:42 +1100 Subject: [PATCH 252/286] Removed ICompletionChain Just made it into a abstract class at the top of the hierarchy --- src/fsharp/FSharp.Core/seqcomposer.fs | 102 ++++++++++++------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 20 +++-- 2 files changed, 59 insertions(+), 63 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index bbc6ab3cdf9..8b82e661fb1 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -43,17 +43,19 @@ namespace Microsoft.FSharp.Collections type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit - type ICompletionChain = + [] + type Consumer() = abstract ChainComplete : stopTailCall:byref * PipeIdx -> unit abstract ChainDispose : stopTailCall:byref -> unit [] type Consumer<'T,'U> () = + inherit Consumer() + abstract ProcessNext : input:'T -> bool - interface ICompletionChain with - member this.ChainComplete (_,_) = () - member this.ChainDispose _ = () + override this.ChainComplete (_,_) = () + override this.ChainDispose _ = () [] type ConsumerWithState<'T,'U,'Value> = @@ -69,21 +71,20 @@ namespace Microsoft.FSharp.Collections type ConsumerChainedWithState<'T,'U,'Value> = inherit ConsumerWithState<'T,'U,'Value> - val private Next : ICompletionChain + val private Next : Consumer - new (next:ICompletionChain, init) = { + new (next:Consumer, init) = { inherit ConsumerWithState<'T,'U,'Value> (init) Next = next } - interface ICompletionChain with - member this.ChainComplete (stopTailCall, terminatingIdx) = - this.Next.ChainComplete (&stopTailCall, terminatingIdx) - member this.ChainDispose stopTailCall = - this.Next.ChainDispose (&stopTailCall) + override this.ChainComplete (stopTailCall, terminatingIdx) = + this.Next.ChainComplete (&stopTailCall, terminatingIdx) + override this.ChainDispose stopTailCall = + this.Next.ChainDispose (&stopTailCall) [] - type ConsumerChained<'T,'U>(next:ICompletionChain) = + type ConsumerChained<'T,'U>(next:Consumer) = inherit ConsumerChainedWithState<'T,'U,NoValue>(next, Unchecked.defaultof) [] @@ -93,16 +94,15 @@ namespace Microsoft.FSharp.Collections abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit - interface ICompletionChain with - member this.ChainComplete (stopTailCall, terminatingIdx) = - this.OnComplete terminatingIdx - next.ChainComplete (&stopTailCall, terminatingIdx) - member this.ChainDispose stopTailCall = - try this.OnDispose () - finally next.ChainDispose (&stopTailCall) + override this.ChainComplete (stopTailCall, terminatingIdx) = + this.OnComplete terminatingIdx + next.ChainComplete (&stopTailCall, terminatingIdx) + override this.ChainDispose stopTailCall = + try this.OnDispose () + finally next.ChainDispose (&stopTailCall) [] - type ConsumerChainedWithCleanup<'T,'U>(next:ICompletionChain) = + type ConsumerChainedWithCleanup<'T,'U>(next:Consumer) = inherit ConsumerChainedWithStateAndCleanup<'T,'U,NoValue>(next, Unchecked.defaultof) [] @@ -115,10 +115,9 @@ namespace Microsoft.FSharp.Collections abstract OnComplete : PipeIdx -> unit - interface ICompletionChain with - member this.ChainComplete (stopTailCall, terminatingIdx) = - this.OnComplete terminatingIdx - member this.ChainDispose _ = () + override this.ChainComplete (stopTailCall, terminatingIdx) = + this.OnComplete terminatingIdx + override this.ChainDispose _ = () [] type SeqFactory<'T,'U> () = @@ -149,7 +148,6 @@ namespace Microsoft.FSharp.Collections let inline enumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) let inline enumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline enumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline iCompletionChain (t:#ICompletionChain) : ICompletionChain = (# "" t : ICompletionChain #) type ComposedFactory<'T,'U,'V> private (first:SeqFactory<'T,'U>, second:SeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = @@ -259,11 +257,11 @@ namespace Microsoft.FSharp.Collections try executeOn pipeline consumer let mutable stopTailCall = () - (Upcast.iCompletionChain consumer).ChainComplete (&stopTailCall, pipeline.HaltedIdx) + consumer.ChainComplete (&stopTailCall, pipeline.HaltedIdx) result finally let mutable stopTailCall = () - (Upcast.iCompletionChain consumer).ChainDispose (&stopTailCall) + consumer.ChainDispose (&stopTailCall) module Enumerable = type Empty<'T>() = @@ -282,7 +280,7 @@ namespace Microsoft.FSharp.Collections static member Element = element [] - type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ICompletionChain) = + type EnumeratorBase<'T>(result:Result<'T>, seqComponent:Consumer) = interface IDisposable with member __.Dispose() : unit = let mutable stopTailCall = () @@ -335,7 +333,7 @@ namespace Microsoft.FSharp.Collections else result.SeqState <- SeqProcessNextStates.Finished let mutable stopTailCall = () - (Upcast.iCompletionChain seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) + (seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -349,7 +347,7 @@ namespace Microsoft.FSharp.Collections source.Dispose () finally let mutable stopTailCall = () - (Upcast.iCompletionChain seqComponent).ChainDispose (&stopTailCall) + (seqComponent).ChainDispose (&stopTailCall) and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqFactory<'T,'U>) = inherit EnumerableBase<'U>() @@ -485,7 +483,7 @@ namespace Microsoft.FSharp.Collections else result.SeqState <- SeqProcessNextStates.Finished let mutable stopTailCall = () - (Upcast.iCompletionChain seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) + (seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -537,7 +535,7 @@ namespace Microsoft.FSharp.Collections | _ -> result.SeqState <- SeqProcessNextStates.Finished let mutable stopTailCall = () - (Upcast.iCompletionChain seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) + (seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -651,7 +649,7 @@ namespace Microsoft.FSharp.Collections else result.SeqState <- SeqProcessNextStates.Finished let mutable stopTailCall = () - (Upcast.iCompletionChain seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) + (seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -945,7 +943,7 @@ namespace Microsoft.FSharp.Collections source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,Lazy>> - (Upcast.iCompletionChain next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with + (next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = if this.Value.Value.Add input then TailCall.avoid (next.ProcessNext input) else false @@ -1036,7 +1034,7 @@ namespace Microsoft.FSharp.Collections let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = - upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with + upcast { new ConsumerChained<'T,'V>(next) with member __.ProcessNext input = if f input then TailCall.avoid (next.ProcessNext input) else false } } @@ -1046,7 +1044,7 @@ namespace Microsoft.FSharp.Collections let inline map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = source |> compose { new SeqFactory<'T,'U>() with member __.Create _ _ next = - upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with + upcast { new ConsumerChained<'T,'V>(next) with member __.ProcessNext input = TailCall.avoid (next.ProcessNext (f input)) } } @@ -1055,7 +1053,7 @@ namespace Microsoft.FSharp.Collections let inline mapi f source = source |> compose { new SeqFactory<'T,'U>() with member __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,int>(Upcast.iCompletionChain next, -1) with + upcast { new ConsumerChainedWithState<'T,'V,int>(next, -1) with override this.ProcessNext (input:'T) : bool = this.Value <- this.Value + 1 TailCall.avoid (next.ProcessNext (f this.Value input)) } } @@ -1065,7 +1063,7 @@ namespace Microsoft.FSharp.Collections let inline map2<'First,'Second,'U> (map:'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = source1 |> compose { new SeqFactory<'First,'U>() with member __.Create<'V> outOfBand pipeIdx next = - upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, IEnumerator<'Second>>(Upcast.iCompletionChain next, (source2.GetEnumerator ())) with + upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, IEnumerator<'Second>>(next, (source2.GetEnumerator ())) with member self.ProcessNext input = if self.Value.MoveNext () then TailCall.avoid (next.ProcessNext (map input self.Value.Current)) @@ -1083,7 +1081,7 @@ namespace Microsoft.FSharp.Collections source1 |> compose { new SeqFactory<'First,'U>() with member __.Create<'V> outOfBand pipeIdx next = upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values>> - (Upcast.iCompletionChain next, Values<_,_>(-1, source2.GetEnumerator ())) with + (next, Values<_,_>(-1, source2.GetEnumerator ())) with member self.ProcessNext input = if self.Value._2.MoveNext () then self.Value._1 <- self.Value._1 + 1 @@ -1103,7 +1101,7 @@ namespace Microsoft.FSharp.Collections source1 |> compose { new SeqFactory<'First,'U>() with member __.Create<'V> outOfBand pipeIdx next = upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values,IEnumerator<'Third>>> - (Upcast.iCompletionChain next, Values<_,_>(source2.GetEnumerator(),source3.GetEnumerator())) with + (next, Values<_,_>(source2.GetEnumerator(),source3.GetEnumerator())) with member self.ProcessNext input = if self.Value._1.MoveNext() && self.Value._2.MoveNext () then TailCall.avoid (next.ProcessNext (map input self.Value._1 .Current self.Value._2.Current)) @@ -1144,7 +1142,7 @@ namespace Microsoft.FSharp.Collections let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = source |> compose { new SeqFactory<'T,'U>() with member __.Create _ _ next = - upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with + upcast { new ConsumerChained<'T,'V>(next) with member __.ProcessNext input = match f input with | Some value -> TailCall.avoid (next.ProcessNext value) @@ -1156,7 +1154,7 @@ namespace Microsoft.FSharp.Collections source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,HashSet<'T>> - (Upcast.iCompletionChain next,(HashSet<'T>(HashIdentity.Structural<'T>))) with + (next,(HashSet<'T>(HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = if this.Value.Add input then TailCall.avoid (next.ProcessNext input) else false } } @@ -1167,7 +1165,7 @@ namespace Microsoft.FSharp.Collections source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,HashSet<'Key>> - (Upcast.iCompletionChain next,(HashSet<'Key>(HashIdentity.Structural<'Key>))) with + (next,(HashSet<'Key>(HashIdentity.Structural<'Key>))) with override this.ProcessNext (input:'T) : bool = if this.Value.Add (keyf input) then TailCall.avoid (next.ProcessNext input) else false } } @@ -1266,7 +1264,7 @@ namespace Microsoft.FSharp.Collections source |> compose { new SeqFactory<'T,'T * 'T>() with member __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'U,Values> - ( Upcast.iCompletionChain next + ( next , Values ((* isFirst = _1*) true ,(* lastValue = _2*) Unchecked.defaultof<'T> @@ -1308,7 +1306,7 @@ namespace Microsoft.FSharp.Collections let inline scan (folder:'State->'T->'State) (initialState: 'State) (source:ISeq<'T>) :ISeq<'State> = source |> compose { new SeqFactory<'T,'State>() with member __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,'State>(Upcast.iCompletionChain next, initialState) with + upcast { new ConsumerChainedWithState<'T,'V,'State>(next, initialState) with override this.ProcessNext (input:'T) : bool = this.Value <- folder this.Value input TailCall.avoid (next.ProcessNext this.Value) } } @@ -1319,7 +1317,7 @@ namespace Microsoft.FSharp.Collections source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = upcast { - new ConsumerChainedWithStateAndCleanup<'T,'U,int>(Upcast.iCompletionChain next,(*count*)0) with + new ConsumerChainedWithStateAndCleanup<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = if (*count*) self.Value < skipCount then @@ -1350,7 +1348,7 @@ namespace Microsoft.FSharp.Collections let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,bool>(Upcast.iCompletionChain next,true) with + upcast { new ConsumerChainedWithState<'T,'V,bool>(next,true) with override self.ProcessNext (input:'T) : bool = if self.Value (*skip*) then self.Value <- predicate input @@ -1393,7 +1391,7 @@ namespace Microsoft.FSharp.Collections source |> compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipelineIdx next = upcast { - new ConsumerChainedWithStateAndCleanup<'T,'U,int>(Upcast.iCompletionChain next,(*count*)0) with + new ConsumerChainedWithStateAndCleanup<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = if (*count*) self.Value < takeCount then self.Value <- self.Value + 1 @@ -1417,7 +1415,7 @@ namespace Microsoft.FSharp.Collections let inline takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipeIdx next = - upcast { new ConsumerChained<'T,'V>(Upcast.iCompletionChain next) with + upcast { new ConsumerChained<'T,'V>(next) with override __.ProcessNext (input:'T) : bool = if predicate input then TailCall.avoid (next.ProcessNext input) @@ -1431,7 +1429,7 @@ namespace Microsoft.FSharp.Collections let inline tail errorString (source:ISeq<'T>) :ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = - upcast { new ConsumerChainedWithStateAndCleanup<'T,'V,bool>(Upcast.iCompletionChain next,(*first*) true) with + upcast { new ConsumerChainedWithStateAndCleanup<'T,'V,bool>(next,(*first*) true) with override self.ProcessNext (input:'T) : bool = if (*first*) self.Value then self.Value <- false @@ -1451,7 +1449,7 @@ namespace Microsoft.FSharp.Collections source |> compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipeIdx next = upcast { - new ConsumerChainedWithState<'T,'U,int>(Upcast.iCompletionChain next,(*count*)0) with + new ConsumerChainedWithState<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = if (*count*) self.Value < truncateCount then self.Value <- self.Value + 1 @@ -1540,7 +1538,7 @@ namespace Microsoft.FSharp.Collections member __.Create outOfBand pipeIdx next = upcast { new ConsumerChainedWithState<'T,'U,Values<'T[],int,int>> - ( Upcast.iCompletionChain next + ( next , Values<'T[],int,int> ((*circularBuffer = _1 *) Array.zeroCreateUnchecked windowSize ,(* idx = _2 *) 0 diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index c4f352f0988..9fea9832e7c 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -42,7 +42,8 @@ namespace Microsoft.FSharp.Collections /// base implementation is provided in Consumer, and should not be overwritten. Consumer /// provides it's own OnComplete and OnDispose function which should be used to handle /// a particular consumers cleanup. - type ICompletionChain = + [] + type Consumer = /// 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 @@ -56,7 +57,7 @@ namespace Microsoft.FSharp.Collections /// Consumer is the base class of all elements within the pipeline [] type Consumer<'T,'U> = - interface ICompletionChain + inherit Consumer new : unit -> Consumer<'T,'U> abstract member ProcessNext : input:'T -> bool @@ -69,29 +70,27 @@ namespace Microsoft.FSharp.Collections [] type ConsumerChainedWithState<'T,'U,'Value> = inherit ConsumerWithState<'T,'U,'Value> - interface ICompletionChain - val private Next : ICompletionChain - new : next:ICompletionChain * init:'Value -> ConsumerChainedWithState<'T,'U,'Value> + val private Next : Consumer + new : next:Consumer * init:'Value -> ConsumerChainedWithState<'T,'U,'Value> [] type ConsumerChained<'T,'U> = inherit ConsumerChainedWithState<'T,'U,NoValue> - new : next:ICompletionChain -> ConsumerChained<'T,'U> + new : next:Consumer -> ConsumerChained<'T,'U> [] type ConsumerChainedWithStateAndCleanup<'T,'U,'Value> = inherit ConsumerChainedWithState<'T,'U,'Value> - interface ICompletionChain abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit - new : next:ICompletionChain * init:'Value -> ConsumerChainedWithStateAndCleanup<'T,'U,'Value> + new : next:Consumer * init:'Value -> ConsumerChainedWithStateAndCleanup<'T,'U,'Value> [] type ConsumerChainedWithCleanup<'T,'U> = inherit ConsumerChainedWithStateAndCleanup<'T,'U,NoValue> - new : next:ICompletionChain -> ConsumerChainedWithCleanup<'T,'U> + new : next:Consumer -> ConsumerChainedWithCleanup<'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 @@ -104,7 +103,6 @@ namespace Microsoft.FSharp.Collections [] type FolderWithOnComplete<'T, 'Value> = inherit Folder<'T,'Value> - interface ICompletionChain abstract OnComplete : PipeIdx -> unit @@ -225,7 +223,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerator interface IDisposable new : result: Result<'T> * - seqComponent: ICompletionChain -> + seqComponent: Consumer -> EnumeratorBase<'T> end and [] EnumerableBase<'T> = From d06e56e9708ea38680027ccb0ec5e051f6b42d42 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 15 Dec 2016 19:26:22 +1100 Subject: [PATCH 253/286] Removed unnecessary SetResult type Wrapped it's functionality into Result type --- src/fsharp/FSharp.Core/seqcomposer.fs | 21 ++++++++++----------- src/fsharp/FSharp.Core/seqcomposer.fsi | 7 +------ 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 8b82e661fb1..89572dfca99 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -179,21 +179,20 @@ namespace Microsoft.FSharp.Collections | Finished = 2 type Result<'T>() = + inherit Consumer<'T,'T>() + + let mutable current = Unchecked.defaultof<'T> let mutable haltedIdx = 0 - member val Current = Unchecked.defaultof<'T> with get, set + member __.Current = current member val SeqState = SeqProcessNextStates.NotStarted with get, set member __.HaltedIdx = haltedIdx interface IOutOfBand with member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx - // SetResult<> is used at the end of the chain of SeqComponents to assign the final value - type SetResult<'T> (result:Result<'T>) = - inherit Consumer<'T,'T>() - override __.ProcessNext (input:'T) : bool = - result.Current <- input + current <- input true type OutOfBand() = @@ -355,7 +354,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Build result (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Build result result, result)) interface ISeq<'U> with member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -497,7 +496,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Build result (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Build result result, result)) interface ISeq<'U> with member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -549,7 +548,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Build result (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Build result result, result)) interface ISeq<'U> with member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -588,7 +587,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Build result (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Build result result, result)) interface ISeq<'U> with member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -663,7 +662,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(count, f, current.Build result (SetResult<'U> result), result)) + Upcast.enumerator (new Enumerator<'T,'U>(count, f, current.Build result result, result)) interface ISeq<'U> with member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 9fea9832e7c..136a8e496d7 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -152,18 +152,13 @@ namespace Microsoft.FSharp.Collections | Finished = 2 type Result<'T> = class + inherit Consumer<'T,'T> interface IOutOfBand new : unit -> Result<'T> member Current : 'T member HaltedIdx : int member SeqState : SeqProcessNextStates - member Current : 'T with set member SeqState : SeqProcessNextStates with set - end - type SetResult<'T> = - class - inherit Consumer<'T,'T> - new : result: Result<'T> -> SetResult<'T> override ProcessNext : input:'T -> bool end type OutOfBand = From 8baee067f173e61ead3a98446f47bcbbb59de96a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 15 Dec 2016 19:56:06 +1100 Subject: [PATCH 254/286] Fix iteri2 from seq to ISeq --- src/fsharp/FSharp.Core/seqcomposer.fs | 2 +- src/fsharp/FSharp.Core/seqcomposer.fsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 89572dfca99..99ba97cf976 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -894,7 +894,7 @@ namespace Microsoft.FSharp.Collections [] - let inline iteri2 (f:int->'T->'U->unit) (source1:ISeq<'T>) (source2:seq<'U>) : unit = + let inline iteri2 (f:int->'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = source1 |> foreach (fun halt -> { new FolderWithOnComplete<'T,Values>>(Values<_,_>(-1,source2.GetEnumerator())) with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 136a8e496d7..36cfd73ab8d 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -438,7 +438,7 @@ namespace Microsoft.FSharp.Collections 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:seq<'U> -> unit + val inline iteri2 : f:(int->'T->'U->unit) -> source1:ISeq<'T> -> source2:ISeq<'U> -> unit [] val tryHead : source: ISeq<'T> -> 'T option From 2d74aa330b5376f80b0958a564d194c6eb2917a2 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 18 Dec 2016 08:10:18 +1100 Subject: [PATCH 255/286] Renaming Value to State --- src/fsharp/FSharp.Core/seqcomposer.fs | 352 ++++++++++++------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 30 +-- 2 files changed, 191 insertions(+), 191 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 99ba97cf976..67052fa0e41 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -58,23 +58,23 @@ namespace Microsoft.FSharp.Collections override this.ChainDispose _ = () [] - type ConsumerWithState<'T,'U,'Value> = + type ConsumerWithState<'T,'U,'State> = inherit Consumer<'T,'U> - val mutable Value : 'Value + val mutable State : 'State - new (init) = { - Value = init + new (initialState) = { + State = initialState } [] - type ConsumerChainedWithState<'T,'U,'Value> = - inherit ConsumerWithState<'T,'U,'Value> + type ConsumerChainedWithState<'T,'U,'State> = + inherit ConsumerWithState<'T,'U,'State> val private Next : Consumer - new (next:Consumer, init) = { - inherit ConsumerWithState<'T,'U,'Value> (init) + new (next:Consumer, initialState) = { + inherit ConsumerWithState<'T,'U,'State> (initialState) Next = next } @@ -88,8 +88,8 @@ namespace Microsoft.FSharp.Collections inherit ConsumerChainedWithState<'T,'U,NoValue>(next, Unchecked.defaultof) [] - type ConsumerChainedWithStateAndCleanup<'T,'U,'Value> (next, init) = - inherit ConsumerChainedWithState<'T,'U,'Value>(next, init) + type ConsumerChainedWithStateAndCleanup<'T,'U,'State> (next, inititalState) = + inherit ConsumerChainedWithState<'T,'U,'State>(next, inititalState) abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit @@ -106,12 +106,12 @@ namespace Microsoft.FSharp.Collections inherit ConsumerChainedWithStateAndCleanup<'T,'U,NoValue>(next, Unchecked.defaultof) [] - type Folder<'T,'U>(init) = - inherit ConsumerWithState<'T,'T,'U>(init) + type Folder<'T,'U>(initialState) = + inherit ConsumerWithState<'T,'T,'U>(initialState) [] - type FolderWithOnComplete<'T, 'U>(init) = - inherit Folder<'T,'U>(init) + type FolderWithOnComplete<'T, 'U>(initialState) = + inherit Folder<'T,'U>(initialState) abstract OnComplete : PipeIdx -> unit @@ -762,14 +762,14 @@ namespace Microsoft.FSharp.Collections |> foreach (fun _ -> { new FolderWithOnComplete< ^T, Values< ^T, int>> (Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = - this.Value._1 <- Checked.(+) this.Value._1 value - this.Value._2 <- this.Value._2 + 1 + this.State._1 <- Checked.(+) this.State._1 value + this.State._2 <- this.State._2 + 1 Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = - if this.Value._2 = 0 then + if this.State._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - |> fun total -> LanguagePrimitives.DivideByInt< ^T> total.Value._1 total.Value._2 + |> fun total -> LanguagePrimitives.DivideByInt< ^T> total.State._1 total.State._2 [] @@ -781,14 +781,14 @@ namespace Microsoft.FSharp.Collections |> foreach (fun _ -> { new FolderWithOnComplete<'T,Values<'U, int>>(Values<_,_>(LanguagePrimitives.GenericZero, 0)) with override this.ProcessNext value = - this.Value._1 <- Checked.(+) this.Value._1 (f value) - this.Value._2 <- this.Value._2 + 1 + this.State._1 <- Checked.(+) this.State._1 (f value) + this.State._2 <- this.State._2 + 1 Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = - if this.Value._2 = 0 then + if this.State._2 = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.Value._1 total.Value._2 + |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.State._1 total.State._2 [] @@ -801,20 +801,20 @@ namespace Microsoft.FSharp.Collections |> foreach (fun halt -> { new FolderWithOnComplete<'T, Values>(Values(true, Unchecked.defaultof<'T>, false)) with override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value + if this.State._1 then + this.State._1 <- false + this.State._2 <- value else - this.Value._3 <- true + this.State._3 <- true halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = - if this.Value._1 then + if this.State._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - elif this.Value._3 then + elif this.State._3 then invalidArg "source" errorString }) - |> fun one -> one.Value._2 + |> fun one -> one.State._2 [] @@ -823,10 +823,10 @@ namespace Microsoft.FSharp.Collections |> foreach (fun _ -> { new Folder<'T,'State>(seed) with override this.ProcessNext value = - this.Value <- f this.Value value + this.State <- f this.State value Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun folded -> folded.Value + |> fun folded -> folded.State [] @@ -835,16 +835,16 @@ namespace Microsoft.FSharp.Collections |> foreach (fun halt -> { new FolderWithOnComplete<_,Values<'State,IEnumerator<'T2>>>(Values<_,_>(state,source2.GetEnumerator())) with override self.ProcessNext value = - if self.Value._2.MoveNext() then - self.Value._1 <- folder self.Value._1 value self.Value._2.Current + if self.State._2.MoveNext() then + self.State._1 <- folder self.State._1 value self.State._2.Current else halt() Unchecked.defaultof<_> (* return value unsed in ForEach context *) override self.OnComplete _ = - self.Value._2.Dispose() + self.State._2.Dispose() }) - |> fun fold -> fold.Value._1 + |> fun fold -> fold.State._1 [] @@ -881,14 +881,14 @@ namespace Microsoft.FSharp.Collections |> foreach (fun halt -> { new FolderWithOnComplete<'T,IEnumerator<'U>> (source2.GetEnumerator()) with override self.ProcessNext value = - if self.Value.MoveNext() then - f value self.Value.Current + if self.State.MoveNext() then + f value self.State.Current else halt() Unchecked.defaultof<_> (* return value unsed in ForEach context *) override self.OnComplete _ = - self.Value.Dispose() + self.State.Dispose() }) |> ignore @@ -899,16 +899,16 @@ namespace Microsoft.FSharp.Collections |> foreach (fun halt -> { new FolderWithOnComplete<'T,Values>>(Values<_,_>(-1,source2.GetEnumerator())) with override self.ProcessNext value = - if self.Value._2.MoveNext() then - f self.Value._1 value self.Value._2.Current - self.Value._1 <- self.Value._1 + 1 + if self.State._2.MoveNext() then + f self.State._1 value self.State._2.Current + self.State._1 <- self.State._1 + 1 Unchecked.defaultof<_> else halt() Unchecked.defaultof<_> override self.OnComplete _ = - self.Value._2.Dispose() + self.State._2.Dispose() Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore @@ -920,10 +920,10 @@ namespace Microsoft.FSharp.Collections |> foreach (fun halt -> { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = - this.Value <- Some value + this.State <- Some value halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun head -> head.Value + |> fun head -> head.State [] @@ -932,8 +932,8 @@ namespace Microsoft.FSharp.Collections |> foreach (fun _ -> { new Folder<'T, int> (0) with override this.ProcessNext value = - f this.Value value - this.Value <- this.Value + 1 + f this.State value + this.State <- this.State + 1 Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore @@ -944,7 +944,7 @@ namespace Microsoft.FSharp.Collections upcast { new ConsumerChainedWithState<'T,'V,Lazy>> (next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = - if this.Value.Value.Add input then TailCall.avoid (next.ProcessNext input) + if this.State.Value.Add input then TailCall.avoid (next.ProcessNext input) else false }} @@ -956,10 +956,10 @@ namespace Microsoft.FSharp.Collections { new Folder<'T, bool> (false) with override this.ProcessNext value = if f value then - this.Value <- true + this.State <- true halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun exists -> exists.Value + |> fun exists -> exists.State [] @@ -968,19 +968,19 @@ namespace Microsoft.FSharp.Collections |> foreach (fun halt -> { new FolderWithOnComplete<'T,Values>>(Values<_,_>(false,source2.GetEnumerator())) with override self.ProcessNext value = - if self.Value._2.MoveNext() then - if predicate value self.Value._2.Current then - self.Value._1 <- true + if self.State._2.MoveNext() then + if predicate value self.State._2.Current then + self.State._1 <- true halt() else halt() Unchecked.defaultof<_> (* return value unsed in ForEach context *) override self.OnComplete _ = - self.Value._2.Dispose() + self.State._2.Dispose() }) - |> fun exists -> exists.Value._1 + |> fun exists -> exists.State._1 [] @@ -990,10 +990,10 @@ namespace Microsoft.FSharp.Collections { new Folder<'T, bool> (false) with override this.ProcessNext value = if element = value then - this.Value <- true + this.State <- true halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun contains -> contains.Value + |> fun contains -> contains.State [] @@ -1003,10 +1003,10 @@ namespace Microsoft.FSharp.Collections { new Folder<'T, bool> (true) with override this.ProcessNext value = if not (predicate value) then - this.Value <- false + this.State <- false halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun forall -> forall.Value + |> fun forall -> forall.State [] @@ -1015,18 +1015,18 @@ namespace Microsoft.FSharp.Collections |> foreach (fun halt -> { new FolderWithOnComplete<'T,Values>>(Values<_,_>(true,source2.GetEnumerator())) with override self.ProcessNext value = - if self.Value._2.MoveNext() then - if not (predicate value self.Value._2.Current) then - self.Value._1 <- false + if self.State._2.MoveNext() then + if not (predicate value self.State._2.Current) then + self.State._1 <- false halt() else halt() Unchecked.defaultof<_> (* return value unsed in ForEach context *) override self.OnComplete _ = - self.Value._2.Dispose() + self.State._2.Dispose() }) - |> fun all -> all.Value._1 + |> fun all -> all.State._1 [] @@ -1054,8 +1054,8 @@ namespace Microsoft.FSharp.Collections member __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,int>(next, -1) with override this.ProcessNext (input:'T) : bool = - this.Value <- this.Value + 1 - TailCall.avoid (next.ProcessNext (f this.Value input)) } } + this.State <- this.State + 1 + TailCall.avoid (next.ProcessNext (f this.State input)) } } [] @@ -1064,15 +1064,15 @@ namespace Microsoft.FSharp.Collections member __.Create<'V> outOfBand pipeIdx next = upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, IEnumerator<'Second>>(next, (source2.GetEnumerator ())) with member self.ProcessNext input = - if self.Value.MoveNext () then - TailCall.avoid (next.ProcessNext (map input self.Value.Current)) + if self.State.MoveNext () then + TailCall.avoid (next.ProcessNext (map input self.State.Current)) else outOfBand.StopFurtherProcessing pipeIdx false override self.OnDispose () = () override self.OnComplete _ = - self.Value.Dispose () } } + self.State.Dispose () } } [] @@ -1082,16 +1082,16 @@ namespace Microsoft.FSharp.Collections upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values>> (next, Values<_,_>(-1, source2.GetEnumerator ())) with member self.ProcessNext input = - if self.Value._2.MoveNext () then - self.Value._1 <- self.Value._1 + 1 - TailCall.avoid (next.ProcessNext (map self.Value._1 input self.Value._2.Current)) + if self.State._2.MoveNext () then + self.State._1 <- self.State._1 + 1 + TailCall.avoid (next.ProcessNext (map self.State._1 input self.State._2.Current)) else outOfBand.StopFurtherProcessing pipeIdx false override self.OnDispose () = () override self.OnComplete _ = - self.Value._2.Dispose () } } + self.State._2.Dispose () } } [] @@ -1102,16 +1102,16 @@ namespace Microsoft.FSharp.Collections upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values,IEnumerator<'Third>>> (next, Values<_,_>(source2.GetEnumerator(),source3.GetEnumerator())) with member self.ProcessNext input = - if self.Value._1.MoveNext() && self.Value._2.MoveNext () then - TailCall.avoid (next.ProcessNext (map input self.Value._1 .Current self.Value._2.Current)) + if self.State._1.MoveNext() && self.State._2.MoveNext () then + TailCall.avoid (next.ProcessNext (map input self.State._1 .Current self.State._2.Current)) else outOfBand.StopFurtherProcessing pipeIdx false override self.OnDispose () = () override self.OnComplete _ = - self.Value._1.Dispose () - self.Value._2.Dispose () } } + self.State._1.Dispose () + self.State._2.Dispose () } } [] @@ -1120,22 +1120,22 @@ namespace Microsoft.FSharp.Collections |> foreach (fun halt -> { new FolderWithOnComplete<'T,Values>>(Values<_,_>(0,source2.GetEnumerator())) with override self.ProcessNext value = - if not (self.Value._2.MoveNext()) then - self.Value._1 <- 1 + if not (self.State._2.MoveNext()) then + self.State._1 <- 1 halt () else - let c = f value self.Value._2.Current + let c = f value self.State._2.Current if c <> 0 then - self.Value._1 <- c + self.State._1 <- c halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) override self.OnComplete _ = - if self.Value._1 = 0 && self.Value._2.MoveNext() then - self.Value._1 <- -1 - self.Value._2.Dispose() + if self.State._1 = 0 && self.State._2.MoveNext() then + self.State._1 <- -1 + self.State._2.Dispose() }) - |> fun compare -> compare.Value._1 + |> fun compare -> compare.State._1 [] let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = @@ -1155,7 +1155,7 @@ namespace Microsoft.FSharp.Collections upcast { new ConsumerChainedWithState<'T,'V,HashSet<'T>> (next,(HashSet<'T>(HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = - if this.Value.Add input then TailCall.avoid (next.ProcessNext input) + if this.State.Add input then TailCall.avoid (next.ProcessNext input) else false } } @@ -1166,7 +1166,7 @@ namespace Microsoft.FSharp.Collections upcast { new ConsumerChainedWithState<'T,'V,HashSet<'Key>> (next,(HashSet<'Key>(HashIdentity.Structural<'Key>))) with override this.ProcessNext (input:'T) : bool = - if this.Value.Add (keyf input) then TailCall.avoid (next.ProcessNext input) + if this.State.Add (keyf input) then TailCall.avoid (next.ProcessNext input) else false } } @@ -1176,18 +1176,18 @@ namespace Microsoft.FSharp.Collections |> foreach (fun _ -> { new FolderWithOnComplete<'T,Values>(Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - elif value > this.Value._2 then - this.Value._2 <- value + if this.State._1 then + this.State._1 <- false + this.State._2 <- value + elif value > this.State._2 then + this.State._2 <- value Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = - if this.Value._1 then + if this.State._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - |> fun max -> max.Value._2 + |> fun max -> max.State._2 [] @@ -1196,22 +1196,22 @@ namespace Microsoft.FSharp.Collections |> foreach (fun _ -> { new FolderWithOnComplete<'T,Values>(Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with override this.ProcessNext value = - match this.Value._1, f value with + match this.State._1, f value with | true, valueU -> - this.Value._1 <- false - this.Value._2 <- valueU - this.Value._3 <- value - | false, valueU when valueU > this.Value._2 -> - this.Value._2 <- valueU - this.Value._3 <- value + this.State._1 <- false + this.State._2 <- valueU + this.State._3 <- value + | false, valueU when valueU > this.State._2 -> + this.State._2 <- valueU + this.State._3 <- value | _ -> () Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = - if this.Value._1 then + if this.State._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - |> fun min -> min.Value._3 + |> fun min -> min.State._3 [] @@ -1220,18 +1220,18 @@ namespace Microsoft.FSharp.Collections |> foreach (fun _ -> { new FolderWithOnComplete<'T,Values>(Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value - elif value < this.Value._2 then - this.Value._2 <- value + if this.State._1 then + this.State._1 <- false + this.State._2 <- value + elif value < this.State._2 then + this.State._2 <- value Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = - if this.Value._1 then + if this.State._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - |> fun min -> min.Value._2 + |> fun min -> min.State._2 [] @@ -1240,22 +1240,22 @@ namespace Microsoft.FSharp.Collections |> foreach (fun _ -> { new FolderWithOnComplete< 'T,Values>(Values<_,_,_>(true,Unchecked.defaultof< 'U>,Unchecked.defaultof< 'T>)) with override this.ProcessNext value = - match this.Value._1, f value with + match this.State._1, f value with | true, valueU -> - this.Value._1 <- false - this.Value._2 <- valueU - this.Value._3 <- value - | false, valueU when valueU < this.Value._2 -> - this.Value._2 <- valueU - this.Value._3 <- value + this.State._1 <- false + this.State._2 <- valueU + this.State._3 <- value + | false, valueU when valueU < this.State._2 -> + this.State._2 <- valueU + this.State._3 <- value | _ -> () Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = - if this.Value._1 then + if this.State._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - |> fun min -> min.Value._3 + |> fun min -> min.State._3 [] @@ -1270,13 +1270,13 @@ namespace Microsoft.FSharp.Collections ) ) with override self.ProcessNext (input:'T) : bool = - if (*isFirst*) self.Value._1 then - self.Value._2 (*lastValue*)<- input - self.Value._1 (*isFirst*)<- false + if (*isFirst*) self.State._1 then + self.State._2 (*lastValue*)<- input + self.State._1 (*isFirst*)<- false false else - let currentPair = self.Value._2, input - self.Value._2 (*lastValue*)<- input + let currentPair = self.State._2, input + self.State._2 (*lastValue*)<- input TailCall.avoid (next.ProcessNext currentPair) }} @@ -1287,18 +1287,18 @@ namespace Microsoft.FSharp.Collections |> foreach (fun _ -> { new FolderWithOnComplete<'T, Values>(Values<_,_>(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value + if this.State._1 then + this.State._1 <- false + this.State._2 <- value else - this.Value._2 <- f this.Value._2 value + this.State._2 <- f this.State._2 value Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = - if this.Value._1 then + if this.State._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - |> fun reduced -> reduced.Value._2 + |> fun reduced -> reduced.State._2 [] @@ -1307,8 +1307,8 @@ namespace Microsoft.FSharp.Collections member __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,'State>(next, initialState) with override this.ProcessNext (input:'T) : bool = - this.Value <- folder this.Value input - TailCall.avoid (next.ProcessNext this.Value) } } + this.State <- folder this.State input + TailCall.avoid (next.ProcessNext this.State) } } [] @@ -1319,24 +1319,24 @@ namespace Microsoft.FSharp.Collections new ConsumerChainedWithStateAndCleanup<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = - if (*count*) self.Value < skipCount then - self.Value <- self.Value + 1 + if (*count*) self.State < skipCount then + self.State <- self.State + 1 false else TailCall.avoid (next.ProcessNext input) override self.OnDispose () = () override self.OnComplete _ = - if (*count*) self.Value < skipCount then - let x = skipCount - self.Value + if (*count*) self.State < skipCount then + let x = skipCount - self.State invalidOpFmt "{0}\ntried to skip {1} {2} past the end of the seq" [|errorString; x; (if x=1 then "element" else "elements")|] interface ISkipping with member self.Skipping () = let self = self :?> ConsumerChainedWithState<'T,'U,int> - if (*count*) self.Value < skipCount then - self.Value <- self.Value + 1 + if (*count*) self.State < skipCount then + self.State <- self.State + 1 true else false @@ -1349,9 +1349,9 @@ namespace Microsoft.FSharp.Collections member __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,bool>(next,true) with override self.ProcessNext (input:'T) : bool = - if self.Value (*skip*) then - self.Value <- predicate input - if self.Value (*skip*) then + if self.State (*skip*) then + self.State <- predicate input + if self.State (*skip*) then false else TailCall.avoid (next.ProcessNext input) @@ -1367,9 +1367,9 @@ namespace Microsoft.FSharp.Collections |> foreach (fun _ -> { new Folder< ^T,^T> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = - this.Value <- Checked.(+) this.Value value + this.State <- Checked.(+) this.State value Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun sum -> sum.Value + |> fun sum -> sum.State [] @@ -1380,9 +1380,9 @@ namespace Microsoft.FSharp.Collections |> foreach (fun _ -> { new Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = - this.Value <- Checked.(+) this.Value (f value) + this.State <- Checked.(+) this.State (f value) Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun sum -> sum.Value + |> fun sum -> sum.State [] @@ -1392,9 +1392,9 @@ namespace Microsoft.FSharp.Collections upcast { new ConsumerChainedWithStateAndCleanup<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = - if (*count*) self.Value < takeCount then - self.Value <- self.Value + 1 - if self.Value = takeCount then + if (*count*) self.State < takeCount then + self.State <- self.State + 1 + if self.State = takeCount then outOfBand.StopFurtherProcessing pipelineIdx TailCall.avoid (next.ProcessNext input) else @@ -1403,8 +1403,8 @@ namespace Microsoft.FSharp.Collections override this.OnDispose () = () override this.OnComplete terminatingIdx = - if terminatingIdx < pipelineIdx && this.Value < takeCount then - let x = takeCount - this.Value + if terminatingIdx < pipelineIdx && this.State < takeCount then + let x = takeCount - this.State invalidOpFmt "tried to take {0} {1} past the end of the seq" [|errorString; x; (if x=1 then "element" else "elements")|] }} @@ -1430,15 +1430,15 @@ namespace Microsoft.FSharp.Collections member __.Create _ _ next = upcast { new ConsumerChainedWithStateAndCleanup<'T,'V,bool>(next,(*first*) true) with override self.ProcessNext (input:'T) : bool = - if (*first*) self.Value then - self.Value <- false + if (*first*) self.State then + self.State <- false false else TailCall.avoid (next.ProcessNext input) override self.OnDispose () = () override self.OnComplete _ = - if (*first*) self.Value then + if (*first*) self.State then invalidArg "source" errorString }} @@ -1450,9 +1450,9 @@ namespace Microsoft.FSharp.Collections upcast { new ConsumerChainedWithState<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = - if (*count*) self.Value < truncateCount then - self.Value <- self.Value + 1 - if self.Value = truncateCount then + if (*count*) self.State < truncateCount then + self.State <- self.State + 1 + if self.State = truncateCount then outOfBand.StopFurtherProcessing pipeIdx TailCall.avoid (next.ProcessNext input) else @@ -1480,11 +1480,11 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = match f value with | (Some _) as some -> - this.Value <- some + this.State <- some halt () | None -> () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun pick -> pick.Value + |> fun pick -> pick.State [] @@ -1494,10 +1494,10 @@ namespace Microsoft.FSharp.Collections { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = if f value then - this.Value <- Some value + this.State <- Some value halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun find -> find.Value + |> fun find -> find.State [] @@ -1507,12 +1507,12 @@ namespace Microsoft.FSharp.Collections { new Folder<'T, Values, int>>(Values<_,_>(None, 0)) with override this.ProcessNext value = if predicate value then - this.Value._1 <- Some(this.Value._2) + this.State._1 <- Some(this.State._2) halt () else - this.Value._2 <- this.Value._2 + 1 + this.State._2 <- this.State._2 + 1 Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun tried -> tried.Value._1 + |> fun tried -> tried.State._1 [] let inline tryLast (source :ISeq<'T>) : 'T option = @@ -1520,15 +1520,15 @@ namespace Microsoft.FSharp.Collections |> foreach (fun _ -> { new Folder<'T, Values>(Values(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = - if this.Value._1 then - this.Value._1 <- false - this.Value._2 <- value + if this.State._1 then + this.State._1 <- false + this.State._2 <- value Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun tried -> - if tried.Value._1 then + if tried.State._1 then None else - Some tried.Value._2 + Some tried.State._2 [] @@ -1545,23 +1545,23 @@ namespace Microsoft.FSharp.Collections ) ) with override self.ProcessNext (input:'T) : bool = - self.Value._1.[(* idx *)self.Value._2] <- input + self.State._1.[(* idx *)self.State._2] <- input - self.Value._2 <- (* idx *)self.Value._2 + 1 - if (* idx *) self.Value._2 = windowSize then - self.Value._2 <- 0 + self.State._2 <- (* idx *)self.State._2 + 1 + if (* idx *) self.State._2 = windowSize then + self.State._2 <- 0 - if (* priming *) self.Value._3 > 0 then - self.Value._3 <- self.Value._3 - 1 + if (* priming *) self.State._3 > 0 then + self.State._3 <- self.State._3 - 1 false else if windowSize < 32 then - let window :'T [] = Array.init windowSize (fun i -> self.Value._1.[((* idx *)self.Value._2+i) % windowSize]: 'T) + let window :'T [] = Array.init windowSize (fun i -> self.State._1.[((* idx *)self.State._2+i) % windowSize]: 'T) TailCall.avoid (next.ProcessNext window) else let window = Array.zeroCreateUnchecked windowSize - Array.Copy((*circularBuffer*)self.Value._1, (* idx *)self.Value._2, window, 0, windowSize - (* idx *)self.Value._2) - Array.Copy((*circularBuffer*)self.Value._1, 0, window, windowSize - (* idx *)self.Value._2, (* idx *)self.Value._2) + Array.Copy((*circularBuffer*)self.State._1, (* idx *)self.State._2, window, 0, windowSize - (* idx *)self.State._2) + Array.Copy((*circularBuffer*)self.State._1, 0, window, windowSize - (* idx *)self.State._2, (* idx *)self.State._2) TailCall.avoid (next.ProcessNext window) }} diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 36cfd73ab8d..5611de37e4f 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -62,16 +62,16 @@ namespace Microsoft.FSharp.Collections abstract member ProcessNext : input:'T -> bool [] - type ConsumerWithState<'T,'U,'Value> = + type ConsumerWithState<'T,'U,'State> = inherit Consumer<'T,'U> - val mutable Value : 'Value - new : init:'Value -> ConsumerWithState<'T,'U,'Value> + val mutable State : 'State + new : 'State -> ConsumerWithState<'T,'U,'State> [] - type ConsumerChainedWithState<'T,'U,'Value> = - inherit ConsumerWithState<'T,'U,'Value> + type ConsumerChainedWithState<'T,'U,'State> = + inherit ConsumerWithState<'T,'U,'State> val private Next : Consumer - new : next:Consumer * init:'Value -> ConsumerChainedWithState<'T,'U,'Value> + new : next:Consumer * 'State -> ConsumerChainedWithState<'T,'U,'State> [] type ConsumerChained<'T,'U> = @@ -79,13 +79,13 @@ namespace Microsoft.FSharp.Collections new : next:Consumer -> ConsumerChained<'T,'U> [] - type ConsumerChainedWithStateAndCleanup<'T,'U,'Value> = - inherit ConsumerChainedWithState<'T,'U,'Value> + type ConsumerChainedWithStateAndCleanup<'T,'U,'State> = + inherit ConsumerChainedWithState<'T,'U,'State> abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit - new : next:Consumer * init:'Value -> ConsumerChainedWithStateAndCleanup<'T,'U,'Value> + new : next:Consumer * 'State -> ConsumerChainedWithStateAndCleanup<'T,'U,'State> [] type ConsumerChainedWithCleanup<'T,'U> = @@ -96,17 +96,17 @@ namespace Microsoft.FSharp.Collections /// is as a base class for an object expression that will be used from within /// the ForEach function. [] - type Folder<'T,'Value> = - inherit ConsumerWithState<'T,'T,'Value> - new : init:'Value -> Folder<'T,'Value> + type Folder<'T,'State> = + inherit ConsumerWithState<'T,'T,'State> + new : 'State -> Folder<'T,'State> [] - type FolderWithOnComplete<'T, 'Value> = - inherit Folder<'T,'Value> + type FolderWithOnComplete<'T, 'State> = + inherit Folder<'T,'State> abstract OnComplete : PipeIdx -> unit - new : init:'Value -> FolderWithOnComplete<'T,'Value> + new : 'State -> FolderWithOnComplete<'T,'State> [] type SeqFactory<'T,'U> = From 83e8ea42d5fed95872d2cfa2fa157b100e87b4c7 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 18 Dec 2016 09:13:07 +1100 Subject: [PATCH 256/286] Modified Folder to contain Result - This simplified foreach to allow for some further optimizations --- src/fsharp/FSharp.Core/seqcomposer.fs | 349 ++++++++++--------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 53 +--- 2 files changed, 152 insertions(+), 250 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 67052fa0e41..a47852b8867 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -63,8 +63,8 @@ namespace Microsoft.FSharp.Collections val mutable State : 'State - new (initialState) = { - State = initialState + new (initState) = { + State = initState } [] @@ -73,8 +73,8 @@ namespace Microsoft.FSharp.Collections val private Next : Consumer - new (next:Consumer, initialState) = { - inherit ConsumerWithState<'T,'U,'State> (initialState) + new (next:Consumer, initState) = { + inherit ConsumerWithState<'T,'U,'State> (initState) Next = next } @@ -106,12 +106,23 @@ namespace Microsoft.FSharp.Collections inherit ConsumerChainedWithStateAndCleanup<'T,'U,NoValue>(next, Unchecked.defaultof) [] - type Folder<'T,'U>(initialState) = - inherit ConsumerWithState<'T,'T,'U>(initialState) + type Folder<'T,'Result,'State> = + inherit ConsumerWithState<'T,'T,'State> + + val mutable Result : 'Result + + new (initalResult,initState) = { + inherit ConsumerWithState<'T,'T,'State>(initState) + Result = initalResult + } + + [] + type Folder<'T,'Result>(initResult) = + inherit Folder<'T,'Result,NoValue>(initResult,Unchecked.defaultof) [] - type FolderWithOnComplete<'T, 'U>(initialState) = - inherit Folder<'T,'U>(initialState) + type FolderWithOnComplete<'T,'Result,'State>(initResult,initState) = + inherit Folder<'T,'Result,'State>(initResult,initState) abstract OnComplete : PipeIdx -> unit @@ -131,7 +142,7 @@ namespace Microsoft.FSharp.Collections type ISeq<'T> = inherit IEnumerable<'T> abstract member Compose<'U> : (SeqFactory<'T,'U>) -> ISeq<'U> - abstract member ForEach<'consumer when 'consumer :> Consumer<'T,'T>> : f:((unit->unit)->'consumer) -> 'consumer + abstract member ForEach<'Result,'State> : f:((unit->unit)->Folder<'T,'Result,'State>) -> 'Result open Core @@ -249,7 +260,7 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 - let execute (f:(unit->unit)->#Consumer<'U,'U>) (current:SeqFactory<'T,'U>) executeOn = + let execute (f:(unit->unit)->Folder<'U,'Result,'State>) (current:SeqFactory<'T,'U>) executeOn = let pipeline = OutOfBand() let result = f (fun () -> (pipeline:>IOutOfBand).StopFurtherProcessing (current.PipeIdx+1)) let consumer = current.Build pipeline result @@ -257,7 +268,7 @@ namespace Microsoft.FSharp.Collections executeOn pipeline consumer let mutable stopTailCall = () consumer.ChainComplete (&stopTailCall, pipeline.HaltedIdx) - result + result.Result finally let mutable stopTailCall = () consumer.ChainDispose (&stopTailCall) @@ -360,7 +371,7 @@ namespace Microsoft.FSharp.Collections member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'U,'Result,'State>)) = ForEach.execute f current (ForEach.enumerable enumerable) and ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = @@ -415,7 +426,7 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable<'T,'V>(this, next)) - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'T,'Result,'State>)) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) and ConcatEnumerable<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = @@ -429,7 +440,7 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable<'T,'V>(this, next)) - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'T,'Result,'State>)) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) let create enumerable current = @@ -452,7 +463,7 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable.Enumerable<'T,'V>(this, next)) - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'T,'Result,'State>)) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) @@ -502,7 +513,7 @@ namespace Microsoft.FSharp.Collections member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'U,'Result,'State>)) = ForEach.execute f current (ForEach.array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:SeqFactory<'T,'U>) = @@ -554,7 +565,7 @@ namespace Microsoft.FSharp.Collections member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'U,'Result,'State>)) = ForEach.execute f current (ForEach.list alist) let create alist current = @@ -593,7 +604,7 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) - member this.ForEach (f:(unit->unit)->#Consumer<'U,'U>) = + member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'U,'Result,'State>)) = ForEach.execute f current (ForEach.unfold generator state) module Init = @@ -668,7 +679,7 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) - member this.ForEach (createResult:(unit->unit)->#Consumer<'U,'U>) = + member this.ForEach<'Result,'State> (createResult:((unit->unit)->Folder<'U,'Result,'State>)) = let terminatingIdx = getTerminatingIdx count ForEach.execute createResult current (ForEach.init f terminatingIdx) @@ -736,10 +747,9 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable<'T,'V>(count, f, next)) - member this.ForEach (f:(unit->unit)->#Consumer<'T,'T>) = + member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'T,'Result,'State>)) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (Upcast.enumerable this)) - [] let toComposer (source:seq<'T>) : ISeq<'T> = match source with @@ -749,7 +759,6 @@ namespace Microsoft.FSharp.Collections | null -> nullArg "source" | _ -> Upcast.seq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) - let inline foreach f (source:ISeq<_>) = source.ForEach f let inline compose (factory:#SeqFactory<_,_>) (source:ISeq<'T>) = source.Compose factory @@ -760,17 +769,16 @@ namespace Microsoft.FSharp.Collections and ^T:(static member DivideByInt : ^T * int -> ^T) = source |> foreach (fun _ -> - { new FolderWithOnComplete< ^T, Values< ^T, int>> (Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + upcast { new FolderWithOnComplete< ^T, ^T, int> (LanguagePrimitives.GenericZero, 0) with override this.ProcessNext value = - this.State._1 <- Checked.(+) this.State._1 value - this.State._2 <- this.State._2 + 1 + this.Result <- Checked.(+) this.Result value + this.State <- this.State + 1 Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = - if this.State._2 = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - |> fun total -> LanguagePrimitives.DivideByInt< ^T> total.State._1 total.State._2 - + if this.State = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + this.Result <- LanguagePrimitives.DivideByInt< ^T> this.Result this.State }) [] let inline averageBy (f : 'T -> ^U) (source: ISeq< 'T >) : ^U @@ -779,107 +787,93 @@ namespace Microsoft.FSharp.Collections and ^U:(static member DivideByInt : ^U * int -> ^U) = source |> foreach (fun _ -> - { new FolderWithOnComplete<'T,Values<'U, int>>(Values<_,_>(LanguagePrimitives.GenericZero, 0)) with + upcast { new FolderWithOnComplete<'T,'U, int>(LanguagePrimitives.GenericZero, 0) with override this.ProcessNext value = - this.State._1 <- Checked.(+) this.State._1 (f value) - this.State._2 <- this.State._2 + 1 + this.Result <- Checked.(+) this.Result (f value) + this.State <- this.State + 1 Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = - if this.State._2 = 0 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) - |> fun total -> LanguagePrimitives.DivideByInt< ^U> total.State._1 total.State._2 - + if this.State = 0 then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + this.Result <- LanguagePrimitives.DivideByInt< ^U> this.Result this.State }) [] let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance - [] let inline exactlyOne errorString (source : ISeq<'T>) : 'T = source |> foreach (fun halt -> - { new FolderWithOnComplete<'T, Values>(Values(true, Unchecked.defaultof<'T>, false)) with + upcast { new FolderWithOnComplete<'T,'T,Values>(Unchecked.defaultof<'T>, Values(true, false)) with override this.ProcessNext value = if this.State._1 then this.State._1 <- false - this.State._2 <- value + this.Result <- value else - this.State._3 <- true + this.State._2 <- true halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = if this.State._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - elif this.State._3 then + elif this.State._2 then invalidArg "source" errorString }) - |> fun one -> one.State._2 - [] let inline fold<'T,'State> (f:'State->'T->'State) (seed:'State) (source:ISeq<'T>) : 'State = source |> foreach (fun _ -> - { new Folder<'T,'State>(seed) with + upcast { new Folder<'T,'State>(seed) with override this.ProcessNext value = - this.State <- f this.State value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) - }) - |> fun folded -> folded.State - + this.Result <- f this.Result value + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) [] let inline fold2<'T1,'T2,'State> (folder:'State->'T1->'T2->'State) (state:'State) (source1: ISeq<'T1>) (source2: ISeq<'T2>) = source1 |> foreach (fun halt -> - { new FolderWithOnComplete<_,Values<'State,IEnumerator<'T2>>>(Values<_,_>(state,source2.GetEnumerator())) with + upcast { new FolderWithOnComplete<_,'State,IEnumerator<'T2>>(state,source2.GetEnumerator()) with override self.ProcessNext value = - if self.State._2.MoveNext() then - self.State._1 <- folder self.State._1 value self.State._2.Current + if self.State.MoveNext() then + self.Result <- folder self.Result value self.State.Current else halt() Unchecked.defaultof<_> (* return value unsed in ForEach context *) override self.OnComplete _ = - self.State._2.Dispose() - }) - |> fun fold -> fold.State._1 - + self.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)) - [] let initInfinite<'T> (f:int->'T) : ISeq<'T> = Upcast.seq (new Init.EnumerableDecider<'T>(Nullable (), f)) - [] 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)) - [] let iter f (source:ISeq<'T>) = source |> foreach (fun _ -> - { new Consumer<'T,'T> () with + upcast { new Folder<'T,NoValue> (Unchecked.defaultof) with override this.ProcessNext value = f value Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore - [] let inline iter2 (f:'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = source1 |> foreach (fun halt -> - { new FolderWithOnComplete<'T,IEnumerator<'U>> (source2.GetEnumerator()) with + upcast { new FolderWithOnComplete<'T,NoValue,IEnumerator<'U>> (Unchecked.defaultof<_>,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then f value self.State.Current @@ -888,16 +882,14 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) override self.OnComplete _ = - self.State.Dispose() - }) + self.State.Dispose() }) |> ignore - [] let inline iteri2 (f:int->'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = source1 |> foreach (fun halt -> - { new FolderWithOnComplete<'T,Values>>(Values<_,_>(-1,source2.GetEnumerator())) with + upcast { new FolderWithOnComplete<'T,NoValue,Values>>(Unchecked.defaultof<_>,Values<_,_>(-1,source2.GetEnumerator())) with override self.ProcessNext value = if self.State._2.MoveNext() then f self.State._1 value self.State._2.Current @@ -913,24 +905,21 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> ignore - [] let tryHead (source:ISeq<'T>) = source |> foreach (fun halt -> - { new Folder<'T, Option<'T>> (None) with + upcast { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = - this.State <- Some value + this.Result <- Some value halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun head -> head.State - [] let iteri f (source:ISeq<'T>) = source |> foreach (fun _ -> - { new Folder<'T, int> (0) with + { new Folder<'T,NoValue,int> (Unchecked.defaultof<_>,0) with override this.ProcessNext value = f this.State value this.State <- this.State + 1 @@ -945,89 +934,75 @@ namespace Microsoft.FSharp.Collections (next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = if this.State.Value.Add input then TailCall.avoid (next.ProcessNext input) - else false - }} - + else false }} [] let exists f (source:ISeq<'T>) = source |> foreach (fun halt -> - { new Folder<'T, bool> (false) with + upcast { new Folder<'T, bool> (false) with override this.ProcessNext value = if f value then - this.State <- true + this.Result <- true halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun exists -> exists.State - [] let exists2 (predicate:'T->'U->bool) (source1: ISeq<'T>) (source2: ISeq<'U>) : bool = source1 |> foreach (fun halt -> - { new FolderWithOnComplete<'T,Values>>(Values<_,_>(false,source2.GetEnumerator())) with + upcast { new FolderWithOnComplete<'T,bool,IEnumerator<'U>>(false,source2.GetEnumerator()) with override self.ProcessNext value = - if self.State._2.MoveNext() then - if predicate value self.State._2.Current then - self.State._1 <- true + if self.State.MoveNext() then + if predicate value self.State.Current then + self.Result <- true halt() else halt() Unchecked.defaultof<_> (* return value unsed in ForEach context *) override self.OnComplete _ = - self.State._2.Dispose() - - }) - |> fun exists -> exists.State._1 - + self.State.Dispose() }) [] let inline contains element (source:ISeq<'T>) = source |> foreach (fun halt -> - { new Folder<'T, bool> (false) with + upcast { new Folder<'T, bool> (false) with override this.ProcessNext value = if element = value then - this.State <- true + this.Result <- true halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun contains -> contains.State - [] let forall predicate (source:ISeq<'T>) = source |> foreach (fun halt -> - { new Folder<'T, bool> (true) with + upcast { new Folder<'T, bool> (true) with override this.ProcessNext value = if not (predicate value) then - this.State <- false + this.Result <- false halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun forall -> forall.State - [] let inline forall2 predicate (source1:ISeq<'T>) (source2:ISeq<'U>) : bool = source1 |> foreach (fun halt -> - { new FolderWithOnComplete<'T,Values>>(Values<_,_>(true,source2.GetEnumerator())) with + upcast { new FolderWithOnComplete<'T,bool,IEnumerator<'U>>(true,source2.GetEnumerator()) with override self.ProcessNext value = - if self.State._2.MoveNext() then - if not (predicate value self.State._2.Current) then - self.State._1 <- false + if self.State.MoveNext() then + if not (predicate value self.State.Current) then + self.Result <- false halt() else halt() Unchecked.defaultof<_> (* return value unsed in ForEach context *) override self.OnComplete _ = - self.State._2.Dispose() + self.State.Dispose() }) - |> fun all -> all.State._1 - [] let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = @@ -1038,7 +1013,6 @@ namespace Microsoft.FSharp.Collections 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 |> compose { new SeqFactory<'T,'U>() with @@ -1047,7 +1021,6 @@ namespace Microsoft.FSharp.Collections member __.ProcessNext input = TailCall.avoid (next.ProcessNext (f input)) } } - [] let inline mapi f source = source |> compose { new SeqFactory<'T,'U>() with @@ -1057,7 +1030,6 @@ namespace Microsoft.FSharp.Collections this.State <- this.State + 1 TailCall.avoid (next.ProcessNext (f this.State input)) } } - [] let inline map2<'First,'Second,'U> (map:'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = source1 |> compose { new SeqFactory<'First,'U>() with @@ -1074,7 +1046,6 @@ namespace Microsoft.FSharp.Collections override self.OnComplete _ = self.State.Dispose () } } - [] let inline mapi2<'First,'Second,'U> (map:int -> 'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = source1 |> compose { new SeqFactory<'First,'U>() with @@ -1118,24 +1089,22 @@ namespace Microsoft.FSharp.Collections let inline compareWith (f:'T -> 'T -> int) (source1 :ISeq<'T>) (source2:ISeq<'T>) : int = source1 |> foreach (fun halt -> - { new FolderWithOnComplete<'T,Values>>(Values<_,_>(0,source2.GetEnumerator())) with + upcast { new FolderWithOnComplete<'T,int,IEnumerator<'T>>(0,source2.GetEnumerator()) with override self.ProcessNext value = - if not (self.State._2.MoveNext()) then - self.State._1 <- 1 + if not (self.State.MoveNext()) then + self.Result <- 1 halt () else - let c = f value self.State._2.Current + let c = f value self.State.Current if c <> 0 then - self.State._1 <- c + self.Result <- c halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) override self.OnComplete _ = - if self.State._1 = 0 && self.State._2.MoveNext() then - self.State._1 <- -1 - self.State._2.Dispose() - }) - |> fun compare -> compare.State._1 + if self.Result = 0 && self.State.MoveNext() then + self.Result <- -1 + self.State.Dispose() }) [] let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = @@ -1147,7 +1116,6 @@ namespace Microsoft.FSharp.Collections | Some value -> TailCall.avoid (next.ProcessNext value) | None -> false } } - [] let inline distinct (source:ISeq<'T>) : ISeq<'T> when 'T:equality = source |> compose { new SeqFactory<'T,'T>() with @@ -1158,7 +1126,6 @@ namespace Microsoft.FSharp.Collections if this.State.Add input then TailCall.avoid (next.ProcessNext input) else false } } - [] let inline distinctBy (keyf:'T->'Key) (source:ISeq<'T>) :ISeq<'T> when 'Key:equality = source |> compose { new SeqFactory<'T,'T>() with @@ -1169,94 +1136,81 @@ namespace Microsoft.FSharp.Collections if this.State.Add (keyf input) then TailCall.avoid (next.ProcessNext input) else false } } - [] let inline max (source: ISeq<'T>) : 'T when 'T:comparison = source |> foreach (fun _ -> - { new FolderWithOnComplete<'T,Values>(Values<_,_>(true, Unchecked.defaultof<'T>)) with + upcast { new FolderWithOnComplete<'T,'T,bool>(Unchecked.defaultof<'T>,true) with override this.ProcessNext value = - if this.State._1 then - this.State._1 <- false - this.State._2 <- value - elif value > this.State._2 then - this.State._2 <- value + if this.State then + this.State <- false + this.Result <- value + elif value > this.Result then + this.Result <- value Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = - if this.State._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun max -> max.State._2 - + if this.State then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) [] let inline maxBy (f :'T -> 'U) (source: ISeq<'T>) : 'T when 'U:comparison = source |> foreach (fun _ -> - { new FolderWithOnComplete<'T,Values>(Values<_,_,_>(true,Unchecked.defaultof<'U>,Unchecked.defaultof<'T>)) with + upcast { new FolderWithOnComplete<'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.State._3 <- value + this.Result <- value | false, valueU when valueU > this.State._2 -> this.State._2 <- valueU - this.State._3 <- value + this.Result <- value | _ -> () Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = if this.State._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun min -> min.State._3 - + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) [] let inline min (source: ISeq< 'T>) : 'T when 'T:comparison = source |> foreach (fun _ -> - { new FolderWithOnComplete<'T,Values>(Values<_,_>(true, Unchecked.defaultof<'T>)) with + upcast { new FolderWithOnComplete<'T,'T,bool>(Unchecked.defaultof<'T>,true) with override this.ProcessNext value = - if this.State._1 then - this.State._1 <- false - this.State._2 <- value - elif value < this.State._2 then - this.State._2 <- value + if this.State then + this.State <- false + this.Result <- value + elif value < this.Result then + this.Result <- value Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = - if this.State._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun min -> min.State._2 - + if this.State then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) [] let inline minBy (f : 'T -> 'U) (source: ISeq<'T>) : 'T = source |> foreach (fun _ -> - { new FolderWithOnComplete< 'T,Values>(Values<_,_,_>(true,Unchecked.defaultof< 'U>,Unchecked.defaultof< 'T>)) with + upcast { new FolderWithOnComplete<'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.State._3 <- value + this.Result <- value | false, valueU when valueU < this.State._2 -> this.State._2 <- valueU - this.State._3 <- value + this.Result <- value | _ -> () Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = if this.State._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun min -> min.State._3 - + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) [] let inline pairwise (source:ISeq<'T>) : ISeq<'T * 'T> = @@ -1277,32 +1231,27 @@ namespace Microsoft.FSharp.Collections else let currentPair = self.State._2, input self.State._2 (*lastValue*)<- input - TailCall.avoid (next.ProcessNext currentPair) - }} - + TailCall.avoid (next.ProcessNext currentPair) }} [] let inline reduce (f:'T->'T->'T) (source : ISeq<'T>) : 'T = source |> foreach (fun _ -> - { new FolderWithOnComplete<'T, Values>(Values<_,_>(true, Unchecked.defaultof<'T>)) with + upcast { new FolderWithOnComplete<'T,'T,bool>(Unchecked.defaultof<'T>,true) with override this.ProcessNext value = - if this.State._1 then - this.State._1 <- false - this.State._2 <- value + if this.State then + this.State <- false + this.Result <- value else - this.State._2 <- f this.State._2 value + this.Result <- f this.Result value Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = - if this.State._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - }) - |> fun reduced -> reduced.State._2 - + if this.State then + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) [] - let inline scan (folder:'State->'T->'State) (initialState: 'State) (source:ISeq<'T>) :ISeq<'State> = + let inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = source |> compose { new SeqFactory<'T,'State>() with member __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,'State>(next, initialState) with @@ -1342,7 +1291,6 @@ namespace Microsoft.FSharp.Collections false }} - [] let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with @@ -1358,19 +1306,16 @@ namespace Microsoft.FSharp.Collections else TailCall.avoid (next.ProcessNext input) }} - [] let inline sum (source:ISeq< ^T>) : ^T when ^T:(static member Zero : ^T) and ^T:(static member (+) : ^T * ^T -> ^T) = source |> foreach (fun _ -> - { new Folder< ^T,^T> (LanguagePrimitives.GenericZero) with + upcast { new Folder< ^T,^T> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = - this.State <- Checked.(+) this.State value + this.Result <- Checked.(+) this.Result value Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun sum -> sum.State - [] let inline sumBy (f : 'T -> ^U) (source: ISeq<'T>) : ^U @@ -1378,12 +1323,10 @@ namespace Microsoft.FSharp.Collections and ^U:(static member (+) : ^U * ^U -> ^U) = source |> foreach (fun _ -> - { new Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + upcast { new Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = - this.State <- Checked.(+) this.State (f value) + this.Result <- Checked.(+) this.Result (f value) Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun sum -> sum.State - [] let inline take (errorString:string) (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = @@ -1409,7 +1352,6 @@ namespace Microsoft.FSharp.Collections [|errorString; x; (if x=1 then "element" else "elements")|] }} - [] let inline takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with @@ -1423,7 +1365,6 @@ namespace Microsoft.FSharp.Collections false }} - [] let inline tail errorString (source:ISeq<'T>) :ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with @@ -1439,9 +1380,7 @@ namespace Microsoft.FSharp.Collections override self.OnDispose () = () override self.OnComplete _ = if (*first*) self.State then - invalidArg "source" errorString - }} - + invalidArg "source" errorString }} [] let inline truncate (truncateCount:int) (source:ISeq<'T>) : ISeq<'T> = @@ -1457,79 +1396,67 @@ namespace Microsoft.FSharp.Collections TailCall.avoid (next.ProcessNext input) else outOfBand.StopFurtherProcessing pipeIdx - false - }} - + false }} [] - let inline indexed source = + let indexed source = mapi (fun i x -> i,x) source - [] let tryItem (errorString:string) index (source:ISeq<'T>) = if index < 0 then None else source |> skip errorString index |> tryHead - [] let tryPick f (source:ISeq<'T>) = source |> foreach (fun halt -> - { new Folder<'T, Option<'U>> (None) with + upcast { new Folder<'T, Option<'U>> (None) with override this.ProcessNext value = match f value with | (Some _) as some -> - this.State <- some + this.Result <- some halt () | None -> () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun pick -> pick.State - [] let tryFind f (source:ISeq<'T>) = source |> foreach (fun halt -> - { new Folder<'T, Option<'T>> (None) with + upcast { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = if f value then - this.State <- Some value + this.Result <- Some value halt () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun find -> find.State - [] let inline tryFindIndex (predicate:'T->bool) (source:ISeq<'T>) : int option = source |> foreach (fun halt -> - { new Folder<'T, Values, int>>(Values<_,_>(None, 0)) with + { new Folder<'T, Option, int>(None, 0) with override this.ProcessNext value = if predicate value then - this.State._1 <- Some(this.State._2) + this.Result <- Some this.State halt () else - this.State._2 <- this.State._2 + 1 + this.State <- this.State + 1 Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun tried -> tried.State._1 [] let inline tryLast (source :ISeq<'T>) : 'T option = source |> foreach (fun _ -> - { new Folder<'T, Values>(Values(true, Unchecked.defaultof<'T>)) with + upcast { new FolderWithOnComplete<'T,option<'T>,Values>(None,Values(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.State._1 then this.State._1 <- false this.State._2 <- value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) - |> fun tried -> - if tried.State._1 then - None - else - Some tried.State._2 - + Unchecked.defaultof<_> (* return value unsed in ForEach context *) + override this.OnComplete _ = + if not this.State._1 then + this.Result <- Some this.State._2 }) [] let inline windowed (windowSize:int) (source:ISeq<'T>) : ISeq<'T[]> = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 5611de37e4f..bc99866c796 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -96,17 +96,23 @@ namespace Microsoft.FSharp.Collections /// is as a base class for an object expression that will be used from within /// the ForEach function. [] - type Folder<'T,'State> = + type Folder<'T,'Result,'State> = inherit ConsumerWithState<'T,'T,'State> - new : 'State -> Folder<'T,'State> + new : 'Result*'State -> Folder<'T,'Result,'State> + val mutable Result : 'Result [] - type FolderWithOnComplete<'T, 'State> = - inherit Folder<'T,'State> + type Folder<'T,'Result> = + inherit Folder<'T,'Result,NoValue> + new : 'Result -> Folder<'T,'Result> + + [] + type FolderWithOnComplete<'T,'Result,'State> = + inherit Folder<'T,'Result,'State> abstract OnComplete : PipeIdx -> unit - new : 'State -> FolderWithOnComplete<'T,'State> + new : 'Result*'State -> FolderWithOnComplete<'T,'Result,'State> [] type SeqFactory<'T,'U> = @@ -118,7 +124,7 @@ namespace Microsoft.FSharp.Collections type ISeq<'T> = inherit System.Collections.Generic.IEnumerable<'T> abstract member Compose : SeqFactory<'T,'U> -> ISeq<'U> - abstract member ForEach : f:((unit -> unit) -> 'a) -> 'a when 'a :> Consumer<'T,'T> + abstract member ForEach<'Result,'State> : f:((unit->unit)->Folder<'T,'Result,'State>) -> 'Result open Core @@ -167,37 +173,6 @@ namespace Microsoft.FSharp.Collections new : unit -> OutOfBand member HaltedIdx : int end - module ForEach = begin - val enumerable : - enumerable:IEnumerable<'T> -> - outOfBand: OutOfBand -> - consumer: Consumer<'T,'U> -> unit - val array : - array:'T array -> - outOfBand: OutOfBand -> - consumer: Consumer<'T,'U> -> unit - val list : - alist:'T list -> - outOfBand: OutOfBand -> - consumer: Consumer<'T,'U> -> unit - val unfold : - generator:('S -> ('T * 'S) option) -> - state:'S -> - outOfBand: OutOfBand -> - consumer: Consumer<'T,'U> -> unit - val makeIsSkipping : - consumer: Consumer<'T,'U> -> (unit -> bool) - val init : - f:(int -> 'T) -> - terminatingIdx:int -> - outOfBand: OutOfBand -> - consumer: Consumer<'T,'U> -> unit - val execute : - f:((unit -> unit) -> 'a) -> - current: SeqFactory<'T,'U> -> - executeOn:( OutOfBand -> Consumer<'T,'U> -> - unit) -> 'a when 'a :> Consumer<'U,'U> - end module Enumerable = begin type Empty<'T> = class @@ -396,7 +371,7 @@ namespace Microsoft.FSharp.Collections [] val toComposer : source:seq<'T> -> ISeq<'T> - val inline foreach : f:((unit -> unit) -> 'a) -> source: ISeq<'b> -> 'a when 'a :> Consumer<'b,'b> + val inline foreach : f:((unit -> unit) -> Folder<'T,'Result,'State>) -> source: ISeq<'T> -> 'Result [] val inline average : source: ISeq< ^T> -> ^T @@ -544,7 +519,7 @@ namespace Microsoft.FSharp.Collections val inline truncate : truncateCount:int -> source:ISeq<'T> -> ISeq<'T> [] - val inline indexed : source: ISeq<'a> -> ISeq + val indexed : source: ISeq<'a> -> ISeq [] val tryItem : errorString:string -> index:int -> source: ISeq<'T> -> 'T option From 88298d62ed9422cd59cebd4ef9b0873558214af2 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 18 Dec 2016 14:08:50 +1100 Subject: [PATCH 257/286] Moved IOutOfBound into Folder - Avoid creating extra object - foreach implementations call StopFutureProcessing directly --- src/fsharp/FSharp.Core/seqcomposer.fs | 130 ++++++++++++------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 18 ++-- 2 files changed, 67 insertions(+), 81 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index a47852b8867..0a9f356fb09 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -110,9 +110,15 @@ namespace Microsoft.FSharp.Collections inherit ConsumerWithState<'T,'T,'State> 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,initState) = { inherit ConsumerWithState<'T,'T,'State>(initState) + HaltedIdx = 0 Result = initalResult } @@ -142,7 +148,7 @@ namespace Microsoft.FSharp.Collections type ISeq<'T> = inherit IEnumerable<'T> abstract member Compose<'U> : (SeqFactory<'T,'U>) -> ISeq<'U> - abstract member ForEach<'Result,'State> : f:((unit->unit)->Folder<'T,'Result,'State>) -> 'Result + abstract member ForEach<'Result,'State> : f:(PipeIdx->Folder<'T,'Result,'State>) -> 'Result open Core @@ -190,40 +196,27 @@ namespace Microsoft.FSharp.Collections | Finished = 2 type Result<'T>() = - inherit Consumer<'T,'T>() - - let mutable current = Unchecked.defaultof<'T> - let mutable haltedIdx = 0 + inherit Folder<'T,'T>(Unchecked.defaultof<'T>) - member __.Current = current member val SeqState = SeqProcessNextStates.NotStarted with get, set - member __.HaltedIdx = haltedIdx - interface IOutOfBand with - member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx - - override __.ProcessNext (input:'T) : bool = - current <- input + override this.ProcessNext (input:'T) : bool = + this.Result <- input true - type OutOfBand() = - let mutable haltedIdx = 0 - interface IOutOfBand with member __.StopFurtherProcessing pipeIdx = haltedIdx <- pipeIdx - member __.HaltedIdx = haltedIdx - module ForEach = - let enumerable (enumerable:IEnumerable<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + let enumerable (enumerable:IEnumerable<'T>) (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = use enumerator = enumerable.GetEnumerator () while (outOfBand.HaltedIdx = 0) && (enumerator.MoveNext ()) do consumer.ProcessNext enumerator.Current |> ignore - let array (array:array<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + let array (array:array<'T>) (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = let mutable idx = 0 while (outOfBand.HaltedIdx = 0) && (idx < array.Length) do consumer.ProcessNext array.[idx] |> ignore idx <- idx + 1 - let list (alist:list<'T>) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + let list (alist:list<'T>) (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = let rec iterate lst = match outOfBand.HaltedIdx, lst with | 0, hd :: tl -> @@ -232,7 +225,7 @@ namespace Microsoft.FSharp.Collections | _ -> () iterate alist - let unfold (generator:'S->option<'T*'S>) state (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + let unfold (generator:'S->option<'T*'S>) state (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = let rec iterate current = match outOfBand.HaltedIdx, generator current with | 0, Some (item, next) -> @@ -247,7 +240,7 @@ namespace Microsoft.FSharp.Collections | :? ISkipping as skip -> skip.Skipping | _ -> fun () -> false - let init f (terminatingIdx:int) (outOfBand:OutOfBand) (consumer:Consumer<'T,'U>) = + let init f (terminatingIdx:int) (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = let mutable idx = -1 let isSkipping = makeIsSkipping consumer let mutable maybeSkipping = true @@ -260,14 +253,13 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 - let execute (f:(unit->unit)->Folder<'U,'Result,'State>) (current:SeqFactory<'T,'U>) executeOn = - let pipeline = OutOfBand() - let result = f (fun () -> (pipeline:>IOutOfBand).StopFurtherProcessing (current.PipeIdx+1)) - let consumer = current.Build pipeline result + let execute (f:PipeIdx->Folder<'U,'Result,'State>) (current:SeqFactory<'T,'U>) executeOn = + let result = f (current.PipeIdx+1) + let consumer = current.Build result result try - executeOn pipeline consumer + executeOn result consumer let mutable stopTailCall = () - consumer.ChainComplete (&stopTailCall, pipeline.HaltedIdx) + consumer.ChainComplete (&stopTailCall, result.HaltedIdx) result.Result finally let mutable stopTailCall = () @@ -303,7 +295,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerator<'T> with member __.Current = - if result.SeqState = SeqProcessNextStates.InProcess then result.Current + if result.SeqState = SeqProcessNextStates.InProcess then result.Result else match result.SeqState with | SeqProcessNextStates.NotStarted -> notStarted() @@ -371,7 +363,7 @@ namespace Microsoft.FSharp.Collections member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) - member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'U,'Result,'State>)) = + member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = ForEach.execute f current (ForEach.enumerable enumerable) and ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = @@ -426,7 +418,7 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable<'T,'V>(this, next)) - member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'T,'Result,'State>)) = + member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) and ConcatEnumerable<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = @@ -440,7 +432,7 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable<'T,'V>(this, next)) - member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'T,'Result,'State>)) = + member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) let create enumerable current = @@ -463,7 +455,7 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable.Enumerable<'T,'V>(this, next)) - member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'T,'Result,'State>)) = + member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) @@ -513,7 +505,7 @@ namespace Microsoft.FSharp.Collections member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) - member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'U,'Result,'State>)) = + member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = ForEach.execute f current (ForEach.array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:SeqFactory<'T,'U>) = @@ -565,7 +557,7 @@ namespace Microsoft.FSharp.Collections member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) - member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'U,'Result,'State>)) = + member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = ForEach.execute f current (ForEach.list alist) let create alist current = @@ -604,7 +596,7 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) - member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'U,'Result,'State>)) = + member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = ForEach.execute f current (ForEach.unfold generator state) module Init = @@ -679,7 +671,7 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) - member this.ForEach<'Result,'State> (createResult:((unit->unit)->Folder<'U,'Result,'State>)) = + member this.ForEach<'Result,'State> (createResult:PipeIdx->Folder<'U,'Result,'State>) = let terminatingIdx = getTerminatingIdx count ForEach.execute createResult current (ForEach.init f terminatingIdx) @@ -747,7 +739,7 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable<'T,'V>(count, f, next)) - member this.ForEach<'Result,'State> (f:((unit->unit)->Folder<'T,'Result,'State>)) = + member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (Upcast.enumerable this)) [] @@ -804,7 +796,7 @@ namespace Microsoft.FSharp.Collections [] let inline exactlyOne errorString (source : ISeq<'T>) : 'T = source - |> foreach (fun halt -> + |> foreach (fun pipeIdx -> upcast { new FolderWithOnComplete<'T,'T,Values>(Unchecked.defaultof<'T>, Values(true, false)) with override this.ProcessNext value = if this.State._1 then @@ -812,7 +804,7 @@ namespace Microsoft.FSharp.Collections this.Result <- value else this.State._2 <- true - halt () + this.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = @@ -833,13 +825,13 @@ namespace Microsoft.FSharp.Collections [] let inline fold2<'T1,'T2,'State> (folder:'State->'T1->'T2->'State) (state:'State) (source1: ISeq<'T1>) (source2: ISeq<'T2>) = source1 - |> foreach (fun halt -> + |> foreach (fun pipeIdx -> upcast { new FolderWithOnComplete<_,'State,IEnumerator<'T2>>(state,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then self.Result <- folder self.Result value self.State.Current else - halt() + self.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) override self.OnComplete _ = @@ -872,13 +864,13 @@ namespace Microsoft.FSharp.Collections [] let inline iter2 (f:'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = source1 - |> foreach (fun halt -> + |> foreach (fun pipeIdx -> upcast { new FolderWithOnComplete<'T,NoValue,IEnumerator<'U>> (Unchecked.defaultof<_>,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then f value self.State.Current else - halt() + self.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) override self.OnComplete _ = @@ -888,7 +880,7 @@ namespace Microsoft.FSharp.Collections [] let inline iteri2 (f:int->'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = source1 - |> foreach (fun halt -> + |> foreach (fun pipeIdx -> upcast { new FolderWithOnComplete<'T,NoValue,Values>>(Unchecked.defaultof<_>,Values<_,_>(-1,source2.GetEnumerator())) with override self.ProcessNext value = if self.State._2.MoveNext() then @@ -896,7 +888,7 @@ namespace Microsoft.FSharp.Collections self.State._1 <- self.State._1 + 1 Unchecked.defaultof<_> else - halt() + self.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> override self.OnComplete _ = @@ -908,11 +900,11 @@ namespace Microsoft.FSharp.Collections [] let tryHead (source:ISeq<'T>) = source - |> foreach (fun halt -> + |> foreach (fun pipeIdx -> upcast { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = this.Result <- Some value - halt () + this.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) [] @@ -939,26 +931,26 @@ namespace Microsoft.FSharp.Collections [] let exists f (source:ISeq<'T>) = source - |> foreach (fun halt -> + |> foreach (fun pipeIdx -> upcast { new Folder<'T, bool> (false) with override this.ProcessNext value = if f value then this.Result <- true - halt () + this.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) [] let exists2 (predicate:'T->'U->bool) (source1: ISeq<'T>) (source2: ISeq<'U>) : bool = source1 - |> foreach (fun halt -> + |> foreach (fun pipeIdx -> upcast { new FolderWithOnComplete<'T,bool,IEnumerator<'U>>(false,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then if predicate value self.State.Current then self.Result <- true - halt() + self.StopFurtherProcessing pipeIdx else - halt() + self.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) override self.OnComplete _ = @@ -967,37 +959,37 @@ namespace Microsoft.FSharp.Collections [] let inline contains element (source:ISeq<'T>) = source - |> foreach (fun halt -> + |> foreach (fun pipeIdx -> upcast { new Folder<'T, bool> (false) with override this.ProcessNext value = if element = value then this.Result <- true - halt () + this.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) [] let forall predicate (source:ISeq<'T>) = source - |> foreach (fun halt -> + |> foreach (fun pipeIdx -> upcast { new Folder<'T, bool> (true) with override this.ProcessNext value = if not (predicate value) then this.Result <- false - halt () + this.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) [] let inline forall2 predicate (source1:ISeq<'T>) (source2:ISeq<'U>) : bool = source1 - |> foreach (fun halt -> + |> foreach (fun pipeIdx -> upcast { new FolderWithOnComplete<'T,bool,IEnumerator<'U>>(true,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then if not (predicate value self.State.Current) then self.Result <- false - halt() + self.StopFurtherProcessing pipeIdx else - halt() + self.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) override self.OnComplete _ = @@ -1088,17 +1080,17 @@ namespace Microsoft.FSharp.Collections [] let inline compareWith (f:'T -> 'T -> int) (source1 :ISeq<'T>) (source2:ISeq<'T>) : int = source1 - |> foreach (fun halt -> + |> foreach (fun pipeIdx -> upcast { new FolderWithOnComplete<'T,int,IEnumerator<'T>>(0,source2.GetEnumerator()) with override self.ProcessNext value = if not (self.State.MoveNext()) then self.Result <- 1 - halt () + self.StopFurtherProcessing pipeIdx else let c = f value self.State.Current if c <> 0 then self.Result <- c - halt () + self.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) override self.OnComplete _ = @@ -1410,36 +1402,36 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source:ISeq<'T>) = source - |> foreach (fun halt -> + |> foreach (fun pipeIdx -> upcast { new Folder<'T, Option<'U>> (None) with override this.ProcessNext value = match f value with | (Some _) as some -> this.Result <- some - halt () + this.StopFurtherProcessing pipeIdx | None -> () Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) [] let tryFind f (source:ISeq<'T>) = source - |> foreach (fun halt -> + |> foreach (fun pipeIdx -> upcast { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = if f value then this.Result <- Some value - halt () + this.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) [] let inline tryFindIndex (predicate:'T->bool) (source:ISeq<'T>) : int option = source - |> foreach (fun halt -> + |> foreach (fun pipeIdx -> { new Folder<'T, Option, int>(None, 0) with override this.ProcessNext value = if predicate value then this.Result <- Some this.State - halt () + this.StopFurtherProcessing pipeIdx else this.State <- this.State + 1 Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index bc99866c796..1cff06c2718 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -99,7 +99,10 @@ namespace Microsoft.FSharp.Collections type Folder<'T,'Result,'State> = inherit ConsumerWithState<'T,'T,'State> new : 'Result*'State -> Folder<'T,'Result,'State> + interface IOutOfBand + val mutable HaltedIdx : int val mutable Result : 'Result + member StopFurtherProcessing : PipeIdx -> unit [] type Folder<'T,'Result> = @@ -124,7 +127,7 @@ namespace Microsoft.FSharp.Collections type ISeq<'T> = inherit System.Collections.Generic.IEnumerable<'T> abstract member Compose : SeqFactory<'T,'U> -> ISeq<'U> - abstract member ForEach<'Result,'State> : f:((unit->unit)->Folder<'T,'Result,'State>) -> 'Result + abstract member ForEach<'Result,'State> : f:(PipeIdx->Folder<'T,'Result,'State>) -> 'Result open Core @@ -158,21 +161,12 @@ namespace Microsoft.FSharp.Collections | Finished = 2 type Result<'T> = class - inherit Consumer<'T,'T> - interface IOutOfBand + inherit Folder<'T,'T> new : unit -> Result<'T> - member Current : 'T - member HaltedIdx : int member SeqState : SeqProcessNextStates member SeqState : SeqProcessNextStates with set override ProcessNext : input:'T -> bool end - type OutOfBand = - class - interface IOutOfBand - new : unit -> OutOfBand - member HaltedIdx : int - end module Enumerable = begin type Empty<'T> = class @@ -371,7 +365,7 @@ namespace Microsoft.FSharp.Collections [] val toComposer : source:seq<'T> -> ISeq<'T> - val inline foreach : f:((unit -> unit) -> Folder<'T,'Result,'State>) -> source: ISeq<'T> -> 'Result + val inline foreach : f:(PipeIdx->Folder<'T,'Result,'State>) -> source:ISeq<'T> -> 'Result [] val inline average : source: ISeq< ^T> -> ^T From 1d443f84078d98a0a1a7438ef4572266e0f8fe93 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 18 Dec 2016 14:13:56 +1100 Subject: [PATCH 258/286] Added Upcast for IOutOfBand --- src/fsharp/FSharp.Core/seqcomposer.fs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 0a9f356fb09..0a172ff17eb 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -165,7 +165,7 @@ namespace Microsoft.FSharp.Collections let inline enumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) let inline enumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) let inline enumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - + let inline outOfBand (t:#IOutOfBand) : IOutOfBand = (# "" t : IOutOfBand #) type ComposedFactory<'T,'U,'V> private (first:SeqFactory<'T,'U>, second:SeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = inherit SeqFactory<'T,'V>() @@ -255,7 +255,7 @@ namespace Microsoft.FSharp.Collections let execute (f:PipeIdx->Folder<'U,'Result,'State>) (current:SeqFactory<'T,'U>) executeOn = let result = f (current.PipeIdx+1) - let consumer = current.Build result result + let consumer = current.Build (Upcast.outOfBand result) result try executeOn result consumer let mutable stopTailCall = () @@ -357,7 +357,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Build result result, result)) + Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Build (Upcast.outOfBand result) result, result)) interface ISeq<'U> with member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -499,7 +499,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Build result result, result)) + Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, current.Build (Upcast.outOfBand result) result, result)) interface ISeq<'U> with member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -551,7 +551,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Build result result, result)) + Upcast.enumerator (new Enumerator<'T,'U>(alist, current.Build (Upcast.outOfBand result) result, result)) interface ISeq<'U> with member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -590,7 +590,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Build result result, result)) + Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, current.Build (Upcast.outOfBand result) result, result)) interface ISeq<'U> with member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = @@ -665,7 +665,7 @@ namespace Microsoft.FSharp.Collections interface IEnumerable<'U> with member this.GetEnumerator () : IEnumerator<'U> = let result = Result<'U> () - Upcast.enumerator (new Enumerator<'T,'U>(count, f, current.Build result result, result)) + Upcast.enumerator (new Enumerator<'T,'U>(count, f, current.Build (Upcast.outOfBand result) result, result)) interface ISeq<'U> with member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = From 4d77c559a9ad86921589d2c01e37b132452a555b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 18 Dec 2016 14:45:40 +1100 Subject: [PATCH 259/286] Added *Thin for when no transforms applied --- src/fsharp/FSharp.Core/seqcomposer.fs | 38 +++++++++++++++++++++------ 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 0a172ff17eb..54f669e5090 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -254,17 +254,26 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 let execute (f:PipeIdx->Folder<'U,'Result,'State>) (current:SeqFactory<'T,'U>) executeOn = + let mutable stopTailCall = () let result = f (current.PipeIdx+1) let consumer = current.Build (Upcast.outOfBand result) result try executeOn result consumer - let mutable stopTailCall = () consumer.ChainComplete (&stopTailCall, result.HaltedIdx) result.Result finally - let mutable stopTailCall = () consumer.ChainDispose (&stopTailCall) + let executeThin (f:PipeIdx->Folder<'U,'Result,'State>) executeOn = + let mutable stopTailCall = () + let result = f 1 + try + executeOn 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" @@ -366,6 +375,19 @@ namespace Microsoft.FSharp.Collections member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = ForEach.execute f current (ForEach.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 __.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = + Upcast.seq (new Enumerable<'T,'U>(enumerable, next)) + + member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + ForEach.executeThin f (ForEach.enumerable enumerable) + and ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = let mutable state = SeqProcessNextStates.NotStarted let main = sources.GetEnumerator () @@ -419,7 +441,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (Enumerable<'T,'V>(this, next)) member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) + ForEach.executeThin f (ForEach.enumerable this) and ConcatEnumerable<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = inherit EnumerableBase<'T>() @@ -433,7 +455,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (Enumerable<'T,'V>(this, next)) member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) + ForEach.executeThin f (ForEach.enumerable this) let create enumerable current = Upcast.seq (Enumerable(enumerable, current)) @@ -449,14 +471,14 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () : IEnumerator<'T> = IEnumerator.Empty<'T>() override this.Append source = - Upcast.enumerable (Enumerable.Enumerable<'T,'T> (source, IdentityFactory.Instance)) + Upcast.enumerable (Enumerable.EnumerableThin<'T> source) interface ISeq<'T> with member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable.Enumerable<'T,'V>(this, next)) member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable this) + ForEach.executeThin f (ForEach.enumerable this) @@ -740,7 +762,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (Enumerable<'T,'V>(count, f, next)) member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - ForEach.execute f IdentityFactory.Instance (ForEach.enumerable (Upcast.enumerable this)) + ForEach.executeThin f (ForEach.enumerable (Upcast.enumerable this)) [] let toComposer (source:seq<'T>) : ISeq<'T> = @@ -749,7 +771,7 @@ namespace Microsoft.FSharp.Collections | :? array<'T> as a -> Upcast.seq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) | :? list<'T> as a -> Upcast.seq (List.Enumerable(a, IdentityFactory.Instance)) | null -> nullArg "source" - | _ -> Upcast.seq (Enumerable.Enumerable<'T,'T>(source, IdentityFactory.Instance)) + | _ -> Upcast.seq (Enumerable.EnumerableThin<'T> source) let inline foreach f (source:ISeq<_>) = source.ForEach f let inline compose (factory:#SeqFactory<_,_>) (source:ISeq<'T>) = source.Compose factory From 9c187b82a51b21b807602d6fbd39955cc47efe67 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 18 Dec 2016 19:22:34 +1100 Subject: [PATCH 260/286] Moved OnComplete Dipose() to OnDispose - fixed some consistency around member & override --- src/fsharp/FSharp.Core/seqcomposer.fs | 159 ++++++++++++------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 5 +- 2 files changed, 82 insertions(+), 82 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 54f669e5090..bc1073ca66c 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -127,14 +127,16 @@ namespace Microsoft.FSharp.Collections inherit Folder<'T,'Result,NoValue>(initResult,Unchecked.defaultof) [] - type FolderWithOnComplete<'T,'Result,'State>(initResult,initState) = + type FolderWithCleanup<'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 _ = () + override this.ChainDispose _ = + this.OnDispose () [] type SeqFactory<'T,'U> () = @@ -783,7 +785,7 @@ namespace Microsoft.FSharp.Collections and ^T:(static member DivideByInt : ^T * int -> ^T) = source |> foreach (fun _ -> - upcast { new FolderWithOnComplete< ^T, ^T, int> (LanguagePrimitives.GenericZero, 0) with + upcast { new FolderWithCleanup< ^T, ^T, int> (LanguagePrimitives.GenericZero, 0) with override this.ProcessNext value = this.Result <- Checked.(+) this.Result value this.State <- this.State + 1 @@ -792,7 +794,8 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if this.State = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - this.Result <- LanguagePrimitives.DivideByInt< ^T> this.Result this.State }) + this.Result <- LanguagePrimitives.DivideByInt< ^T> this.Result this.State + override this.OnDispose () = () }) [] let inline averageBy (f : 'T -> ^U) (source: ISeq< 'T >) : ^U @@ -801,7 +804,7 @@ namespace Microsoft.FSharp.Collections and ^U:(static member DivideByInt : ^U * int -> ^U) = source |> foreach (fun _ -> - upcast { new FolderWithOnComplete<'T,'U, int>(LanguagePrimitives.GenericZero, 0) with + upcast { new FolderWithCleanup<'T,'U, int>(LanguagePrimitives.GenericZero, 0) with override this.ProcessNext value = this.Result <- Checked.(+) this.Result (f value) this.State <- this.State + 1 @@ -810,7 +813,8 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if this.State = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - this.Result <- LanguagePrimitives.DivideByInt< ^U> this.Result this.State }) + this.Result <- LanguagePrimitives.DivideByInt< ^U> this.Result this.State + override this.OnDispose () = () }) [] let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance @@ -819,7 +823,7 @@ namespace Microsoft.FSharp.Collections let inline exactlyOne errorString (source : ISeq<'T>) : 'T = source |> foreach (fun pipeIdx -> - upcast { new FolderWithOnComplete<'T,'T,Values>(Unchecked.defaultof<'T>, Values(true, false)) with + upcast { new FolderWithCleanup<'T,'T,Values>(Unchecked.defaultof<'T>, Values(true, false)) with override this.ProcessNext value = if this.State._1 then this.State._1 <- false @@ -833,7 +837,8 @@ namespace Microsoft.FSharp.Collections if this.State._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString elif this.State._2 then - invalidArg "source" errorString }) + invalidArg "source" errorString + override this.OnDispose () = () }) [] let inline fold<'T,'State> (f:'State->'T->'State) (seed:'State) (source:ISeq<'T>) : 'State = @@ -848,7 +853,7 @@ namespace Microsoft.FSharp.Collections let inline fold2<'T1,'T2,'State> (folder:'State->'T1->'T2->'State) (state:'State) (source1: ISeq<'T1>) (source2: ISeq<'T2>) = source1 |> foreach (fun pipeIdx -> - upcast { new FolderWithOnComplete<_,'State,IEnumerator<'T2>>(state,source2.GetEnumerator()) with + upcast { new FolderWithCleanup<_,'State,IEnumerator<'T2>>(state,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then self.Result <- folder self.Result value self.State.Current @@ -856,8 +861,8 @@ namespace Microsoft.FSharp.Collections self.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) - override self.OnComplete _ = - self.State.Dispose() }) + override self.OnComplete _ = () + override self.OnDispose () = self.State.Dispose() }) [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = @@ -887,7 +892,7 @@ namespace Microsoft.FSharp.Collections let inline iter2 (f:'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = source1 |> foreach (fun pipeIdx -> - upcast { new FolderWithOnComplete<'T,NoValue,IEnumerator<'U>> (Unchecked.defaultof<_>,source2.GetEnumerator()) with + upcast { new FolderWithCleanup<'T,NoValue,IEnumerator<'U>> (Unchecked.defaultof<_>,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then f value self.State.Current @@ -895,15 +900,15 @@ namespace Microsoft.FSharp.Collections self.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) - override self.OnComplete _ = - self.State.Dispose() }) + override self.OnComplete _ = () + override self.OnDispose () = self.State.Dispose() }) |> ignore [] let inline iteri2 (f:int->'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = source1 |> foreach (fun pipeIdx -> - upcast { new FolderWithOnComplete<'T,NoValue,Values>>(Unchecked.defaultof<_>,Values<_,_>(-1,source2.GetEnumerator())) with + upcast { new FolderWithCleanup<'T,NoValue,Values>>(Unchecked.defaultof<_>,Values<_,_>(-1,source2.GetEnumerator())) with override self.ProcessNext value = if self.State._2.MoveNext() then f self.State._1 value self.State._2.Current @@ -912,11 +917,8 @@ namespace Microsoft.FSharp.Collections else self.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> - - override self.OnComplete _ = - self.State._2.Dispose() - - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + override self.OnComplete _ = () + override self.OnDispose () = self.State._2.Dispose() }) |> ignore [] @@ -943,7 +945,7 @@ namespace Microsoft.FSharp.Collections [] let inline except (itemsToExclude: seq<'T>) (source:ISeq<'T>) : ISeq<'T> when 'T:equality = source |> compose { new SeqFactory<'T,'T>() with - member __.Create _ _ next = + override __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,Lazy>> (next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = @@ -965,7 +967,7 @@ namespace Microsoft.FSharp.Collections let exists2 (predicate:'T->'U->bool) (source1: ISeq<'T>) (source2: ISeq<'U>) : bool = source1 |> foreach (fun pipeIdx -> - upcast { new FolderWithOnComplete<'T,bool,IEnumerator<'U>>(false,source2.GetEnumerator()) with + upcast { new FolderWithCleanup<'T,bool,IEnumerator<'U>>(false,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then if predicate value self.State.Current then @@ -975,8 +977,8 @@ namespace Microsoft.FSharp.Collections self.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) - override self.OnComplete _ = - self.State.Dispose() }) + override self.OnComplete _ = () + override self.OnDispose () = self.State.Dispose() }) [] let inline contains element (source:ISeq<'T>) = @@ -1004,7 +1006,7 @@ namespace Microsoft.FSharp.Collections let inline forall2 predicate (source1:ISeq<'T>) (source2:ISeq<'U>) : bool = source1 |> foreach (fun pipeIdx -> - upcast { new FolderWithOnComplete<'T,bool,IEnumerator<'U>>(true,source2.GetEnumerator()) with + upcast { new FolderWithCleanup<'T,bool,IEnumerator<'U>>(true,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then if not (predicate value self.State.Current) then @@ -1014,31 +1016,30 @@ namespace Microsoft.FSharp.Collections self.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) - override self.OnComplete _ = - self.State.Dispose() - }) + override self.OnComplete _ = () + override self.OnDispose () = self.State.Dispose() }) [] let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with - member __.Create _ _ next = + override __.Create _ _ next = upcast { new ConsumerChained<'T,'V>(next) with - member __.ProcessNext input = + 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 |> compose { new SeqFactory<'T,'U>() with - member __.Create _ _ next = + override __.Create _ _ next = upcast { new ConsumerChained<'T,'V>(next) with - member __.ProcessNext input = + override __.ProcessNext input = TailCall.avoid (next.ProcessNext (f input)) } } [] let inline mapi f source = source |> compose { new SeqFactory<'T,'U>() with - member __.Create _ _ next = + override __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,int>(next, -1) with override this.ProcessNext (input:'T) : bool = this.State <- this.State + 1 @@ -1047,63 +1048,57 @@ namespace Microsoft.FSharp.Collections [] let inline map2<'First,'Second,'U> (map:'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = source1 |> compose { new SeqFactory<'First,'U>() with - member __.Create<'V> outOfBand pipeIdx next = + override __.Create<'V> outOfBand pipeIdx next = upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, IEnumerator<'Second>>(next, (source2.GetEnumerator ())) with - member self.ProcessNext input = + override self.ProcessNext input = if self.State.MoveNext () then TailCall.avoid (next.ProcessNext (map input self.State.Current)) else outOfBand.StopFurtherProcessing pipeIdx false - - override self.OnDispose () = () - override self.OnComplete _ = - self.State.Dispose () } } + override self.OnComplete _ = () + override self.OnDispose () = self.State.Dispose () }} [] let inline mapi2<'First,'Second,'U> (map:int -> 'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = source1 |> compose { new SeqFactory<'First,'U>() with - member __.Create<'V> outOfBand pipeIdx next = + override __.Create<'V> outOfBand pipeIdx next = upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values>> (next, Values<_,_>(-1, source2.GetEnumerator ())) with - member self.ProcessNext input = + override self.ProcessNext input = if self.State._2.MoveNext () then self.State._1 <- self.State._1 + 1 TailCall.avoid (next.ProcessNext (map self.State._1 input self.State._2.Current)) else outOfBand.StopFurtherProcessing pipeIdx false - - override self.OnDispose () = () - override self.OnComplete _ = - self.State._2.Dispose () } } - + override self.OnDispose () = self.State._2.Dispose () + override self.OnComplete _ = () }} [] let inline map3<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) (source3:ISeq<'Third>) : ISeq<'U> = source1 |> compose { new SeqFactory<'First,'U>() with - member __.Create<'V> outOfBand pipeIdx next = + override __.Create<'V> outOfBand pipeIdx next = upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values,IEnumerator<'Third>>> (next, Values<_,_>(source2.GetEnumerator(),source3.GetEnumerator())) with - member self.ProcessNext input = + override self.ProcessNext input = if self.State._1.MoveNext() && self.State._2.MoveNext () then TailCall.avoid (next.ProcessNext (map input self.State._1 .Current self.State._2.Current)) else outOfBand.StopFurtherProcessing pipeIdx false - - override self.OnDispose () = () - override self.OnComplete _ = + override self.OnComplete _ = () + override self.OnDispose () = self.State._1.Dispose () - self.State._2.Dispose () } } + self.State._2.Dispose () }} [] let inline compareWith (f:'T -> 'T -> int) (source1 :ISeq<'T>) (source2:ISeq<'T>) : int = source1 |> foreach (fun pipeIdx -> - upcast { new FolderWithOnComplete<'T,int,IEnumerator<'T>>(0,source2.GetEnumerator()) with + upcast { new FolderWithCleanup<'T,int,IEnumerator<'T>>(0,source2.GetEnumerator()) with override self.ProcessNext value = if not (self.State.MoveNext()) then self.Result <- 1 @@ -1114,18 +1109,17 @@ namespace Microsoft.FSharp.Collections self.Result <- c self.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unsed in ForEach context *) - override self.OnComplete _ = if self.Result = 0 && self.State.MoveNext() then self.Result <- -1 - self.State.Dispose() }) + override self.OnDispose () = self.State.Dispose() }) [] let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = source |> compose { new SeqFactory<'T,'U>() with - member __.Create _ _ next = + override __.Create _ _ next = upcast { new ConsumerChained<'T,'V>(next) with - member __.ProcessNext input = + override __.ProcessNext input = match f input with | Some value -> TailCall.avoid (next.ProcessNext value) | None -> false } } @@ -1133,7 +1127,7 @@ namespace Microsoft.FSharp.Collections [] let inline distinct (source:ISeq<'T>) : ISeq<'T> when 'T:equality = source |> compose { new SeqFactory<'T,'T>() with - member __.Create _ _ next = + override __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,HashSet<'T>> (next,(HashSet<'T>(HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = @@ -1143,7 +1137,7 @@ namespace Microsoft.FSharp.Collections [] let inline distinctBy (keyf:'T->'Key) (source:ISeq<'T>) :ISeq<'T> when 'Key:equality = source |> compose { new SeqFactory<'T,'T>() with - member __.Create _ _ next = + override __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,HashSet<'Key>> (next,(HashSet<'Key>(HashIdentity.Structural<'Key>))) with override this.ProcessNext (input:'T) : bool = @@ -1154,7 +1148,7 @@ namespace Microsoft.FSharp.Collections let inline max (source: ISeq<'T>) : 'T when 'T:comparison = source |> foreach (fun _ -> - upcast { new FolderWithOnComplete<'T,'T,bool>(Unchecked.defaultof<'T>,true) with + upcast { new FolderWithCleanup<'T,'T,bool>(Unchecked.defaultof<'T>,true) with override this.ProcessNext value = if this.State then this.State <- false @@ -1165,13 +1159,14 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if this.State then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + override self.OnDispose () = () }) [] let inline maxBy (f :'T -> 'U) (source: ISeq<'T>) : 'T when 'U:comparison = source |> foreach (fun _ -> - upcast { new FolderWithOnComplete<'T,'T,Values>(Unchecked.defaultof<'T>,Values<_,_>(true,Unchecked.defaultof<'U>)) with + upcast { new FolderWithCleanup<'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 -> @@ -1186,13 +1181,14 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if this.State._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + override self.OnDispose () = () }) [] let inline min (source: ISeq< 'T>) : 'T when 'T:comparison = source |> foreach (fun _ -> - upcast { new FolderWithOnComplete<'T,'T,bool>(Unchecked.defaultof<'T>,true) with + upcast { new FolderWithCleanup<'T,'T,bool>(Unchecked.defaultof<'T>,true) with override this.ProcessNext value = if this.State then this.State <- false @@ -1203,13 +1199,14 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if this.State then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + override self.OnDispose () = () }) [] let inline minBy (f : 'T -> 'U) (source: ISeq<'T>) : 'T = source |> foreach (fun _ -> - upcast { new FolderWithOnComplete<'T,'T,Values>(Unchecked.defaultof<'T>,Values<_,_>(true,Unchecked.defaultof< 'U>)) with + upcast { new FolderWithCleanup<'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 -> @@ -1224,12 +1221,13 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if this.State._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + override self.OnDispose () = () }) [] let inline pairwise (source:ISeq<'T>) : ISeq<'T * 'T> = source |> compose { new SeqFactory<'T,'T * 'T>() with - member __.Create _ _ next = + override __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'U,Values> ( next , Values @@ -1251,7 +1249,7 @@ namespace Microsoft.FSharp.Collections let inline reduce (f:'T->'T->'T) (source : ISeq<'T>) : 'T = source |> foreach (fun _ -> - upcast { new FolderWithOnComplete<'T,'T,bool>(Unchecked.defaultof<'T>,true) with + upcast { new FolderWithCleanup<'T,'T,bool>(Unchecked.defaultof<'T>,true) with override this.ProcessNext value = if this.State then this.State <- false @@ -1262,12 +1260,13 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if this.State then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString }) + invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString + override self.OnDispose () = () }) [] let inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = source |> compose { new SeqFactory<'T,'State>() with - member __.Create _ _ next = + override __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,'State>(next, initialState) with override this.ProcessNext (input:'T) : bool = this.State <- folder this.State input @@ -1277,7 +1276,7 @@ namespace Microsoft.FSharp.Collections [] let inline skip (errorString:string) (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with - member __.Create _ _ next = + override __.Create _ _ next = upcast { new ConsumerChainedWithStateAndCleanup<'T,'U,int>(next,(*count*)0) with @@ -1288,12 +1287,12 @@ namespace Microsoft.FSharp.Collections else TailCall.avoid (next.ProcessNext input) - override self.OnDispose () = () override self.OnComplete _ = if (*count*) self.State < skipCount then let x = skipCount - self.State invalidOpFmt "{0}\ntried to skip {1} {2} past the end of the seq" [|errorString; x; (if x=1 then "element" else "elements")|] + override self.OnDispose () = () interface ISkipping with member self.Skipping () = @@ -1308,7 +1307,7 @@ namespace Microsoft.FSharp.Collections [] let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with - member __.Create _ _ next = + override __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,bool>(next,true) with override self.ProcessNext (input:'T) : bool = if self.State (*skip*) then @@ -1358,13 +1357,12 @@ namespace Microsoft.FSharp.Collections outOfBand.StopFurtherProcessing pipelineIdx false - 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" [|errorString; x; (if x=1 then "element" else "elements")|] - }} + override this.OnDispose () = () }} [] let inline takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = @@ -1391,10 +1389,10 @@ namespace Microsoft.FSharp.Collections else TailCall.avoid (next.ProcessNext input) - override self.OnDispose () = () override self.OnComplete _ = if (*first*) self.State then - invalidArg "source" errorString }} + invalidArg "source" errorString + override self.OnDispose () = () }} [] let inline truncate (truncateCount:int) (source:ISeq<'T>) : ISeq<'T> = @@ -1462,7 +1460,7 @@ namespace Microsoft.FSharp.Collections let inline tryLast (source :ISeq<'T>) : 'T option = source |> foreach (fun _ -> - upcast { new FolderWithOnComplete<'T,option<'T>,Values>(None,Values(true, Unchecked.defaultof<'T>)) with + upcast { new FolderWithCleanup<'T,option<'T>,Values>(None,Values(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.State._1 then this.State._1 <- false @@ -1470,7 +1468,8 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in ForEach context *) override this.OnComplete _ = if not this.State._1 then - this.Result <- Some this.State._2 }) + this.Result <- Some this.State._2 + override self.OnDispose () = () }) [] let inline windowed (windowSize:int) (source:ISeq<'T>) : ISeq<'T[]> = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 1cff06c2718..4d0468c5c0a 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -110,12 +110,13 @@ namespace Microsoft.FSharp.Collections new : 'Result -> Folder<'T,'Result> [] - type FolderWithOnComplete<'T,'Result,'State> = + type FolderWithCleanup<'T,'Result,'State> = inherit Folder<'T,'Result,'State> + abstract OnDispose : unit -> unit abstract OnComplete : PipeIdx -> unit - new : 'Result*'State -> FolderWithOnComplete<'T,'Result,'State> + new : 'Result*'State -> FolderWithCleanup<'T,'Result,'State> [] type SeqFactory<'T,'U> = From 4e35d5cefc247d99fe108efe07d753a73ad8abca Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 18 Dec 2016 19:49:02 +1100 Subject: [PATCH 261/286] "Inline" ForEach methods - via struct interface (i.e. inline at runtime) - basically speed parity for sum --- src/fsharp/FSharp.Core/seqcomposer.fs | 114 +++++++++++++++----------- 1 file changed, 67 insertions(+), 47 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index bc1073ca66c..3fb587418cc 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -207,70 +207,90 @@ namespace Microsoft.FSharp.Collections true module ForEach = - let enumerable (enumerable:IEnumerable<'T>) (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = - use enumerator = enumerable.GetEnumerator () - while (outOfBand.HaltedIdx = 0) && (enumerator.MoveNext ()) do - consumer.ProcessNext enumerator.Current |> ignore - - let array (array:array<'T>) (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = - let mutable idx = 0 - while (outOfBand.HaltedIdx = 0) && (idx < array.Length) do - consumer.ProcessNext array.[idx] |> ignore - idx <- idx + 1 - - let list (alist:list<'T>) (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = - let rec iterate lst = - match outOfBand.HaltedIdx, lst with - | 0, hd :: tl -> - consumer.ProcessNext hd |> ignore - iterate tl - | _ -> () - iterate alist - - let unfold (generator:'S->option<'T*'S>) state (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = - let rec iterate current = - match outOfBand.HaltedIdx, generator current with - | 0, Some (item, next) -> - consumer.ProcessNext item |> ignore - iterate next - | _ -> () - - iterate state + type IIterate<'T> = + abstract Iterate<'U,'Result,'State> : outOfBand:Folder<'U,'Result,'State> -> consumer:Consumer<'T,'U> -> unit + + [] + type enumerable<'T> (enumerable:IEnumerable<'T>) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'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:Consumer<'T,'U>) = + let mutable idx = 0 + while (outOfBand.HaltedIdx = 0) && (idx < array.Length) do + consumer.ProcessNext array.[idx] |> ignore + idx <- idx + 1 + + [] + type List<'T> (alist:list<'T>) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = + let rec iterate lst = + match outOfBand.HaltedIdx, lst with + | 0, hd :: tl -> + consumer.ProcessNext hd |> ignore + 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:Consumer<'T,'U>) = + let rec iterate current = + match outOfBand.HaltedIdx, generator current with + | 0, Some (item, next) -> + consumer.ProcessNext item |> ignore + iterate next + | _ -> () + + iterate state let makeIsSkipping (consumer:Consumer<'T,'U>) = match box consumer with | :? ISkipping as skip -> skip.Skipping | _ -> fun () -> false - let init f (terminatingIdx:int) (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = - let mutable idx = -1 - let isSkipping = makeIsSkipping consumer - let mutable maybeSkipping = true - while (outOfBand.HaltedIdx = 0) && (idx < terminatingIdx) do - if maybeSkipping then - maybeSkipping <- isSkipping () + type init<'T> (f, terminatingIdx:int) = + interface IIterate<'T> with + member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = + let mutable idx = -1 + let isSkipping = makeIsSkipping consumer + let mutable maybeSkipping = true + while (outOfBand.HaltedIdx = 0) && (idx < terminatingIdx) do + if maybeSkipping then + maybeSkipping <- isSkipping () - if not maybeSkipping then - consumer.ProcessNext (f (idx+1)) |> ignore + if not maybeSkipping then + consumer.ProcessNext (f (idx+1)) |> ignore - idx <- idx + 1 + idx <- idx + 1 - let execute (f:PipeIdx->Folder<'U,'Result,'State>) (current:SeqFactory<'T,'U>) executeOn = + let execute (f:PipeIdx->Folder<'U,'Result,'State>) (current:SeqFactory<'T,'U>) (executeOn:#IIterate<'T>) = let mutable stopTailCall = () let result = f (current.PipeIdx+1) let consumer = current.Build (Upcast.outOfBand result) result try - executeOn result consumer + executeOn.Iterate result consumer consumer.ChainComplete (&stopTailCall, result.HaltedIdx) result.Result finally consumer.ChainDispose (&stopTailCall) - let executeThin (f:PipeIdx->Folder<'U,'Result,'State>) executeOn = + let executeThin (f:PipeIdx->Folder<'T,'Result,'State>) (executeOn:#IIterate<'T>) = let mutable stopTailCall = () let result = f 1 try - executeOn result result + executeOn.Iterate result result result.ChainComplete (&stopTailCall, result.HaltedIdx) result.Result finally @@ -530,7 +550,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - ForEach.execute f current (ForEach.array (delayedArray ())) + ForEach.execute f current (ForEach.Array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:SeqFactory<'T,'U>) = Upcast.seq (Enumerable(delayedArray, current)) @@ -582,7 +602,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - ForEach.execute f current (ForEach.list alist) + ForEach.execute f current (ForEach.List alist) let create alist current = Upcast.seq (Enumerable(alist, current)) @@ -621,7 +641,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - ForEach.execute f current (ForEach.unfold generator state) + ForEach.execute f current (ForEach.unfold (generator, state)) module Init = // The original implementation of "init" delayed the calculation of Current, and so it was possible @@ -697,7 +717,7 @@ namespace Microsoft.FSharp.Collections member this.ForEach<'Result,'State> (createResult:PipeIdx->Folder<'U,'Result,'State>) = let terminatingIdx = getTerminatingIdx count - ForEach.execute createResult current (ForEach.init f terminatingIdx) + ForEach.execute createResult current (ForEach.init (f, terminatingIdx)) let upto lastOption f = match lastOption with From fe35bdac685220a69874f8a2fc9fbdbe731635f1 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 20 Dec 2016 16:31:52 +1100 Subject: [PATCH 262/286] Shrinking signature file --- src/fsharp/FSharp.Core/seq.fs | 15 +- src/fsharp/FSharp.Core/seqcomposer.fs | 24 ++- src/fsharp/FSharp.Core/seqcomposer.fsi | 246 ++----------------------- 3 files changed, 34 insertions(+), 251 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index c5adc43ac6f..08533094e68 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -51,14 +51,6 @@ namespace Microsoft.FSharp.Collections let inline foreach f (source:seq<_>) = Composer.foreach f (toComposer source) - let private seqFactory (createSeqComponent:#SeqFactory<_,_>) (source:seq<'T>) = - match source with - | :? Composer.Core.ISeq<'T> as s -> Upcast.enumerable (s.Compose createSeqComponent) - | :? array<'T> as a -> Upcast.enumerable (Composer.Array.create a createSeqComponent) - | :? list<'T> as a -> Upcast.enumerable (Composer.List.create a createSeqComponent) - | null -> nullArg "source" - | _ -> Upcast.enumerable (Composer.Enumerable.create source createSeqComponent) - [] let delay f = mkDelayedSeq f @@ -254,7 +246,7 @@ namespace Microsoft.FSharp.Collections [] let concat (sources:seq<#seq<'T>>) : seq<'T> = checkNonNull "sources" sources - upcast Composer.Enumerable.ConcatEnumerable sources + sources |> toComposer |> Composer.map toComposer |> Composer.concat |> Upcast.enumerable [] let length (source : seq<'T>) = @@ -304,10 +296,7 @@ namespace Microsoft.FSharp.Collections let append (source1: seq<'T>) (source2: seq<'T>) = checkNonNull "source1" source1 checkNonNull "source2" source2 - match source1 with - | :? Composer.Enumerable.EnumerableBase<'T> as s -> s.Append source2 - | _ -> Upcast.enumerable (new Composer.Enumerable.AppendEnumerable<_>([source2; source1])) - + Composer.append (toComposer source1) (toComposer source2) |> Upcast.enumerable [] let collect f sources = map f sources |> concat diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 3fb587418cc..1a16885a22c 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -337,9 +337,9 @@ namespace Microsoft.FSharp.Collections let derivedClassShouldImplement () = failwith "library implementation error: derived class should implement (should be abstract)" - abstract member Append : (seq<'T>) -> IEnumerable<'T> + abstract member Append : (ISeq<'T>) -> ISeq<'T> - default this.Append source = Upcast.enumerable (AppendEnumerable [this; source]) + default this.Append source = Upcast.seq (AppendEnumerable [this; source]) interface IEnumerable with member this.GetEnumerator () : IEnumerator = @@ -448,7 +448,7 @@ namespace Microsoft.FSharp.Collections main.Dispose () active.Dispose () - and AppendEnumerable<'T> (sources:list>) = + and AppendEnumerable<'T> (sources:list>) = inherit EnumerableBase<'T>() interface IEnumerable<'T> with @@ -456,7 +456,7 @@ namespace Microsoft.FSharp.Collections Upcast.enumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) override this.Append source = - Upcast.enumerable (AppendEnumerable (source :: sources)) + Upcast.seq (AppendEnumerable (source :: sources)) interface ISeq<'T> with member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = @@ -493,7 +493,7 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () : IEnumerator<'T> = IEnumerator.Empty<'T>() override this.Append source = - Upcast.enumerable (Enumerable.EnumerableThin<'T> source) + Upcast.seq (Enumerable.EnumerableThin<'T> source) interface ISeq<'T> with member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = @@ -1294,7 +1294,7 @@ namespace Microsoft.FSharp.Collections [] - let inline skip (errorString:string) (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = + let skip (errorString:string) (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = source |> compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = upcast { @@ -1525,3 +1525,15 @@ namespace Microsoft.FSharp.Collections 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])) + + diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 4d0468c5c0a..5178802bdf3 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -132,237 +132,6 @@ namespace Microsoft.FSharp.Collections open Core - type ComposedFactory<'T,'U,'V> = - class - inherit SeqFactory<'T,'V> - private new : first: SeqFactory<'T,'U> * - second: SeqFactory<'U,'V> * - secondPipeIdx: PipeIdx -> - ComposedFactory<'T,'U,'V> - static member - Combine : first: SeqFactory<'T,'U> -> - second: SeqFactory<'U,'V> -> - SeqFactory<'T,'V> - end - and IdentityFactory<'T> = - class - inherit SeqFactory<'T,'T> - new : unit -> IdentityFactory<'T> - static member Instance : SeqFactory<'T,'T> - end - - and ISkipping = - interface - abstract member Skipping : unit -> bool - end - - type SeqProcessNextStates = - | InProcess = 0 - | NotStarted = 1 - | Finished = 2 - type Result<'T> = - class - inherit Folder<'T,'T> - new : unit -> Result<'T> - member SeqState : SeqProcessNextStates - member SeqState : SeqProcessNextStates with set - override ProcessNext : input:'T -> bool - end - module Enumerable = begin - type Empty<'T> = - class - interface IDisposable - interface IEnumerator - interface IEnumerator<'T> - new : unit -> Empty<'T> - end - type EmptyEnumerators<'T> = - class - new : unit -> EmptyEnumerators<'T> - static member Element : IEnumerator<'T> - end - [] - type EnumeratorBase<'T> = - class - interface IEnumerator<'T> - interface IEnumerator - interface IDisposable - new : result: Result<'T> * - seqComponent: Consumer -> - EnumeratorBase<'T> - end - and [] EnumerableBase<'T> = - class - interface ISeq<'T> - interface IEnumerable<'T> - interface IEnumerable - new : unit -> EnumerableBase<'T> - abstract member - Append : seq<'T> -> IEnumerable<'T> - override - Append : source:seq<'T> -> IEnumerable<'T> - end - and Enumerator<'T,'U> = - class - inherit EnumeratorBase<'U> - interface IDisposable - interface IEnumerator - new : source:IEnumerator<'T> * - seqComponent: Consumer<'T,'U> * - result: Result<'U> -> - Enumerator<'T,'U> - end - and Enumerable<'T,'U> = - class - inherit EnumerableBase<'U> - interface ISeq<'U> - interface IEnumerable<'U> - new : enumerable:IEnumerable<'T> * - current: SeqFactory<'T,'U> -> - Enumerable<'T,'U> - end - and ConcatEnumerator<'T,'Collection when 'Collection :> seq<'T>> = - class - interface IDisposable - interface IEnumerator - interface IEnumerator<'T> - new : sources:seq<'Collection> -> - ConcatEnumerator<'T,'Collection> - end - and AppendEnumerable<'T> = - class - inherit EnumerableBase<'T> - interface ISeq<'T> - interface IEnumerable<'T> - new : sources:seq<'T> list -> AppendEnumerable<'T> - override - Append : source:seq<'T> -> - IEnumerable<'T> - end - and ConcatEnumerable<'T,'Collection when 'Collection :> seq<'T>> = - class - inherit EnumerableBase<'T> - interface ISeq<'T> - interface IEnumerable<'T> - new : sources:seq<'Collection> -> - ConcatEnumerable<'T,'Collection> - end - val create : - enumerable:IEnumerable<'a> -> - current: SeqFactory<'a,'b> -> ISeq<'b> - end - module EmptyEnumerable = begin - type Enumerable<'T> = - class - inherit Enumerable.EnumerableBase<'T> - interface ISeq<'T> - interface IEnumerable<'T> - new : unit -> Enumerable<'T> - override - Append : source:seq<'T> -> IEnumerable<'T> - static member Instance : ISeq<'T> - end - end - module Array = begin - type Enumerator<'T,'U> = - class - inherit Enumerable.EnumeratorBase<'U> - interface IEnumerator - new : delayedArray:(unit -> 'T array) * - seqComponent: Consumer<'T,'U> * - result: Result<'U> -> Enumerator<'T,'U> - end - type Enumerable<'T,'U> = - class - inherit Enumerable.EnumerableBase<'U> - interface ISeq<'U> - interface IEnumerable<'U> - new : delayedArray:(unit -> 'T array) * - current: SeqFactory<'T,'U> -> - Enumerable<'T,'U> - end - val createDelayed : - delayedArray:(unit -> 'T array) -> - current: SeqFactory<'T,'U> -> ISeq<'U> - val create : - array:'T array -> - current: SeqFactory<'T,'U> -> ISeq<'U> - val createDelayedId : - delayedArray:(unit -> 'T array) -> ISeq<'T> - val createId : array:'T array -> ISeq<'T> - end - module List = begin - type Enumerator<'T,'U> = - class - inherit Enumerable.EnumeratorBase<'U> - interface IEnumerator - new : alist:'T list * seqComponent: Consumer<'T,'U> * - result: Result<'U> -> Enumerator<'T,'U> - end - type Enumerable<'T,'U> = - class - inherit Enumerable.EnumerableBase<'U> - interface ISeq<'U> - interface IEnumerable<'U> - new : alist:'T list * current: SeqFactory<'T,'U> -> - Enumerable<'T,'U> - end - val create : - alist:'a list -> - current: SeqFactory<'a,'b> -> ISeq<'b> - end - module Unfold = begin - type Enumerator<'T,'U,'State> = - class - inherit Enumerable.EnumeratorBase<'U> - interface IEnumerator - new : generator:('State -> ('T * 'State) option) * state:'State * - seqComponent: Consumer<'T,'U> * - result: Result<'U> -> - Enumerator<'T,'U,'State> - end - type Enumerable<'T,'U,'GeneratorState> = - class - inherit Enumerable.EnumerableBase<'U> - interface ISeq<'U> - interface IEnumerable<'U> - new : generator:('GeneratorState -> ('T * 'GeneratorState) option) * - state:'GeneratorState * current: SeqFactory<'T,'U> -> - Enumerable<'T,'U,'GeneratorState> - end - end - module Init = begin - val getTerminatingIdx : count:Nullable -> int - type Enumerator<'T,'U> = - class - inherit Enumerable.EnumeratorBase<'U> - interface IEnumerator - new : count:Nullable * f:(int -> 'T) * - seqComponent: Consumer<'T,'U> * - result: Result<'U> -> Enumerator<'T,'U> - end - type Enumerable<'T,'U> = - class - inherit Enumerable.EnumerableBase<'U> - interface ISeq<'U> - interface IEnumerable<'U> - new : count:Nullable * f:(int -> 'T) * - current: SeqFactory<'T,'U> -> - Enumerable<'T,'U> - end - val upto : - lastOption:int option -> - f:(int -> 'U) -> IEnumerator<'U> - type EnumerableDecider<'T> = - class - inherit Enumerable.EnumerableBase<'T> - interface ISeq<'T> - interface IEnumerable<'T> - new : count:Nullable * f:(int -> 'T) -> - EnumerableDecider<'T> - end - end - [] val toComposer : source:seq<'T> -> ISeq<'T> @@ -486,7 +255,7 @@ namespace Microsoft.FSharp.Collections val inline scan : folder:('State->'T->'State) -> initialState:'State -> source:ISeq<'T> -> ISeq<'State> [] - val inline skip : errorString:string -> skipCount:int -> source:ISeq<'T> -> ISeq<'T> + val skip : errorString:string -> skipCount:int -> source:ISeq<'T> -> ISeq<'T> [] val inline skipWhile : predicate:('T->bool) -> source:ISeq<'T> -> ISeq<'T> @@ -533,3 +302,16 @@ namespace Microsoft.FSharp.Collections [] val inline windowed : windowSize:int -> source:ISeq<'T> -> ISeq<'T[]> + + [] + val concat : sources:ISeq<'Collection> -> ISeq<'T> when 'Collection :> ISeq<'T> + + [] + val append: source1:ISeq<'T> -> source2:ISeq<'T> -> ISeq<'T> + + module internal Array = begin + val createDelayed : (unit -> 'T array) -> SeqFactory<'T,'U> -> ISeq<'U> + val create : 'T array -> SeqFactory<'T,'U> -> ISeq<'U> + val createDelayedId : (unit -> 'T array) -> ISeq<'T> + val createId : 'T array -> ISeq<'T> + end From 178e302796081f63ff4bca2f43fbd6a3fcd2a388 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 20 Dec 2016 16:43:15 +1100 Subject: [PATCH 263/286] Removed foreach/compose helpers - the didn't really serve any purpose --- src/fsharp/FSharp.Core/seq.fs | 5 +- src/fsharp/FSharp.Core/seqcomposer.fs | 128 ++++++++++--------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 6 +- 3 files changed, 52 insertions(+), 87 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 08533094e68..e1dae6b0b7b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -46,10 +46,7 @@ namespace Microsoft.FSharp.Collections [] let toComposer (source:seq<'T>): Composer.Core.ISeq<'T> = - Composer.toComposer source - - let inline foreach f (source:seq<_>) = - Composer.foreach f (toComposer source) + Composer.ofSeq source [] let delay f = mkDelayedSeq f diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 1a16885a22c..3a783324398 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -786,8 +786,8 @@ namespace Microsoft.FSharp.Collections member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = ForEach.executeThin f (ForEach.enumerable (Upcast.enumerable this)) - [] - let toComposer (source:seq<'T>) : ISeq<'T> = + [] + let ofSeq (source:seq<'T>) : ISeq<'T> = match source with | :? ISeq<'T> as s -> s | :? array<'T> as a -> Upcast.seq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) @@ -795,16 +795,12 @@ namespace Microsoft.FSharp.Collections | null -> nullArg "source" | _ -> Upcast.seq (Enumerable.EnumerableThin<'T> source) - let inline foreach f (source:ISeq<_>) = source.ForEach f - let inline compose (factory:#SeqFactory<_,_>) (source:ISeq<'T>) = source.Compose factory - [] let 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) = - source - |> foreach (fun _ -> + source.ForEach (fun _ -> upcast { new FolderWithCleanup< ^T, ^T, int> (LanguagePrimitives.GenericZero, 0) with override this.ProcessNext value = this.Result <- Checked.(+) this.Result value @@ -822,8 +818,7 @@ namespace Microsoft.FSharp.Collections when ^U:(static member Zero : ^U) and ^U:(static member (+) : ^U * ^U -> ^U) and ^U:(static member DivideByInt : ^U * int -> ^U) = - source - |> foreach (fun _ -> + source.ForEach (fun _ -> upcast { new FolderWithCleanup<'T,'U, int>(LanguagePrimitives.GenericZero, 0) with override this.ProcessNext value = this.Result <- Checked.(+) this.Result (f value) @@ -841,8 +836,7 @@ namespace Microsoft.FSharp.Collections [] let inline exactlyOne errorString (source : ISeq<'T>) : 'T = - source - |> foreach (fun pipeIdx -> + source.ForEach (fun pipeIdx -> upcast { new FolderWithCleanup<'T,'T,Values>(Unchecked.defaultof<'T>, Values(true, false)) with override this.ProcessNext value = if this.State._1 then @@ -862,8 +856,7 @@ namespace Microsoft.FSharp.Collections [] let inline fold<'T,'State> (f:'State->'T->'State) (seed:'State) (source:ISeq<'T>) : 'State = - source - |> foreach (fun _ -> + source.ForEach (fun _ -> upcast { new Folder<'T,'State>(seed) with override this.ProcessNext value = this.Result <- f this.Result value @@ -871,8 +864,7 @@ namespace Microsoft.FSharp.Collections [] let inline fold2<'T1,'T2,'State> (folder:'State->'T1->'T2->'State) (state:'State) (source1: ISeq<'T1>) (source2: ISeq<'T2>) = - source1 - |> foreach (fun pipeIdx -> + source1.ForEach (fun pipeIdx -> upcast { new FolderWithCleanup<_,'State,IEnumerator<'T2>>(state,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then @@ -900,8 +892,7 @@ namespace Microsoft.FSharp.Collections [] let iter f (source:ISeq<'T>) = - source - |> foreach (fun _ -> + source.ForEach (fun _ -> upcast { new Folder<'T,NoValue> (Unchecked.defaultof) with override this.ProcessNext value = f value @@ -910,8 +901,7 @@ namespace Microsoft.FSharp.Collections [] let inline iter2 (f:'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = - source1 - |> foreach (fun pipeIdx -> + source1.ForEach (fun pipeIdx -> upcast { new FolderWithCleanup<'T,NoValue,IEnumerator<'U>> (Unchecked.defaultof<_>,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then @@ -926,8 +916,7 @@ namespace Microsoft.FSharp.Collections [] let inline iteri2 (f:int->'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = - source1 - |> foreach (fun pipeIdx -> + source1.ForEach (fun pipeIdx -> upcast { new FolderWithCleanup<'T,NoValue,Values>>(Unchecked.defaultof<_>,Values<_,_>(-1,source2.GetEnumerator())) with override self.ProcessNext value = if self.State._2.MoveNext() then @@ -943,8 +932,7 @@ namespace Microsoft.FSharp.Collections [] let tryHead (source:ISeq<'T>) = - source - |> foreach (fun pipeIdx -> + source.ForEach (fun pipeIdx -> upcast { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = this.Result <- Some value @@ -953,8 +941,7 @@ namespace Microsoft.FSharp.Collections [] let iteri f (source:ISeq<'T>) = - source - |> foreach (fun _ -> + source.ForEach (fun _ -> { new Folder<'T,NoValue,int> (Unchecked.defaultof<_>,0) with override this.ProcessNext value = f this.State value @@ -964,7 +951,7 @@ namespace Microsoft.FSharp.Collections [] let inline except (itemsToExclude: seq<'T>) (source:ISeq<'T>) : ISeq<'T> when 'T:equality = - source |> compose { new SeqFactory<'T,'T>() with + source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,Lazy>> (next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with @@ -974,8 +961,7 @@ namespace Microsoft.FSharp.Collections [] let exists f (source:ISeq<'T>) = - source - |> foreach (fun pipeIdx -> + source.ForEach (fun pipeIdx -> upcast { new Folder<'T, bool> (false) with override this.ProcessNext value = if f value then @@ -985,8 +971,7 @@ namespace Microsoft.FSharp.Collections [] let exists2 (predicate:'T->'U->bool) (source1: ISeq<'T>) (source2: ISeq<'U>) : bool = - source1 - |> foreach (fun pipeIdx -> + source1.ForEach (fun pipeIdx -> upcast { new FolderWithCleanup<'T,bool,IEnumerator<'U>>(false,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then @@ -1002,8 +987,7 @@ namespace Microsoft.FSharp.Collections [] let inline contains element (source:ISeq<'T>) = - source - |> foreach (fun pipeIdx -> + source.ForEach (fun pipeIdx -> upcast { new Folder<'T, bool> (false) with override this.ProcessNext value = if element = value then @@ -1013,8 +997,7 @@ namespace Microsoft.FSharp.Collections [] let forall predicate (source:ISeq<'T>) = - source - |> foreach (fun pipeIdx -> + source.ForEach (fun pipeIdx -> upcast { new Folder<'T, bool> (true) with override this.ProcessNext value = if not (predicate value) then @@ -1024,8 +1007,7 @@ namespace Microsoft.FSharp.Collections [] let inline forall2 predicate (source1:ISeq<'T>) (source2:ISeq<'U>) : bool = - source1 - |> foreach (fun pipeIdx -> + source1.ForEach (fun pipeIdx -> upcast { new FolderWithCleanup<'T,bool,IEnumerator<'U>>(true,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then @@ -1041,7 +1023,7 @@ namespace Microsoft.FSharp.Collections [] let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source |> compose { new SeqFactory<'T,'T>() with + source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = upcast { new ConsumerChained<'T,'V>(next) with override __.ProcessNext input = @@ -1050,15 +1032,15 @@ namespace Microsoft.FSharp.Collections [] let inline map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = - source |> compose { new SeqFactory<'T,'U>() with + source.Compose { new SeqFactory<'T,'U>() with override __.Create _ _ next = upcast { new ConsumerChained<'T,'V>(next) with override __.ProcessNext input = TailCall.avoid (next.ProcessNext (f input)) } } [] - let inline mapi f source = - source |> compose { new SeqFactory<'T,'U>() with + let inline mapi f (source:ISeq<_>) = + source.Compose { new SeqFactory<'T,'U>() with override __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,int>(next, -1) with override this.ProcessNext (input:'T) : bool = @@ -1067,7 +1049,7 @@ namespace Microsoft.FSharp.Collections [] let inline map2<'First,'Second,'U> (map:'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = - source1 |> compose { new SeqFactory<'First,'U>() with + source1.Compose { new SeqFactory<'First,'U>() with override __.Create<'V> outOfBand pipeIdx next = upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, IEnumerator<'Second>>(next, (source2.GetEnumerator ())) with override self.ProcessNext input = @@ -1081,7 +1063,7 @@ namespace Microsoft.FSharp.Collections [] let inline mapi2<'First,'Second,'U> (map:int -> 'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = - source1 |> compose { new SeqFactory<'First,'U>() with + source1.Compose { new SeqFactory<'First,'U>() with override __.Create<'V> outOfBand pipeIdx next = upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values>> (next, Values<_,_>(-1, source2.GetEnumerator ())) with @@ -1098,7 +1080,7 @@ namespace Microsoft.FSharp.Collections [] let inline map3<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) (source3:ISeq<'Third>) : ISeq<'U> = - source1 |> compose { new SeqFactory<'First,'U>() with + source1.Compose { new SeqFactory<'First,'U>() with override __.Create<'V> outOfBand pipeIdx next = upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values,IEnumerator<'Third>>> (next, Values<_,_>(source2.GetEnumerator(),source3.GetEnumerator())) with @@ -1116,8 +1098,7 @@ namespace Microsoft.FSharp.Collections [] let inline compareWith (f:'T -> 'T -> int) (source1 :ISeq<'T>) (source2:ISeq<'T>) : int = - source1 - |> foreach (fun pipeIdx -> + source1.ForEach (fun pipeIdx -> upcast { new FolderWithCleanup<'T,int,IEnumerator<'T>>(0,source2.GetEnumerator()) with override self.ProcessNext value = if not (self.State.MoveNext()) then @@ -1136,7 +1117,7 @@ namespace Microsoft.FSharp.Collections [] let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = - source |> compose { new SeqFactory<'T,'U>() with + source.Compose { new SeqFactory<'T,'U>() with override __.Create _ _ next = upcast { new ConsumerChained<'T,'V>(next) with override __.ProcessNext input = @@ -1146,7 +1127,7 @@ namespace Microsoft.FSharp.Collections [] let inline distinct (source:ISeq<'T>) : ISeq<'T> when 'T:equality = - source |> compose { new SeqFactory<'T,'T>() with + source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,HashSet<'T>> (next,(HashSet<'T>(HashIdentity.Structural<'T>))) with @@ -1156,7 +1137,7 @@ namespace Microsoft.FSharp.Collections [] let inline distinctBy (keyf:'T->'Key) (source:ISeq<'T>) :ISeq<'T> when 'Key:equality = - source |> compose { new SeqFactory<'T,'T>() with + source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,HashSet<'Key>> (next,(HashSet<'Key>(HashIdentity.Structural<'Key>))) with @@ -1166,8 +1147,7 @@ namespace Microsoft.FSharp.Collections [] let inline max (source: ISeq<'T>) : 'T when 'T:comparison = - source - |> foreach (fun _ -> + source.ForEach (fun _ -> upcast { new FolderWithCleanup<'T,'T,bool>(Unchecked.defaultof<'T>,true) with override this.ProcessNext value = if this.State then @@ -1184,8 +1164,7 @@ namespace Microsoft.FSharp.Collections [] let inline maxBy (f :'T -> 'U) (source: ISeq<'T>) : 'T when 'U:comparison = - source - |> foreach (fun _ -> + source.ForEach (fun _ -> upcast { new FolderWithCleanup<'T,'T,Values>(Unchecked.defaultof<'T>,Values<_,_>(true,Unchecked.defaultof<'U>)) with override this.ProcessNext value = match this.State._1, f value with @@ -1206,8 +1185,7 @@ namespace Microsoft.FSharp.Collections [] let inline min (source: ISeq< 'T>) : 'T when 'T:comparison = - source - |> foreach (fun _ -> + source.ForEach (fun _ -> upcast { new FolderWithCleanup<'T,'T,bool>(Unchecked.defaultof<'T>,true) with override this.ProcessNext value = if this.State then @@ -1224,8 +1202,7 @@ namespace Microsoft.FSharp.Collections [] let inline minBy (f : 'T -> 'U) (source: ISeq<'T>) : 'T = - source - |> foreach (fun _ -> + source.ForEach (fun _ -> upcast { new FolderWithCleanup<'T,'T,Values>(Unchecked.defaultof<'T>,Values<_,_>(true,Unchecked.defaultof< 'U>)) with override this.ProcessNext value = match this.State._1, f value with @@ -1246,7 +1223,7 @@ namespace Microsoft.FSharp.Collections [] let inline pairwise (source:ISeq<'T>) : ISeq<'T * 'T> = - source |> compose { new SeqFactory<'T,'T * 'T>() with + source.Compose { new SeqFactory<'T,'T * 'T>() with override __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'U,Values> ( next @@ -1267,8 +1244,7 @@ namespace Microsoft.FSharp.Collections [] let inline reduce (f:'T->'T->'T) (source : ISeq<'T>) : 'T = - source - |> foreach (fun _ -> + source.ForEach (fun _ -> upcast { new FolderWithCleanup<'T,'T,bool>(Unchecked.defaultof<'T>,true) with override this.ProcessNext value = if this.State then @@ -1285,7 +1261,7 @@ namespace Microsoft.FSharp.Collections [] let inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = - source |> compose { new SeqFactory<'T,'State>() with + source.Compose { new SeqFactory<'T,'State>() with override __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,'State>(next, initialState) with override this.ProcessNext (input:'T) : bool = @@ -1295,7 +1271,7 @@ namespace Microsoft.FSharp.Collections [] let skip (errorString:string) (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = - source |> compose { new SeqFactory<'T,'T>() with + source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = upcast { new ConsumerChainedWithStateAndCleanup<'T,'U,int>(next,(*count*)0) with @@ -1326,7 +1302,7 @@ namespace Microsoft.FSharp.Collections [] let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source |> compose { new SeqFactory<'T,'T>() with + source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = upcast { new ConsumerChainedWithState<'T,'V,bool>(next,true) with override self.ProcessNext (input:'T) : bool = @@ -1343,8 +1319,7 @@ namespace Microsoft.FSharp.Collections let inline sum (source:ISeq< ^T>) : ^T when ^T:(static member Zero : ^T) and ^T:(static member (+) : ^T * ^T -> ^T) = - source - |> foreach (fun _ -> + source.ForEach (fun _ -> upcast { new Folder< ^T,^T> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Result <- Checked.(+) this.Result value @@ -1354,8 +1329,7 @@ namespace Microsoft.FSharp.Collections let inline sumBy (f : 'T -> ^U) (source: ISeq<'T>) : ^U when ^U:(static member Zero : ^U) and ^U:(static member (+) : ^U * ^U -> ^U) = - source - |> foreach (fun _ -> + source.ForEach (fun _ -> upcast { new Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = this.Result <- Checked.(+) this.Result (f value) @@ -1363,7 +1337,7 @@ namespace Microsoft.FSharp.Collections [] let inline take (errorString:string) (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = - source |> compose { new SeqFactory<'T,'T>() with + source.Compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipelineIdx next = upcast { new ConsumerChainedWithStateAndCleanup<'T,'U,int>(next,(*count*)0) with @@ -1386,7 +1360,7 @@ namespace Microsoft.FSharp.Collections [] let inline takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source |> compose { new SeqFactory<'T,'T>() with + source.Compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipeIdx next = upcast { new ConsumerChained<'T,'V>(next) with override __.ProcessNext (input:'T) : bool = @@ -1399,7 +1373,7 @@ namespace Microsoft.FSharp.Collections [] let inline tail errorString (source:ISeq<'T>) :ISeq<'T> = - source |> compose { new SeqFactory<'T,'T>() with + source.Compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = upcast { new ConsumerChainedWithStateAndCleanup<'T,'V,bool>(next,(*first*) true) with override self.ProcessNext (input:'T) : bool = @@ -1416,7 +1390,7 @@ namespace Microsoft.FSharp.Collections [] let inline truncate (truncateCount:int) (source:ISeq<'T>) : ISeq<'T> = - source |> compose { new SeqFactory<'T,'T>() with + source.Compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipeIdx next = upcast { new ConsumerChainedWithState<'T,'U,int>(next,(*count*)0) with @@ -1441,8 +1415,7 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source:ISeq<'T>) = - source - |> foreach (fun pipeIdx -> + source.ForEach (fun pipeIdx -> upcast { new Folder<'T, Option<'U>> (None) with override this.ProcessNext value = match f value with @@ -1454,8 +1427,7 @@ namespace Microsoft.FSharp.Collections [] let tryFind f (source:ISeq<'T>) = - source - |> foreach (fun pipeIdx -> + source.ForEach (fun pipeIdx -> upcast { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = if f value then @@ -1465,8 +1437,7 @@ namespace Microsoft.FSharp.Collections [] let inline tryFindIndex (predicate:'T->bool) (source:ISeq<'T>) : int option = - source - |> foreach (fun pipeIdx -> + source.ForEach (fun pipeIdx -> { new Folder<'T, Option, int>(None, 0) with override this.ProcessNext value = if predicate value then @@ -1478,8 +1449,7 @@ namespace Microsoft.FSharp.Collections [] let inline tryLast (source :ISeq<'T>) : 'T option = - source - |> foreach (fun _ -> + source.ForEach (fun _ -> upcast { new FolderWithCleanup<'T,option<'T>,Values>(None,Values(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.State._1 then @@ -1493,7 +1463,7 @@ namespace Microsoft.FSharp.Collections [] let inline windowed (windowSize:int) (source:ISeq<'T>) : ISeq<'T[]> = - source |> compose { new SeqFactory<'T,'T[]>() with + source.Compose { new SeqFactory<'T,'T[]>() with member __.Create outOfBand pipeIdx next = upcast { new ConsumerChainedWithState<'T,'U,Values<'T[],int,int>> diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 5178802bdf3..45efa99bd62 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -132,10 +132,8 @@ namespace Microsoft.FSharp.Collections open Core - [] - val toComposer : source:seq<'T> -> ISeq<'T> - - val inline foreach : f:(PipeIdx->Folder<'T,'Result,'State>) -> source:ISeq<'T> -> 'Result + [] + val ofSeq : source:seq<'T> -> ISeq<'T> [] val inline average : source: ISeq< ^T> -> ^T From 8d2d9476069f7de1e35cefc0e416e7f997f86f8c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 20 Dec 2016 16:44:41 +1100 Subject: [PATCH 264/286] Renamed ForEach to Fold --- src/fsharp/FSharp.Core/seqcomposer.fs | 154 ++++++++++++------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 4 +- 2 files changed, 79 insertions(+), 79 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 3a783324398..93ca0b3bc78 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -150,7 +150,7 @@ namespace Microsoft.FSharp.Collections type ISeq<'T> = inherit IEnumerable<'T> abstract member Compose<'U> : (SeqFactory<'T,'U>) -> ISeq<'U> - abstract member ForEach<'Result,'State> : f:(PipeIdx->Folder<'T,'Result,'State>) -> 'Result + abstract member Fold<'Result,'State> : f:(PipeIdx->Folder<'T,'Result,'State>) -> 'Result open Core @@ -206,7 +206,7 @@ namespace Microsoft.FSharp.Collections this.Result <- input true - module ForEach = + module Fold = type IIterate<'T> = abstract Iterate<'U,'Result,'State> : outOfBand:Folder<'U,'Result,'State> -> consumer:Consumer<'T,'U> -> unit @@ -352,7 +352,7 @@ namespace Microsoft.FSharp.Collections interface ISeq<'T> with member __.Compose _ = derivedClassShouldImplement () - member __.ForEach _ = derivedClassShouldImplement () + member __.Fold _ = derivedClassShouldImplement () and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, seqComponent) @@ -394,8 +394,8 @@ namespace Microsoft.FSharp.Collections member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) - member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - ForEach.execute f current (ForEach.enumerable enumerable) + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + Fold.execute f current (Fold.enumerable enumerable) and EnumerableThin<'T>(enumerable:IEnumerable<'T>) = inherit EnumerableBase<'T>() @@ -407,8 +407,8 @@ namespace Microsoft.FSharp.Collections member __.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (new Enumerable<'T,'U>(enumerable, next)) - member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - ForEach.executeThin f (ForEach.enumerable enumerable) + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + Fold.executeThin f (Fold.enumerable enumerable) and ConcatEnumerator<'T, 'Collection when 'Collection :> seq<'T>> (sources:seq<'Collection>) = let mutable state = SeqProcessNextStates.NotStarted @@ -462,8 +462,8 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable<'T,'V>(this, next)) - member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - ForEach.executeThin f (ForEach.enumerable this) + 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>() @@ -476,8 +476,8 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable<'T,'V>(this, next)) - member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - ForEach.executeThin f (ForEach.enumerable this) + 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)) @@ -499,8 +499,8 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable.Enumerable<'T,'V>(this, next)) - member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - ForEach.executeThin f (ForEach.enumerable this) + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + Fold.executeThin f (Fold.enumerable this) @@ -549,8 +549,8 @@ namespace Microsoft.FSharp.Collections member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) - member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - ForEach.execute f current (ForEach.Array (delayedArray ())) + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + Fold.execute f current (Fold.Array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:SeqFactory<'T,'U>) = Upcast.seq (Enumerable(delayedArray, current)) @@ -601,8 +601,8 @@ namespace Microsoft.FSharp.Collections member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) - member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - ForEach.execute f current (ForEach.List alist) + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + Fold.execute f current (Fold.List alist) let create alist current = Upcast.seq (Enumerable(alist, current)) @@ -640,8 +640,8 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) - member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - ForEach.execute f current (ForEach.unfold (generator, state)) + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = + Fold.execute f current (Fold.unfold (generator, state)) module Init = // The original implementation of "init" delayed the calculation of Current, and so it was possible @@ -667,7 +667,7 @@ namespace Microsoft.FSharp.Collections inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let isSkipping = - ForEach.makeIsSkipping seqComponent + Fold.makeIsSkipping seqComponent let terminatingIdx = getTerminatingIdx count @@ -715,9 +715,9 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) - member this.ForEach<'Result,'State> (createResult:PipeIdx->Folder<'U,'Result,'State>) = + member this.Fold<'Result,'State> (createResult:PipeIdx->Folder<'U,'Result,'State>) = let terminatingIdx = getTerminatingIdx count - ForEach.execute createResult current (ForEach.init (f, terminatingIdx)) + Fold.execute createResult current (Fold.init (f, terminatingIdx)) let upto lastOption f = match lastOption with @@ -783,8 +783,8 @@ namespace Microsoft.FSharp.Collections member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = Upcast.seq (Enumerable<'T,'V>(count, f, next)) - member this.ForEach<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = - ForEach.executeThin f (ForEach.enumerable (Upcast.enumerable this)) + member this.Fold<'Result,'State> (f:PipeIdx->Folder<'T,'Result,'State>) = + Fold.executeThin f (Fold.enumerable (Upcast.enumerable this)) [] let ofSeq (source:seq<'T>) : ISeq<'T> = @@ -800,12 +800,12 @@ namespace Microsoft.FSharp.Collections when ^T:(static member Zero : ^T) and ^T:(static member (+) : ^T * ^T -> ^T) and ^T:(static member DivideByInt : ^T * int -> ^T) = - source.ForEach (fun _ -> + source.Fold (fun _ -> upcast { new FolderWithCleanup< ^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 unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in Fold context *) override this.OnComplete _ = if this.State = 0 then @@ -818,12 +818,12 @@ namespace Microsoft.FSharp.Collections when ^U:(static member Zero : ^U) and ^U:(static member (+) : ^U * ^U -> ^U) and ^U:(static member DivideByInt : ^U * int -> ^U) = - source.ForEach (fun _ -> + source.Fold (fun _ -> upcast { new FolderWithCleanup<'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 unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in Fold context *) override this.OnComplete _ = if this.State = 0 then @@ -836,7 +836,7 @@ namespace Microsoft.FSharp.Collections [] let inline exactlyOne errorString (source : ISeq<'T>) : 'T = - source.ForEach (fun pipeIdx -> + source.Fold (fun pipeIdx -> upcast { new FolderWithCleanup<'T,'T,Values>(Unchecked.defaultof<'T>, Values(true, false)) with override this.ProcessNext value = if this.State._1 then @@ -845,7 +845,7 @@ namespace Microsoft.FSharp.Collections else this.State._2 <- true this.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in Fold context *) override this.OnComplete _ = if this.State._1 then @@ -856,22 +856,22 @@ namespace Microsoft.FSharp.Collections [] let inline fold<'T,'State> (f:'State->'T->'State) (seed:'State) (source:ISeq<'T>) : 'State = - source.ForEach (fun _ -> + source.Fold (fun _ -> upcast { new Folder<'T,'State>(seed) with override this.ProcessNext value = this.Result <- f this.Result value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in Fold context *) }) [] let inline fold2<'T1,'T2,'State> (folder:'State->'T1->'T2->'State) (state:'State) (source1: ISeq<'T1>) (source2: ISeq<'T2>) = - source1.ForEach (fun pipeIdx -> + source1.Fold (fun pipeIdx -> upcast { new FolderWithCleanup<_,'State,IEnumerator<'T2>>(state,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then self.Result <- folder self.Result value self.State.Current else self.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in Fold context *) override self.OnComplete _ = () override self.OnDispose () = self.State.Dispose() }) @@ -892,23 +892,23 @@ namespace Microsoft.FSharp.Collections [] let iter f (source:ISeq<'T>) = - source.ForEach (fun _ -> + source.Fold (fun _ -> upcast { new Folder<'T,NoValue> (Unchecked.defaultof) with override this.ProcessNext value = f value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in Fold context *) }) |> ignore [] let inline iter2 (f:'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = - source1.ForEach (fun pipeIdx -> + source1.Fold (fun pipeIdx -> upcast { new FolderWithCleanup<'T,NoValue,IEnumerator<'U>> (Unchecked.defaultof<_>,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then f value self.State.Current else self.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in Fold context *) override self.OnComplete _ = () override self.OnDispose () = self.State.Dispose() }) @@ -916,7 +916,7 @@ namespace Microsoft.FSharp.Collections [] let inline iteri2 (f:int->'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = - source1.ForEach (fun pipeIdx -> + source1.Fold (fun pipeIdx -> upcast { new FolderWithCleanup<'T,NoValue,Values>>(Unchecked.defaultof<_>,Values<_,_>(-1,source2.GetEnumerator())) with override self.ProcessNext value = if self.State._2.MoveNext() then @@ -932,21 +932,21 @@ namespace Microsoft.FSharp.Collections [] let tryHead (source:ISeq<'T>) = - source.ForEach (fun pipeIdx -> + source.Fold (fun pipeIdx -> upcast { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = this.Result <- Some value this.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in Fold context *) }) [] let iteri f (source:ISeq<'T>) = - source.ForEach (fun _ -> + source.Fold (fun _ -> { new Folder<'T,NoValue,int> (Unchecked.defaultof<_>,0) with override this.ProcessNext value = f this.State value this.State <- this.State + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in Fold context *) }) |> ignore [] @@ -961,17 +961,17 @@ namespace Microsoft.FSharp.Collections [] let exists f (source:ISeq<'T>) = - source.ForEach (fun pipeIdx -> + source.Fold (fun pipeIdx -> upcast { new Folder<'T, bool> (false) with override this.ProcessNext value = if f value then this.Result <- true this.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in Fold context *) }) [] let exists2 (predicate:'T->'U->bool) (source1: ISeq<'T>) (source2: ISeq<'U>) : bool = - source1.ForEach (fun pipeIdx -> + source1.Fold (fun pipeIdx -> upcast { new FolderWithCleanup<'T,bool,IEnumerator<'U>>(false,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then @@ -980,34 +980,34 @@ namespace Microsoft.FSharp.Collections self.StopFurtherProcessing pipeIdx else self.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in Fold context *) override self.OnComplete _ = () override self.OnDispose () = self.State.Dispose() }) [] let inline contains element (source:ISeq<'T>) = - source.ForEach (fun pipeIdx -> + source.Fold (fun pipeIdx -> upcast { new Folder<'T, bool> (false) with override this.ProcessNext value = if element = value then this.Result <- true this.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in Fold context *) }) [] let forall predicate (source:ISeq<'T>) = - source.ForEach (fun pipeIdx -> + source.Fold (fun pipeIdx -> upcast { new Folder<'T, bool> (true) with override this.ProcessNext value = if not (predicate value) then this.Result <- false this.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in Fold context *) }) [] let inline forall2 predicate (source1:ISeq<'T>) (source2:ISeq<'U>) : bool = - source1.ForEach (fun pipeIdx -> + source1.Fold (fun pipeIdx -> upcast { new FolderWithCleanup<'T,bool,IEnumerator<'U>>(true,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then @@ -1016,7 +1016,7 @@ namespace Microsoft.FSharp.Collections self.StopFurtherProcessing pipeIdx else self.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in Fold context *) override self.OnComplete _ = () override self.OnDispose () = self.State.Dispose() }) @@ -1098,7 +1098,7 @@ namespace Microsoft.FSharp.Collections [] let inline compareWith (f:'T -> 'T -> int) (source1 :ISeq<'T>) (source2:ISeq<'T>) : int = - source1.ForEach (fun pipeIdx -> + source1.Fold (fun pipeIdx -> upcast { new FolderWithCleanup<'T,int,IEnumerator<'T>>(0,source2.GetEnumerator()) with override self.ProcessNext value = if not (self.State.MoveNext()) then @@ -1109,7 +1109,7 @@ namespace Microsoft.FSharp.Collections if c <> 0 then self.Result <- c self.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in Fold context *) override self.OnComplete _ = if self.Result = 0 && self.State.MoveNext() then self.Result <- -1 @@ -1147,7 +1147,7 @@ namespace Microsoft.FSharp.Collections [] let inline max (source: ISeq<'T>) : 'T when 'T:comparison = - source.ForEach (fun _ -> + source.Fold (fun _ -> upcast { new FolderWithCleanup<'T,'T,bool>(Unchecked.defaultof<'T>,true) with override this.ProcessNext value = if this.State then @@ -1155,7 +1155,7 @@ namespace Microsoft.FSharp.Collections this.Result <- value elif value > this.Result then this.Result <- value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in Fold context *) override this.OnComplete _ = if this.State then @@ -1164,7 +1164,7 @@ namespace Microsoft.FSharp.Collections [] let inline maxBy (f :'T -> 'U) (source: ISeq<'T>) : 'T when 'U:comparison = - source.ForEach (fun _ -> + source.Fold (fun _ -> upcast { new FolderWithCleanup<'T,'T,Values>(Unchecked.defaultof<'T>,Values<_,_>(true,Unchecked.defaultof<'U>)) with override this.ProcessNext value = match this.State._1, f value with @@ -1176,7 +1176,7 @@ namespace Microsoft.FSharp.Collections this.State._2 <- valueU this.Result <- value | _ -> () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in Fold context *) override this.OnComplete _ = if this.State._1 then @@ -1185,7 +1185,7 @@ namespace Microsoft.FSharp.Collections [] let inline min (source: ISeq< 'T>) : 'T when 'T:comparison = - source.ForEach (fun _ -> + source.Fold (fun _ -> upcast { new FolderWithCleanup<'T,'T,bool>(Unchecked.defaultof<'T>,true) with override this.ProcessNext value = if this.State then @@ -1193,7 +1193,7 @@ namespace Microsoft.FSharp.Collections this.Result <- value elif value < this.Result then this.Result <- value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in Fold context *) override this.OnComplete _ = if this.State then @@ -1202,7 +1202,7 @@ namespace Microsoft.FSharp.Collections [] let inline minBy (f : 'T -> 'U) (source: ISeq<'T>) : 'T = - source.ForEach (fun _ -> + source.Fold (fun _ -> upcast { new FolderWithCleanup<'T,'T,Values>(Unchecked.defaultof<'T>,Values<_,_>(true,Unchecked.defaultof< 'U>)) with override this.ProcessNext value = match this.State._1, f value with @@ -1214,7 +1214,7 @@ namespace Microsoft.FSharp.Collections this.State._2 <- valueU this.Result <- value | _ -> () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in Fold context *) override this.OnComplete _ = if this.State._1 then @@ -1244,7 +1244,7 @@ namespace Microsoft.FSharp.Collections [] let inline reduce (f:'T->'T->'T) (source : ISeq<'T>) : 'T = - source.ForEach (fun _ -> + source.Fold (fun _ -> upcast { new FolderWithCleanup<'T,'T,bool>(Unchecked.defaultof<'T>,true) with override this.ProcessNext value = if this.State then @@ -1252,7 +1252,7 @@ namespace Microsoft.FSharp.Collections this.Result <- value else this.Result <- f this.Result value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in Fold context *) override this.OnComplete _ = if this.State then @@ -1319,21 +1319,21 @@ namespace Microsoft.FSharp.Collections let inline sum (source:ISeq< ^T>) : ^T when ^T:(static member Zero : ^T) and ^T:(static member (+) : ^T * ^T -> ^T) = - source.ForEach (fun _ -> + source.Fold (fun _ -> upcast { new Folder< ^T,^T> (LanguagePrimitives.GenericZero) with override this.ProcessNext value = this.Result <- Checked.(+) this.Result value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in Fold context *) }) [] let inline sumBy (f : 'T -> ^U) (source: ISeq<'T>) : ^U when ^U:(static member Zero : ^U) and ^U:(static member (+) : ^U * ^U -> ^U) = - source.ForEach (fun _ -> + source.Fold (fun _ -> upcast { new Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with override this.ProcessNext value = this.Result <- Checked.(+) this.Result (f value) - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in Fold context *) }) [] let inline take (errorString:string) (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = @@ -1415,7 +1415,7 @@ namespace Microsoft.FSharp.Collections [] let tryPick f (source:ISeq<'T>) = - source.ForEach (fun pipeIdx -> + source.Fold (fun pipeIdx -> upcast { new Folder<'T, Option<'U>> (None) with override this.ProcessNext value = match f value with @@ -1423,21 +1423,21 @@ namespace Microsoft.FSharp.Collections this.Result <- some this.StopFurtherProcessing pipeIdx | None -> () - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in Fold context *) }) [] let tryFind f (source:ISeq<'T>) = - source.ForEach (fun pipeIdx -> + source.Fold (fun pipeIdx -> upcast { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = if f value then this.Result <- Some value this.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in Fold context *) }) [] let inline tryFindIndex (predicate:'T->bool) (source:ISeq<'T>) : int option = - source.ForEach (fun pipeIdx -> + source.Fold (fun pipeIdx -> { new Folder<'T, Option, int>(None, 0) with override this.ProcessNext value = if predicate value then @@ -1445,17 +1445,17 @@ namespace Microsoft.FSharp.Collections this.StopFurtherProcessing pipeIdx else this.State <- this.State + 1 - Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) + Unchecked.defaultof<_> (* return value unsed in Fold context *) }) [] let inline tryLast (source :ISeq<'T>) : 'T option = - source.ForEach (fun _ -> + source.Fold (fun _ -> upcast { new FolderWithCleanup<'T,option<'T>,Values>(None,Values(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.State._1 then this.State._1 <- false this.State._2 <- value - Unchecked.defaultof<_> (* return value unsed in ForEach context *) + Unchecked.defaultof<_> (* return value unsed in Fold context *) override this.OnComplete _ = if not this.State._1 then this.Result <- Some this.State._2 diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 45efa99bd62..a98f747e066 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -94,7 +94,7 @@ namespace Microsoft.FSharp.Collections /// 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 ForEach function. + /// the Fold function. [] type Folder<'T,'Result,'State> = inherit ConsumerWithState<'T,'T,'State> @@ -128,7 +128,7 @@ namespace Microsoft.FSharp.Collections type ISeq<'T> = inherit System.Collections.Generic.IEnumerable<'T> abstract member Compose : SeqFactory<'T,'U> -> ISeq<'U> - abstract member ForEach<'Result,'State> : f:(PipeIdx->Folder<'T,'Result,'State>) -> 'Result + abstract member Fold<'Result,'State> : f:(PipeIdx->Folder<'T,'Result,'State>) -> 'Result open Core From 35abb63af04328ff392c894e5cff026664d2f83b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 20 Dec 2016 19:36:38 +1100 Subject: [PATCH 265/286] Removed PipeIdx from SeqFactory - Made management of it part of the ISeq classes - Removed internal Build function as well --- src/fsharp/FSharp.Core/seqcomposer.fs | 95 ++++++++++++-------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 2 - 2 files changed, 44 insertions(+), 53 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 93ca0b3bc78..35ea80a434c 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -140,13 +140,8 @@ namespace Microsoft.FSharp.Collections [] type SeqFactory<'T,'U> () = - abstract PipeIdx : PipeIdx abstract Create<'V> : IOutOfBand -> PipeIdx -> Consumer<'U,'V> -> Consumer<'T,'V> - default __.PipeIdx = 1 - - member this.Build outOfBand next = this.Create outOfBand 1 next - type ISeq<'T> = inherit IEnumerable<'T> abstract member Compose<'U> : (SeqFactory<'T,'U>) -> ISeq<'U> @@ -169,17 +164,17 @@ namespace Microsoft.FSharp.Collections let inline enumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline outOfBand (t:#IOutOfBand) : IOutOfBand = (# "" t : IOutOfBand #) - type ComposedFactory<'T,'U,'V> private (first:SeqFactory<'T,'U>, second:SeqFactory<'U,'V>, secondPipeIdx:PipeIdx) = - inherit SeqFactory<'T,'V>() + let createFold (factory:SeqFactory<_,_>) (folder:Folder<_,_,_>) pipeIdx = + factory.Create (Upcast.outOfBand folder) pipeIdx folder - override __.PipeIdx = - secondPipeIdx + type ComposedFactory<'T,'U,'V> private (first:SeqFactory<'T,'U>, second:SeqFactory<'U,'V>) = + inherit SeqFactory<'T,'V>() override this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'V,'W>) : Consumer<'T,'W> = - first.Create outOfBand pipeIdx (second.Create outOfBand secondPipeIdx next) + first.Create outOfBand (pipeIdx-1) (second.Create outOfBand pipeIdx next) static member Combine (first:SeqFactory<'T,'U>) (second:SeqFactory<'U,'V>) : SeqFactory<'T,'V> = - upcast ComposedFactory(first, second, first.PipeIdx+1) + upcast ComposedFactory(first, second) and IdentityFactory<'T> () = inherit SeqFactory<'T,'T> () @@ -275,10 +270,10 @@ namespace Microsoft.FSharp.Collections idx <- idx + 1 - let execute (f:PipeIdx->Folder<'U,'Result,'State>) (current:SeqFactory<'T,'U>) (executeOn:#IIterate<'T>) = + let execute (f:PipeIdx->Folder<'U,'Result,'State>) (current:SeqFactory<'T,'U>) pipeIdx (executeOn:#IIterate<'T>) = let mutable stopTailCall = () - let result = f (current.PipeIdx+1) - let consumer = current.Build (Upcast.outOfBand result) result + let result = f (pipeIdx+1) + let consumer = createFold current result pipeIdx try executeOn.Iterate result consumer consumer.ChainComplete (&stopTailCall, result.HaltedIdx) @@ -382,20 +377,20 @@ namespace Microsoft.FSharp.Collections let mutable stopTailCall = () (seqComponent).ChainDispose (&stopTailCall) - and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqFactory<'T,'U>) = + and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqFactory<'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(), current.Build (Upcast.outOfBand result) result, result)) + Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), createFold current result pipeIdx, result)) interface ISeq<'U> with member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(enumerable, ComposedFactory.Combine current next)) + 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 (Fold.enumerable enumerable) + Fold.execute f current pipeIdx (Fold.enumerable enumerable) and EnumerableThin<'T>(enumerable:IEnumerable<'T>) = inherit EnumerableBase<'T>() @@ -405,7 +400,7 @@ namespace Microsoft.FSharp.Collections interface ISeq<'T> with member __.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (new Enumerable<'T,'U>(enumerable, next)) + 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) @@ -456,11 +451,11 @@ namespace Microsoft.FSharp.Collections Upcast.enumerator (new ConcatEnumerator<_,_> (sources |> List.rev)) override this.Append source = - Upcast.seq (AppendEnumerable (source :: sources)) + Upcast.seq (AppendEnumerable (source::sources)) interface ISeq<'T> with member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable<'T,'V>(this, next)) + 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) @@ -474,13 +469,13 @@ namespace Microsoft.FSharp.Collections interface ISeq<'T> with member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable<'T,'V>(this, next)) + 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)) + Upcast.seq (Enumerable(enumerable, current, 1)) module EmptyEnumerable = type Enumerable<'T> () = @@ -497,13 +492,11 @@ namespace Microsoft.FSharp.Collections interface ISeq<'T> with member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable.Enumerable<'T,'V>(this, next)) + 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>(delayedArray:unit->array<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) @@ -537,23 +530,23 @@ namespace Microsoft.FSharp.Collections initMoveNext () moveNext () - type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqFactory<'T,'U>) = + type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqFactory<'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>(delayedArray, current.Build (Upcast.outOfBand result) result, result)) + Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, createFold current result pipeIdx, result)) interface ISeq<'U> with member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next)) + Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next, 1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - Fold.execute f current (Fold.Array (delayedArray ())) + Fold.execute f current pipeIdx (Fold.Array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:SeqFactory<'T,'U>) = - Upcast.seq (Enumerable(delayedArray, current)) + Upcast.seq (Enumerable(delayedArray, current, 1)) let create (array:array<'T>) (current:SeqFactory<'T,'U>) = createDelayed (fun () -> array) current @@ -589,23 +582,23 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext list - type Enumerable<'T,'U>(alist:list<'T>, current:SeqFactory<'T,'U>) = + type Enumerable<'T,'U>(alist:list<'T>, current:SeqFactory<'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, current.Build (Upcast.outOfBand result) result, result)) + Upcast.enumerator (new Enumerator<'T,'U>(alist, createFold current result pipeIdx, result)) interface ISeq<'U> with member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next)) + Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next, pipeIdx+1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - Fold.execute f current (Fold.List alist) + Fold.execute f current pipeIdx (Fold.List alist) let create alist current = - Upcast.seq (Enumerable(alist, current)) + Upcast.seq (Enumerable(alist, current, 1)) module Unfold = type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, result:Result<'U>) = @@ -628,20 +621,20 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:SeqFactory<'T,'U>) = + type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:SeqFactory<'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, current.Build (Upcast.outOfBand result) result, result)) + Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, createFold current result pipeIdx, result)) interface ISeq<'U> with member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next)) + Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next, pipeIdx+1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - Fold.execute f current (Fold.unfold (generator, state)) + Fold.execute f current pipeIdx (Fold.unfold (generator, state)) module Init = // The original implementation of "init" delayed the calculation of Current, and so it was possible @@ -703,21 +696,21 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqFactory<'T,'U>) = + type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqFactory<'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, current.Build (Upcast.outOfBand result) result, result)) + Upcast.enumerator (new Enumerator<'T,'U>(count, f, createFold current result pipeIdx, result)) interface ISeq<'U> with member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next)) + Upcast.seq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next, pipeIdx+1)) member this.Fold<'Result,'State> (createResult:PipeIdx->Folder<'U,'Result,'State>) = let terminatingIdx = getTerminatingIdx count - Fold.execute createResult current (Fold.init (f, terminatingIdx)) + Fold.execute createResult current pipeIdx (Fold.init (f, terminatingIdx)) let upto lastOption f = match lastOption with @@ -769,7 +762,7 @@ namespace Microsoft.FSharp.Collections interface System.IDisposable with member x.Dispose() = () } - type EnumerableDecider<'T>(count:Nullable, f:int->'T) = + type EnumerableDecider<'T>(count:Nullable, f:int->'T, pipeIdx:PipeIdx) = inherit Enumerable.EnumerableBase<'T>() interface IEnumerable<'T> with @@ -781,7 +774,7 @@ namespace Microsoft.FSharp.Collections interface ISeq<'T> with member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = - Upcast.seq (Enumerable<'T,'V>(count, f, next)) + 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)) @@ -790,8 +783,8 @@ namespace Microsoft.FSharp.Collections let ofSeq (source:seq<'T>) : ISeq<'T> = match source with | :? ISeq<'T> as s -> s - | :? array<'T> as a -> Upcast.seq (Array.Enumerable((fun () -> a), IdentityFactory.Instance)) - | :? list<'T> as a -> Upcast.seq (List.Enumerable(a, IdentityFactory.Instance)) + | :? array<'T> as a -> Upcast.seq (Array.Enumerable((fun () -> a), IdentityFactory.Instance, 1)) + | :? list<'T> as a -> Upcast.seq (List.Enumerable(a, IdentityFactory.Instance, 1)) | null -> nullArg "source" | _ -> Upcast.seq (Enumerable.EnumerableThin<'T> source) @@ -878,17 +871,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)) + 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)) + 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)) + Upcast.seq (new Init.EnumerableDecider<'T>(Nullable count, f, 1)) [] let iter f (source:ISeq<'T>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index a98f747e066..aad255f5d67 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -121,8 +121,6 @@ namespace Microsoft.FSharp.Collections [] type SeqFactory<'T,'U> = new : unit -> SeqFactory<'T,'U> - abstract PipeIdx : PipeIdx - default PipeIdx : PipeIdx abstract member Create : IOutOfBand -> PipeIdx -> Consumer<'U,'V> -> Consumer<'T,'V> type ISeq<'T> = From 273db07a4b8be161cb89a8798597fc9d8179e358 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 20 Dec 2016 19:49:05 +1100 Subject: [PATCH 266/286] Made Fold iterators more consistent --- src/fsharp/FSharp.Core/seqcomposer.fs | 56 +++++++++++++++++---------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 35ea80a434c..5e76b463963 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -221,33 +221,39 @@ namespace Microsoft.FSharp.Collections type Array<'T> (array:array<'T>) = interface IIterate<'T> with member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = - let mutable idx = 0 - while (outOfBand.HaltedIdx = 0) && (idx < array.Length) do - consumer.ProcessNext array.[idx] |> ignore - idx <- idx + 1 + 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 List<'T> (alist:list<'T>) = interface IIterate<'T> with member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = let rec iterate lst = - match outOfBand.HaltedIdx, lst with - | 0, hd :: tl -> + match lst with + | hd :: tl -> consumer.ProcessNext hd |> ignore - iterate tl + 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:Consumer<'T,'U>) = + let generator = generator let rec iterate current = - match outOfBand.HaltedIdx, generator current with - | 0, Some (item, next) -> + match generator current with + | Some (item, next) -> consumer.ProcessNext item |> ignore - iterate next + if outOfBand.HaltedIdx = 0 then + iterate next | _ -> () - iterate state let makeIsSkipping (consumer:Consumer<'T,'U>) = @@ -255,20 +261,30 @@ namespace Microsoft.FSharp.Collections | :? ISkipping as skip -> skip.Skipping | _ -> fun () -> false - type init<'T> (f, terminatingIdx:int) = + [] + type init<'T> (f:int->'T, terminatingIdx:int) = interface IIterate<'T> with member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = - let mutable idx = -1 + let terminatingIdx =terminatingIdx + let f = f + let isSkipping = makeIsSkipping consumer - let mutable maybeSkipping = true - while (outOfBand.HaltedIdx = 0) && (idx < terminatingIdx) do - if maybeSkipping then - maybeSkipping <- isSkipping () + let rec skip idx = + if idx >= terminatingIdx || outOfBand.HaltedIdx <> 0 then + terminatingIdx + elif isSkipping () then + skip (idx+1) + else + idx - if not maybeSkipping then - consumer.ProcessNext (f (idx+1)) |> ignore + let rec iterate idx = + if idx < terminatingIdx then + consumer.ProcessNext (f idx) |> ignore + if outOfBand.HaltedIdx = 0 then + iterate (idx+1) - idx <- idx + 1 + skip 0 + |> iterate let execute (f:PipeIdx->Folder<'U,'Result,'State>) (current:SeqFactory<'T,'U>) pipeIdx (executeOn:#IIterate<'T>) = let mutable stopTailCall = () From 5f325483fc278c6bca19925a4a73a7ade2b0ad78 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 24 Dec 2016 14:04:13 +1100 Subject: [PATCH 267/286] Renamed Consumer to Activity - didn't really consume anything - removed helper classes to slightly decrease surface area --- src/fsharp/FSharp.Core/seqcomposer.fs | 154 ++++++++++++------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 54 ++++----- 2 files changed, 92 insertions(+), 116 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 5e76b463963..f61e5c96486 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -27,7 +27,6 @@ namespace Microsoft.FSharp.Collections type Values<'a,'b> = val mutable _1 : 'a val mutable _2 : 'b - new (a:'a, b: 'b) = { _1 = a; _2 = b } [] @@ -35,7 +34,6 @@ namespace Microsoft.FSharp.Collections 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 @@ -44,37 +42,35 @@ namespace Microsoft.FSharp.Collections abstract StopFurtherProcessing : PipeIdx -> unit [] - type Consumer() = + type Activity() = abstract ChainComplete : stopTailCall:byref * PipeIdx -> unit abstract ChainDispose : stopTailCall:byref -> unit [] - type Consumer<'T,'U> () = - inherit Consumer() - + type Activity<'T,'U> () = + inherit Activity() abstract ProcessNext : input:'T -> bool - override this.ChainComplete (_,_) = () override this.ChainDispose _ = () [] - type ConsumerWithState<'T,'U,'State> = - inherit Consumer<'T,'U> - + type Activity<'T,'U,'State> = + inherit Activity<'T,'U> + val mutable State : 'State - + new (initState) = { State = initState } [] - type ConsumerChainedWithState<'T,'U,'State> = - inherit ConsumerWithState<'T,'U,'State> - - val private Next : Consumer - - new (next:Consumer, initState) = { - inherit ConsumerWithState<'T,'U,'State> (initState) + type ActivityChained<'T,'U,'State> = + inherit Activity<'T,'U,'State> + + val private Next : Activity + + new (next:Activity, initState:'State) = { + inherit Activity<'T,'U,'State> (initState) Next = next } @@ -84,12 +80,8 @@ namespace Microsoft.FSharp.Collections this.Next.ChainDispose (&stopTailCall) [] - type ConsumerChained<'T,'U>(next:Consumer) = - inherit ConsumerChainedWithState<'T,'U,NoValue>(next, Unchecked.defaultof) - - [] - type ConsumerChainedWithStateAndCleanup<'T,'U,'State> (next, inititalState) = - inherit ConsumerChainedWithState<'T,'U,'State>(next, inititalState) + type ActivityChainedWithPostProcessing<'T,'U,'State> (next:Activity, inititalState:'State) = + inherit ActivityChained<'T,'U,'State>(next, inititalState) abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit @@ -101,13 +93,9 @@ namespace Microsoft.FSharp.Collections try this.OnDispose () finally next.ChainDispose (&stopTailCall) - [] - type ConsumerChainedWithCleanup<'T,'U>(next:Consumer) = - inherit ConsumerChainedWithStateAndCleanup<'T,'U,NoValue>(next, Unchecked.defaultof) - [] type Folder<'T,'Result,'State> = - inherit ConsumerWithState<'T,'T,'State> + inherit Activity<'T,'T,'State> val mutable Result : 'Result val mutable HaltedIdx : int @@ -117,7 +105,7 @@ namespace Microsoft.FSharp.Collections member this.StopFurtherProcessing pipeIdx = this.StopFurtherProcessing pipeIdx new (initalResult,initState) = { - inherit ConsumerWithState<'T,'T,'State>(initState) + inherit Activity<'T,'T,'State>(initState) HaltedIdx = 0 Result = initalResult } @@ -127,7 +115,7 @@ namespace Microsoft.FSharp.Collections inherit Folder<'T,'Result,NoValue>(initResult,Unchecked.defaultof) [] - type FolderWithCleanup<'T,'Result,'State>(initResult,initState) = + type FolderWithPostProcessing<'T,'Result,'State>(initResult,initState) = inherit Folder<'T,'Result,'State>(initResult,initState) abstract OnComplete : PipeIdx -> unit @@ -140,7 +128,7 @@ namespace Microsoft.FSharp.Collections [] type SeqFactory<'T,'U> () = - abstract Create<'V> : IOutOfBand -> PipeIdx -> Consumer<'U,'V> -> Consumer<'T,'V> + abstract Create<'V> : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> type ISeq<'T> = inherit IEnumerable<'T> @@ -170,7 +158,7 @@ namespace Microsoft.FSharp.Collections type ComposedFactory<'T,'U,'V> private (first:SeqFactory<'T,'U>, second:SeqFactory<'U,'V>) = inherit SeqFactory<'T,'V>() - override this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Consumer<'V,'W>) : Consumer<'T,'W> = + override this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = first.Create outOfBand (pipeIdx-1) (second.Create outOfBand pipeIdx next) static member Combine (first:SeqFactory<'T,'U>) (second:SeqFactory<'U,'V>) : SeqFactory<'T,'V> = @@ -179,7 +167,7 @@ namespace Microsoft.FSharp.Collections and IdentityFactory<'T> () = inherit SeqFactory<'T,'T> () static let singleton : SeqFactory<'T,'T> = upcast (IdentityFactory<'T>()) - override __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Consumer<'T,'V>) : Consumer<'T,'V> = next + override __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next static member Instance = singleton and ISkipping = @@ -203,12 +191,12 @@ namespace Microsoft.FSharp.Collections module Fold = type IIterate<'T> = - abstract Iterate<'U,'Result,'State> : outOfBand:Folder<'U,'Result,'State> -> consumer:Consumer<'T,'U> -> unit + 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:Consumer<'T,'U>) = + member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = use enumerator = enumerable.GetEnumerator () let rec iterate () = if enumerator.MoveNext () then @@ -220,7 +208,7 @@ namespace Microsoft.FSharp.Collections [] type Array<'T> (array:array<'T>) = interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = + member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = let array = array let rec iterate idx = if idx < array.Length then @@ -232,7 +220,7 @@ namespace Microsoft.FSharp.Collections [] type List<'T> (alist:list<'T>) = interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = + member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = let rec iterate lst = match lst with | hd :: tl -> @@ -245,7 +233,7 @@ namespace Microsoft.FSharp.Collections [] type unfold<'S,'T> (generator:'S->option<'T*'S>, state:'S) = interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = + member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = let generator = generator let rec iterate current = match generator current with @@ -256,7 +244,7 @@ namespace Microsoft.FSharp.Collections | _ -> () iterate state - let makeIsSkipping (consumer:Consumer<'T,'U>) = + let makeIsSkipping (consumer:Activity<'T,'U>) = match box consumer with | :? ISkipping as skip -> skip.Skipping | _ -> fun () -> false @@ -264,7 +252,7 @@ namespace Microsoft.FSharp.Collections [] type init<'T> (f:int->'T, terminatingIdx:int) = interface IIterate<'T> with - member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Consumer<'T,'U>) = + member __.Iterate (outOfBand:Folder<'U,'Result,'State>) (consumer:Activity<'T,'U>) = let terminatingIdx =terminatingIdx let f = f @@ -324,7 +312,7 @@ namespace Microsoft.FSharp.Collections static member Element = element [] - type EnumeratorBase<'T>(result:Result<'T>, seqComponent:Consumer) = + type EnumeratorBase<'T>(result:Result<'T>, seqComponent:Activity) = interface IDisposable with member __.Dispose() : unit = let mutable stopTailCall = () @@ -365,7 +353,7 @@ namespace Microsoft.FSharp.Collections member __.Compose _ = derivedClassShouldImplement () member __.Fold _ = derivedClassShouldImplement () - and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:Activity<'T,'U>, result:Result<'U>) = inherit EnumeratorBase<'U>(result, seqComponent) let rec moveNext () = @@ -514,7 +502,7 @@ namespace Microsoft.FSharp.Collections Fold.executeThin f (Fold.enumerable this) module Array = - type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:Activity<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable idx = 0 @@ -574,7 +562,7 @@ namespace Microsoft.FSharp.Collections create array IdentityFactory.Instance module List = - type Enumerator<'T,'U>(alist:list<'T>, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U>(alist:list<'T>, seqComponent:Activity<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable list = alist @@ -617,7 +605,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (Enumerable(alist, current, 1)) module Unfold = - type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U,'State>(generator:'State->option<'T*'State>, state:'State, seqComponent:Activity<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let mutable current = state @@ -672,7 +660,7 @@ namespace Microsoft.FSharp.Collections else System.Int32.MaxValue - type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:Consumer<'T,'U>, result:Result<'U>) = + type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:Activity<'T,'U>, result:Result<'U>) = inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let isSkipping = @@ -810,7 +798,7 @@ namespace Microsoft.FSharp.Collections and ^T:(static member (+) : ^T * ^T -> ^T) and ^T:(static member DivideByInt : ^T * int -> ^T) = source.Fold (fun _ -> - upcast { new FolderWithCleanup< ^T, ^T, int> (LanguagePrimitives.GenericZero, 0) with + 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 @@ -828,7 +816,7 @@ namespace Microsoft.FSharp.Collections and ^U:(static member (+) : ^U * ^U -> ^U) and ^U:(static member DivideByInt : ^U * int -> ^U) = source.Fold (fun _ -> - upcast { new FolderWithCleanup<'T,'U, int>(LanguagePrimitives.GenericZero, 0) with + 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 @@ -846,7 +834,7 @@ namespace Microsoft.FSharp.Collections [] let inline exactlyOne errorString (source : ISeq<'T>) : 'T = source.Fold (fun pipeIdx -> - upcast { new FolderWithCleanup<'T,'T,Values>(Unchecked.defaultof<'T>, Values(true, false)) with + 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 @@ -874,7 +862,7 @@ namespace Microsoft.FSharp.Collections [] 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 FolderWithCleanup<_,'State,IEnumerator<'T2>>(state,source2.GetEnumerator()) with + upcast { new FolderWithPostProcessing<_,'State,IEnumerator<'T2>>(state,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then self.Result <- folder self.Result value self.State.Current @@ -911,7 +899,7 @@ namespace Microsoft.FSharp.Collections [] let inline iter2 (f:'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = source1.Fold (fun pipeIdx -> - upcast { new FolderWithCleanup<'T,NoValue,IEnumerator<'U>> (Unchecked.defaultof<_>,source2.GetEnumerator()) with + upcast { new FolderWithPostProcessing<'T,NoValue,IEnumerator<'U>> (Unchecked.defaultof<_>,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then f value self.State.Current @@ -926,7 +914,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 FolderWithCleanup<'T,NoValue,Values>>(Unchecked.defaultof<_>,Values<_,_>(-1,source2.GetEnumerator())) with + upcast { new FolderWithPostProcessing<'T,NoValue,Values>>(Unchecked.defaultof<_>,Values<_,_>(-1,source2.GetEnumerator())) with override self.ProcessNext value = if self.State._2.MoveNext() then f self.State._1 value self.State._2.Current @@ -962,7 +950,7 @@ namespace Microsoft.FSharp.Collections let inline except (itemsToExclude: seq<'T>) (source:ISeq<'T>) : ISeq<'T> when 'T:equality = source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,Lazy>> + upcast { new ActivityChained<'T,'V,Lazy>> (next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = if this.State.Value.Add input then TailCall.avoid (next.ProcessNext input) @@ -981,7 +969,7 @@ namespace Microsoft.FSharp.Collections [] let exists2 (predicate:'T->'U->bool) (source1: ISeq<'T>) (source2: ISeq<'U>) : bool = source1.Fold (fun pipeIdx -> - upcast { new FolderWithCleanup<'T,bool,IEnumerator<'U>>(false,source2.GetEnumerator()) with + upcast { new FolderWithPostProcessing<'T,bool,IEnumerator<'U>>(false,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then if predicate value self.State.Current then @@ -1017,7 +1005,7 @@ namespace Microsoft.FSharp.Collections [] let inline forall2 predicate (source1:ISeq<'T>) (source2:ISeq<'U>) : bool = source1.Fold (fun pipeIdx -> - upcast { new FolderWithCleanup<'T,bool,IEnumerator<'U>>(true,source2.GetEnumerator()) with + upcast { new FolderWithPostProcessing<'T,bool,IEnumerator<'U>>(true,source2.GetEnumerator()) with override self.ProcessNext value = if self.State.MoveNext() then if not (predicate value self.State.Current) then @@ -1034,7 +1022,7 @@ namespace Microsoft.FSharp.Collections let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = - upcast { new ConsumerChained<'T,'V>(next) with + upcast { new ActivityChained<'T,'V,NoValue>(next,Unchecked.defaultof) with override __.ProcessNext input = if f input then TailCall.avoid (next.ProcessNext input) else false } } @@ -1043,7 +1031,7 @@ namespace Microsoft.FSharp.Collections let inline map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = source.Compose { new SeqFactory<'T,'U>() with override __.Create _ _ next = - upcast { new ConsumerChained<'T,'V>(next) with + upcast { new ActivityChained<'T,'V,NoValue>(next,Unchecked.defaultof) with override __.ProcessNext input = TailCall.avoid (next.ProcessNext (f input)) } } @@ -1051,7 +1039,7 @@ namespace Microsoft.FSharp.Collections let inline mapi f (source:ISeq<_>) = source.Compose { new SeqFactory<'T,'U>() with override __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,int>(next, -1) with + upcast { new ActivityChained<'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)) } } @@ -1059,8 +1047,8 @@ namespace Microsoft.FSharp.Collections [] let inline map2<'First,'Second,'U> (map:'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = source1.Compose { new SeqFactory<'First,'U>() with - override __.Create<'V> outOfBand pipeIdx next = - upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, IEnumerator<'Second>>(next, (source2.GetEnumerator ())) with + override __.Create outOfBand pipeIdx (next:Activity<'U,'V>) = + upcast { new ActivityChainedWithPostProcessing<'First,'V, IEnumerator<'Second>>(next, (source2.GetEnumerator ())) with override self.ProcessNext input = if self.State.MoveNext () then TailCall.avoid (next.ProcessNext (map input self.State.Current)) @@ -1074,7 +1062,7 @@ namespace Microsoft.FSharp.Collections let inline mapi2<'First,'Second,'U> (map:int -> 'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = source1.Compose { new SeqFactory<'First,'U>() with override __.Create<'V> outOfBand pipeIdx next = - upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values>> + upcast { new ActivityChainedWithPostProcessing<'First,'V, Values>> (next, Values<_,_>(-1, source2.GetEnumerator ())) with override self.ProcessNext input = if self.State._2.MoveNext () then @@ -1091,7 +1079,7 @@ namespace Microsoft.FSharp.Collections (map:'First->'Second->'Third->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) (source3:ISeq<'Third>) : ISeq<'U> = source1.Compose { new SeqFactory<'First,'U>() with override __.Create<'V> outOfBand pipeIdx next = - upcast { new ConsumerChainedWithStateAndCleanup<'First,'V, Values,IEnumerator<'Third>>> + upcast { new ActivityChainedWithPostProcessing<'First,'V, Values,IEnumerator<'Third>>> (next, Values<_,_>(source2.GetEnumerator(),source3.GetEnumerator())) with override self.ProcessNext input = if self.State._1.MoveNext() && self.State._2.MoveNext () then @@ -1108,7 +1096,7 @@ namespace Microsoft.FSharp.Collections [] let inline compareWith (f:'T -> 'T -> int) (source1 :ISeq<'T>) (source2:ISeq<'T>) : int = source1.Fold (fun pipeIdx -> - upcast { new FolderWithCleanup<'T,int,IEnumerator<'T>>(0,source2.GetEnumerator()) with + upcast { new FolderWithPostProcessing<'T,int,IEnumerator<'T>>(0,source2.GetEnumerator()) with override self.ProcessNext value = if not (self.State.MoveNext()) then self.Result <- 1 @@ -1128,7 +1116,7 @@ namespace Microsoft.FSharp.Collections let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = source.Compose { new SeqFactory<'T,'U>() with override __.Create _ _ next = - upcast { new ConsumerChained<'T,'V>(next) with + upcast { new ActivityChained<'T,'V,NoValue>(next,Unchecked.defaultof) with override __.ProcessNext input = match f input with | Some value -> TailCall.avoid (next.ProcessNext value) @@ -1138,7 +1126,7 @@ namespace Microsoft.FSharp.Collections let inline distinct (source:ISeq<'T>) : ISeq<'T> when 'T:equality = source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,HashSet<'T>> + upcast { new ActivityChained<'T,'V,HashSet<'T>> (next,(HashSet<'T>(HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = if this.State.Add input then TailCall.avoid (next.ProcessNext input) @@ -1148,7 +1136,7 @@ namespace Microsoft.FSharp.Collections let inline distinctBy (keyf:'T->'Key) (source:ISeq<'T>) :ISeq<'T> when 'Key:equality = source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,HashSet<'Key>> + upcast { new ActivityChained<'T,'V,HashSet<'Key>> (next,(HashSet<'Key>(HashIdentity.Structural<'Key>))) with override this.ProcessNext (input:'T) : bool = if this.State.Add (keyf input) then TailCall.avoid (next.ProcessNext input) @@ -1157,7 +1145,7 @@ namespace Microsoft.FSharp.Collections [] let inline max (source: ISeq<'T>) : 'T when 'T:comparison = source.Fold (fun _ -> - upcast { new FolderWithCleanup<'T,'T,bool>(Unchecked.defaultof<'T>,true) with + upcast { new FolderWithPostProcessing<'T,'T,bool>(Unchecked.defaultof<'T>,true) with override this.ProcessNext value = if this.State then this.State <- false @@ -1174,7 +1162,7 @@ namespace Microsoft.FSharp.Collections [] let inline maxBy (f :'T -> 'U) (source: ISeq<'T>) : 'T when 'U:comparison = source.Fold (fun _ -> - upcast { new FolderWithCleanup<'T,'T,Values>(Unchecked.defaultof<'T>,Values<_,_>(true,Unchecked.defaultof<'U>)) with + 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 -> @@ -1195,7 +1183,7 @@ namespace Microsoft.FSharp.Collections [] let inline min (source: ISeq< 'T>) : 'T when 'T:comparison = source.Fold (fun _ -> - upcast { new FolderWithCleanup<'T,'T,bool>(Unchecked.defaultof<'T>,true) with + upcast { new FolderWithPostProcessing<'T,'T,bool>(Unchecked.defaultof<'T>,true) with override this.ProcessNext value = if this.State then this.State <- false @@ -1212,7 +1200,7 @@ namespace Microsoft.FSharp.Collections [] let inline minBy (f : 'T -> 'U) (source: ISeq<'T>) : 'T = source.Fold (fun _ -> - upcast { new FolderWithCleanup<'T,'T,Values>(Unchecked.defaultof<'T>,Values<_,_>(true,Unchecked.defaultof< 'U>)) with + 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 -> @@ -1234,7 +1222,7 @@ namespace Microsoft.FSharp.Collections let inline pairwise (source:ISeq<'T>) : ISeq<'T * 'T> = source.Compose { new SeqFactory<'T,'T * 'T>() with override __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'U,Values> + upcast { new ActivityChained<'T,'U,Values> ( next , Values ((* isFirst = _1*) true @@ -1254,7 +1242,7 @@ namespace Microsoft.FSharp.Collections [] let inline reduce (f:'T->'T->'T) (source : ISeq<'T>) : 'T = source.Fold (fun _ -> - upcast { new FolderWithCleanup<'T,'T,bool>(Unchecked.defaultof<'T>,true) with + upcast { new FolderWithPostProcessing<'T,'T,bool>(Unchecked.defaultof<'T>,true) with override this.ProcessNext value = if this.State then this.State <- false @@ -1272,7 +1260,7 @@ namespace Microsoft.FSharp.Collections let inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = source.Compose { new SeqFactory<'T,'State>() with override __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,'State>(next, initialState) with + upcast { new ActivityChained<'T,'V,'State>(next, initialState) with override this.ProcessNext (input:'T) : bool = this.State <- folder this.State input TailCall.avoid (next.ProcessNext this.State) } } @@ -1283,7 +1271,7 @@ namespace Microsoft.FSharp.Collections source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = upcast { - new ConsumerChainedWithStateAndCleanup<'T,'U,int>(next,(*count*)0) with + new ActivityChainedWithPostProcessing<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = if (*count*) self.State < skipCount then @@ -1301,7 +1289,7 @@ namespace Microsoft.FSharp.Collections interface ISkipping with member self.Skipping () = - let self = self :?> ConsumerChainedWithState<'T,'U,int> + let self = self :?> ActivityChained<'T,'U,int> if (*count*) self.State < skipCount then self.State <- self.State + 1 true @@ -1313,7 +1301,7 @@ namespace Microsoft.FSharp.Collections let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = - upcast { new ConsumerChainedWithState<'T,'V,bool>(next,true) with + upcast { new ActivityChained<'T,'V,bool>(next,true) with override self.ProcessNext (input:'T) : bool = if self.State (*skip*) then self.State <- predicate input @@ -1349,7 +1337,7 @@ namespace Microsoft.FSharp.Collections source.Compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipelineIdx next = upcast { - new ConsumerChainedWithStateAndCleanup<'T,'U,int>(next,(*count*)0) with + new ActivityChainedWithPostProcessing<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = if (*count*) self.State < takeCount then self.State <- self.State + 1 @@ -1371,7 +1359,7 @@ namespace Microsoft.FSharp.Collections let inline takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source.Compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipeIdx next = - upcast { new ConsumerChained<'T,'V>(next) with + upcast { new ActivityChained<'T,'V,NoValue>(next,Unchecked.defaultof) with override __.ProcessNext (input:'T) : bool = if predicate input then TailCall.avoid (next.ProcessNext input) @@ -1384,7 +1372,7 @@ namespace Microsoft.FSharp.Collections let inline tail errorString (source:ISeq<'T>) :ISeq<'T> = source.Compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = - upcast { new ConsumerChainedWithStateAndCleanup<'T,'V,bool>(next,(*first*) true) with + upcast { new ActivityChainedWithPostProcessing<'T,'V,bool>(next,(*first*) true) with override self.ProcessNext (input:'T) : bool = if (*first*) self.State then self.State <- false @@ -1402,7 +1390,7 @@ namespace Microsoft.FSharp.Collections source.Compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipeIdx next = upcast { - new ConsumerChainedWithState<'T,'U,int>(next,(*count*)0) with + new ActivityChained<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = if (*count*) self.State < truncateCount then self.State <- self.State + 1 @@ -1459,7 +1447,7 @@ namespace Microsoft.FSharp.Collections [] let inline tryLast (source :ISeq<'T>) : 'T option = source.Fold (fun _ -> - upcast { new FolderWithCleanup<'T,option<'T>,Values>(None,Values(true, Unchecked.defaultof<'T>)) with + upcast { new FolderWithPostProcessing<'T,option<'T>,Values>(None,Values(true, Unchecked.defaultof<'T>)) with override this.ProcessNext value = if this.State._1 then this.State._1 <- false @@ -1475,7 +1463,7 @@ namespace Microsoft.FSharp.Collections source.Compose { new SeqFactory<'T,'T[]>() with member __.Create outOfBand pipeIdx next = upcast { - new ConsumerChainedWithState<'T,'U,Values<'T[],int,int>> + new ActivityChained<'T,'U,Values<'T[],int,int>> ( next , Values<'T[],int,int> ((*circularBuffer = _1 *) Array.zeroCreateUnchecked windowSize diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index aad255f5d67..3e556aed0a1 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -38,12 +38,10 @@ namespace Microsoft.FSharp.Collections type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit - /// ICompletionChain is used to correctly handle cleaning up of the pipeline. A - /// base implementation is provided in Consumer, and should not be overwritten. Consumer - /// provides it's own OnComplete and OnDispose function which should be used to handle - /// a particular consumers cleanup. + /// 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 Consumer = + 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 @@ -54,50 +52,40 @@ namespace Microsoft.FSharp.Collections /// after the enumeration has completed. abstract ChainDispose : stopTailCall:byref -> unit - /// Consumer is the base class of all elements within the pipeline + /// Activity is the base class of all elements within the pipeline [] - type Consumer<'T,'U> = - inherit Consumer - new : unit -> Consumer<'T,'U> + type Activity<'T,'U> = + inherit Activity + new : unit -> Activity<'T,'U> abstract member ProcessNext : input:'T -> bool [] - type ConsumerWithState<'T,'U,'State> = - inherit Consumer<'T,'U> + type Activity<'T,'U,'State> = + inherit Activity<'T,'U> val mutable State : 'State - new : 'State -> ConsumerWithState<'T,'U,'State> + new : 'State -> Activity<'T,'U,'State> [] - type ConsumerChainedWithState<'T,'U,'State> = - inherit ConsumerWithState<'T,'U,'State> - val private Next : Consumer - new : next:Consumer * 'State -> ConsumerChainedWithState<'T,'U,'State> + type ActivityChained<'T,'U,'State> = + inherit Activity<'T,'U,'State> + val private Next : Activity + new : next:Activity * 'State -> ActivityChained<'T,'U,'State> [] - type ConsumerChained<'T,'U> = - inherit ConsumerChainedWithState<'T,'U,NoValue> - new : next:Consumer -> ConsumerChained<'T,'U> - - [] - type ConsumerChainedWithStateAndCleanup<'T,'U,'State> = - inherit ConsumerChainedWithState<'T,'U,'State> + type ActivityChainedWithPostProcessing<'T,'U,'State> = + inherit ActivityChained<'T,'U,'State> abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit - new : next:Consumer * 'State -> ConsumerChainedWithStateAndCleanup<'T,'U,'State> - - [] - type ConsumerChainedWithCleanup<'T,'U> = - inherit ConsumerChainedWithStateAndCleanup<'T,'U,NoValue> - new : next:Consumer -> ConsumerChainedWithCleanup<'T,'U> + new : next:Activity * 'State -> ActivityChainedWithPostProcessing<'T,'U,'State> /// 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 ConsumerWithState<'T,'T,'State> + inherit Activity<'T,'T,'State> new : 'Result*'State -> Folder<'T,'Result,'State> interface IOutOfBand val mutable HaltedIdx : int @@ -110,18 +98,18 @@ namespace Microsoft.FSharp.Collections new : 'Result -> Folder<'T,'Result> [] - type FolderWithCleanup<'T,'Result,'State> = + type FolderWithPostProcessing<'T,'Result,'State> = inherit Folder<'T,'Result,'State> abstract OnDispose : unit -> unit abstract OnComplete : PipeIdx -> unit - new : 'Result*'State -> FolderWithCleanup<'T,'Result,'State> + new : 'Result*'State -> FolderWithPostProcessing<'T,'Result,'State> [] type SeqFactory<'T,'U> = new : unit -> SeqFactory<'T,'U> - abstract member Create : IOutOfBand -> PipeIdx -> Consumer<'U,'V> -> Consumer<'T,'V> + abstract member Create : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> type ISeq<'T> = inherit System.Collections.Generic.IEnumerable<'T> From 3c09a0b1e9366d07c4d855bb9303f71917a4086c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 24 Dec 2016 14:55:18 +1100 Subject: [PATCH 268/286] Removed errorString argument - Moved SR.GetString code into Composer --- src/fsharp/FSharp.Core/seq.fs | 10 +++++----- src/fsharp/FSharp.Core/seqcomposer.fs | 18 +++++++++--------- src/fsharp/FSharp.Core/seqcomposer.fsi | 10 +++++----- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index e1dae6b0b7b..54f854d65c7 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -80,7 +80,7 @@ namespace Microsoft.FSharp.Collections [] let skip count (source: seq<_>) = source |> toComposer - |> Composer.skip (SR.GetString SR.notEnoughElements) count |> Upcast.enumerable + |> Composer.skip count |> Upcast.enumerable let invalidArgumnetIndex = invalidArgFmt "index" @@ -88,7 +88,7 @@ namespace Microsoft.FSharp.Collections let item i (source : seq<'T>) = if i < 0 then invalidArgInputMustBeNonNegative "index" i else source - |> toComposer |> Composer.skip (SR.GetString SR.notEnoughElements) i |> Upcast.enumerable + |> toComposer |> Composer.skip i |> Upcast.enumerable |> tryHead |> function | None -> invalidArgFmt "index" "{0}\nseq was short by 1 element" [|SR.GetString SR.notEnoughElements|] @@ -96,7 +96,7 @@ namespace Microsoft.FSharp.Collections [] let tryItem i (source:seq<'T>) = - source |> toComposer |> Composer.tryItem (SR.GetString SR.notEnoughElements) i + source |> toComposer |> Composer.tryItem i [] let nth i (source : seq<'T>) = item i source @@ -227,7 +227,7 @@ namespace Microsoft.FSharp.Collections if count < 0 then invalidArgInputMustBeNonNegative "count" count (* Note: don't create or dispose any IEnumerable if n = 0 *) if count = 0 then empty else - source |> toComposer |> Composer.take (SR.GetString SR.notEnoughElements) count |> Upcast.enumerable + source |> toComposer |> Composer.take count |> Upcast.enumerable [] let isEmpty (source : seq<'T>) = @@ -720,7 +720,7 @@ namespace Microsoft.FSharp.Collections [] let tail (source: seq<'T>) = - source |> toComposer |> Composer.tail (SR.GetString SR.notEnoughElements) |> Upcast.enumerable + source |> toComposer |> Composer.tail |> Upcast.enumerable [] let tryLast (source : seq<_>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index f61e5c96486..a2993dbdf0c 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -1267,7 +1267,7 @@ namespace Microsoft.FSharp.Collections [] - let skip (errorString:string) (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = + let skip (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = upcast { @@ -1284,7 +1284,7 @@ namespace Microsoft.FSharp.Collections if (*count*) self.State < skipCount then let x = skipCount - self.State invalidOpFmt "{0}\ntried to skip {1} {2} past the end of the seq" - [|errorString; x; (if x=1 then "element" else "elements")|] + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] override self.OnDispose () = () interface ISkipping with @@ -1333,7 +1333,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in Fold context *) }) [] - let inline take (errorString:string) (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = + let take (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = source.Compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipelineIdx next = upcast { @@ -1352,7 +1352,7 @@ namespace Microsoft.FSharp.Collections if terminatingIdx < pipelineIdx && this.State < takeCount then let x = takeCount - this.State invalidOpFmt "tried to take {0} {1} past the end of the seq" - [|errorString; x; (if x=1 then "element" else "elements")|] + [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|] override this.OnDispose () = () }} [] @@ -1369,7 +1369,7 @@ namespace Microsoft.FSharp.Collections }} [] - let inline tail errorString (source:ISeq<'T>) :ISeq<'T> = + let tail (source:ISeq<'T>) :ISeq<'T> = source.Compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = upcast { new ActivityChainedWithPostProcessing<'T,'V,bool>(next,(*first*) true) with @@ -1382,11 +1382,11 @@ namespace Microsoft.FSharp.Collections override self.OnComplete _ = if (*first*) self.State then - invalidArg "source" errorString + invalidArg "source" (SR.GetString SR.notEnoughElements) override self.OnDispose () = () }} [] - let inline truncate (truncateCount:int) (source:ISeq<'T>) : ISeq<'T> = + let truncate (truncateCount:int) (source:ISeq<'T>) : ISeq<'T> = source.Compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipeIdx next = upcast { @@ -1406,9 +1406,9 @@ namespace Microsoft.FSharp.Collections mapi (fun i x -> i,x) source [] - let tryItem (errorString:string) index (source:ISeq<'T>) = + let tryItem index (source:ISeq<'T>) = if index < 0 then None else - source |> skip errorString index |> tryHead + source |> skip index |> tryHead [] let tryPick f (source:ISeq<'T>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 3e556aed0a1..c9d70874908 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -239,7 +239,7 @@ namespace Microsoft.FSharp.Collections val inline scan : folder:('State->'T->'State) -> initialState:'State -> source:ISeq<'T> -> ISeq<'State> [] - val skip : errorString:string -> skipCount:int -> source:ISeq<'T> -> ISeq<'T> + val skip : skipCount:int -> source:ISeq<'T> -> ISeq<'T> [] val inline skipWhile : predicate:('T->bool) -> source:ISeq<'T> -> ISeq<'T> @@ -255,22 +255,22 @@ namespace Microsoft.FSharp.Collections and ^U:(static member (+) : ^U * ^U -> ^U) [] - val inline take : errorString:string -> takeCount:int -> source:ISeq<'T> -> ISeq<'T> + val take : takeCount:int -> source:ISeq<'T> -> ISeq<'T> [] val inline takeWhile : predicate:('T->bool) -> source:ISeq<'T> -> ISeq<'T> [] - val inline tail : errorString:string -> source:ISeq<'T> -> ISeq<'T> + val tail : source:ISeq<'T> -> ISeq<'T> [] - val inline truncate : truncateCount:int -> source:ISeq<'T> -> ISeq<'T> + val truncate : truncateCount:int -> source:ISeq<'T> -> ISeq<'T> [] val indexed : source: ISeq<'a> -> ISeq [] - val tryItem : errorString:string -> index:int -> source: ISeq<'T> -> 'T option + val tryItem : index:int -> source: ISeq<'T> -> 'T option [] val tryPick : f:('T -> 'U option) -> source: ISeq<'T> -> Option<'U> From 401d3e165c46601d2697b6d2a2c4635dabe8ed26 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 24 Dec 2016 15:00:35 +1100 Subject: [PATCH 269/286] better selection of inline function --- src/fsharp/FSharp.Core/seq.fs | 2 +- src/fsharp/FSharp.Core/seqcomposer.fs | 22 +++++++++++----------- src/fsharp/FSharp.Core/seqcomposer.fsi | 26 +++++++++++++------------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 54f854d65c7..666fc06519b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -734,7 +734,7 @@ namespace Microsoft.FSharp.Collections [] let exactlyOne (source : seq<_>) = - source |> toComposer |> Composer.exactlyOne (SR.GetString(SR.inputSequenceTooLong)) + source |> toComposer |> Composer.exactlyOne member this.OnComplete _ = if this.Value._1 then diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index a2993dbdf0c..08dddd8c99a 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -832,7 +832,7 @@ namespace Microsoft.FSharp.Collections let empty<'T> = EmptyEnumerable.Enumerable<'T>.Instance [] - let inline exactlyOne errorString (source : ISeq<'T>) : 'T = + 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 = @@ -848,7 +848,7 @@ namespace Microsoft.FSharp.Collections if this.State._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString elif this.State._2 then - invalidArg "source" errorString + invalidArg "source" (SR.GetString SR.inputSequenceTooLong) override this.OnDispose () = () }) [] @@ -888,7 +888,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (new Init.EnumerableDecider<'T>(Nullable count, f, 1)) [] - let iter f (source:ISeq<'T>) = + let inline iter f (source:ISeq<'T>) = source.Fold (fun _ -> upcast { new Folder<'T,NoValue> (Unchecked.defaultof) with override this.ProcessNext value = @@ -937,7 +937,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in Fold context *) }) [] - let iteri f (source:ISeq<'T>) = + let inline iteri f (source:ISeq<'T>) = source.Fold (fun _ -> { new Folder<'T,NoValue,int> (Unchecked.defaultof<_>,0) with override this.ProcessNext value = @@ -957,7 +957,7 @@ namespace Microsoft.FSharp.Collections else false }} [] - let exists f (source:ISeq<'T>) = + let inline exists f (source:ISeq<'T>) = source.Fold (fun pipeIdx -> upcast { new Folder<'T, bool> (false) with override this.ProcessNext value = @@ -967,7 +967,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in Fold context *) }) [] - let exists2 (predicate:'T->'U->bool) (source1: ISeq<'T>) (source2: ISeq<'U>) : bool = + 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 self.ProcessNext value = @@ -993,7 +993,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in Fold context *) }) [] - let forall predicate (source:ISeq<'T>) = + let inline forall predicate (source:ISeq<'T>) = source.Fold (fun pipeIdx -> upcast { new Folder<'T, bool> (true) with override this.ProcessNext value = @@ -1219,7 +1219,7 @@ namespace Microsoft.FSharp.Collections override self.OnDispose () = () }) [] - let inline pairwise (source:ISeq<'T>) : ISeq<'T * 'T> = + let pairwise (source:ISeq<'T>) : ISeq<'T*'T> = source.Compose { new SeqFactory<'T,'T * 'T>() with override __.Create _ _ next = upcast { new ActivityChained<'T,'U,Values> @@ -1411,7 +1411,7 @@ namespace Microsoft.FSharp.Collections source |> skip index |> tryHead [] - let tryPick f (source:ISeq<'T>) = + let inline tryPick f (source:ISeq<'T>) = source.Fold (fun pipeIdx -> upcast { new Folder<'T, Option<'U>> (None) with override this.ProcessNext value = @@ -1423,7 +1423,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unsed in Fold context *) }) [] - let tryFind f (source:ISeq<'T>) = + let inline tryFind f (source:ISeq<'T>) = source.Fold (fun pipeIdx -> upcast { new Folder<'T, Option<'T>> (None) with override this.ProcessNext value = @@ -1459,7 +1459,7 @@ namespace Microsoft.FSharp.Collections override self.OnDispose () = () }) [] - let inline windowed (windowSize:int) (source:ISeq<'T>) : ISeq<'T[]> = + let windowed (windowSize:int) (source:ISeq<'T>) : ISeq<'T[]> = source.Compose { new SeqFactory<'T,'T[]>() with member __.Create outOfBand pipeIdx next = upcast { diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index c9d70874908..f9f638f1470 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -134,10 +134,10 @@ namespace Microsoft.FSharp.Collections and ^U:(static member DivideByInt : ^U * int -> ^U) [] - val empty<'T> : ISeq<'T> + val empty<'T> : ISeq<'T> [] - val inline exactlyOne : errorString:string -> source : ISeq<'T> -> 'T + val exactlyOne : ISeq<'T> -> 'T [] val inline fold<'T,'State> : f:('State->'T->'State) -> seed:'State -> source:ISeq<'T> -> 'State @@ -155,7 +155,7 @@ namespace Microsoft.FSharp.Collections val init : count:int -> f:(int -> 'T) -> ISeq<'T> [] - val iter : f:('T -> unit) -> source: ISeq<'T> -> unit + val inline iter : f:('T -> unit) -> source: ISeq<'T> -> unit [] val inline iter2 : f:('T->'U->unit) -> source1 : ISeq<'T> -> source2 : ISeq<'U> -> unit @@ -164,25 +164,25 @@ namespace Microsoft.FSharp.Collections val inline iteri2 : f:(int->'T->'U->unit) -> source1:ISeq<'T> -> source2:ISeq<'U> -> unit [] - val tryHead : source: ISeq<'T> -> 'T option + val tryHead : ISeq<'T> -> 'T option [] - val iteri : f:(int -> 'T -> unit) -> source: ISeq<'T> -> unit + 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 exists : f:('T -> bool) -> source: ISeq<'T> -> bool + val inline exists : f:('T -> bool) -> source: ISeq<'T> -> bool [] - val exists2 : predicate:('T->'U->bool) -> source1:ISeq<'T> -> source2:ISeq<'U> -> 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 forall : f:('T -> bool) -> source: ISeq<'T> -> bool + val inline forall : f:('T -> bool) -> source: ISeq<'T> -> bool [] val inline forall2 : predicate:('T->'U->bool) -> source1:ISeq<'T> -> source2:ISeq<'U> -> bool @@ -230,7 +230,7 @@ namespace Microsoft.FSharp.Collections val inline minBy : f:('T -> 'U) -> source: ISeq<'T> -> 'T when 'U:comparison [] - val inline pairwise : source:ISeq<'T> -> ISeq<'T * 'T> + val pairwise : source:ISeq<'T> -> ISeq<'T * 'T> [] val inline reduce : f:('T->'T->'T) -> source: ISeq<'T> -> 'T @@ -273,19 +273,19 @@ namespace Microsoft.FSharp.Collections val tryItem : index:int -> source: ISeq<'T> -> 'T option [] - val tryPick : f:('T -> 'U option) -> source: ISeq<'T> -> Option<'U> + val inline tryPick : f:('T -> 'U option) -> source: ISeq<'T> -> Option<'U> [] - val tryFind : f:('T -> bool) -> source: ISeq<'T> -> Option<'T> + val inline tryFind : f:('T -> bool) -> source: ISeq<'T> -> Option<'T> [] - val inline tryFindIndex: preidcate:('T->bool) -> source:ISeq<'T> -> int option + val inline tryFindIndex: predicate:('T->bool) -> source:ISeq<'T> -> int option [] val inline tryLast : source:ISeq<'T> -> 'T option [] - val inline windowed : windowSize:int -> source:ISeq<'T> -> ISeq<'T[]> + val windowed : windowSize:int -> source:ISeq<'T> -> ISeq<'T[]> [] val concat : sources:ISeq<'Collection> -> ISeq<'T> when 'Collection :> ISeq<'T> From 0194f57cd50a63602ffdc00551508bca9661945e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 24 Dec 2016 19:40:44 +1100 Subject: [PATCH 270/286] Simplified inheritence hierarchy - and finally decided to just go with Transform as the general name for processing --- src/fsharp/FSharp.Core/seqcomposer.fs | 122 ++++++++++++------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 32 +++---- 2 files changed, 67 insertions(+), 87 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 08dddd8c99a..a450726b1c0 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -54,49 +54,51 @@ namespace Microsoft.FSharp.Collections override this.ChainDispose _ = () [] - type Activity<'T,'U,'State> = + type Transform<'T,'U,'State> = inherit Activity<'T,'U> - val mutable State : 'State - - new (initState) = { + new (next:Activity, initState:'State) = { + inherit Activity<'T,'U> () State = initState + Next = next } - [] - type ActivityChained<'T,'U,'State> = - inherit Activity<'T,'U,'State> - + val mutable State : 'State val private Next : Activity - new (next:Activity, initState:'State) = { - inherit Activity<'T,'U,'State> (initState) - Next = next - } - override this.ChainComplete (stopTailCall, terminatingIdx) = this.Next.ChainComplete (&stopTailCall, terminatingIdx) override this.ChainDispose stopTailCall = this.Next.ChainDispose (&stopTailCall) [] - type ActivityChainedWithPostProcessing<'T,'U,'State> (next:Activity, inititalState:'State) = - inherit ActivityChained<'T,'U,'State>(next, inititalState) + type TransformWithPostProcessing<'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 private Next : Activity abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit override this.ChainComplete (stopTailCall, terminatingIdx) = this.OnComplete terminatingIdx - next.ChainComplete (&stopTailCall, terminatingIdx) + this.Next.ChainComplete (&stopTailCall, terminatingIdx) override this.ChainDispose stopTailCall = try this.OnDispose () - finally next.ChainDispose (&stopTailCall) + finally this.Next.ChainDispose (&stopTailCall) [] type Folder<'T,'Result,'State> = - inherit Activity<'T,'T,'State> + inherit Activity<'T,'T> + val mutable State : 'State val mutable Result : 'Result val mutable HaltedIdx : int @@ -105,15 +107,12 @@ namespace Microsoft.FSharp.Collections member this.StopFurtherProcessing pipeIdx = this.StopFurtherProcessing pipeIdx new (initalResult,initState) = { - inherit Activity<'T,'T,'State>(initState) + inherit Activity<'T,'T>() + State = initState HaltedIdx = 0 Result = initalResult } - [] - type Folder<'T,'Result>(initResult) = - inherit Folder<'T,'Result,NoValue>(initResult,Unchecked.defaultof) - [] type FolderWithPostProcessing<'T,'Result,'State>(initResult,initState) = inherit Folder<'T,'Result,'State>(initResult,initState) @@ -181,7 +180,7 @@ namespace Microsoft.FSharp.Collections | Finished = 2 type Result<'T>() = - inherit Folder<'T,'T>(Unchecked.defaultof<'T>) + inherit Folder<'T,'T,NoValue>(Unchecked.defaultof<'T>,Unchecked.defaultof) member val SeqState = SeqProcessNextStates.NotStarted with get, set @@ -854,7 +853,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>(seed) with + upcast { new Folder<'T,'State,NoValue>(seed,Unchecked.defaultof) with override this.ProcessNext value = this.Result <- f this.Result value Unchecked.defaultof<_> (* return value unsed in Fold context *) }) @@ -890,7 +889,7 @@ namespace Microsoft.FSharp.Collections [] let inline iter f (source:ISeq<'T>) = source.Fold (fun _ -> - upcast { new Folder<'T,NoValue> (Unchecked.defaultof) with + upcast { new Folder<'T,NoValue,NoValue> (Unchecked.defaultof,Unchecked.defaultof) with override this.ProcessNext value = f value Unchecked.defaultof<_> (* return value unsed in Fold context *) }) @@ -930,7 +929,7 @@ namespace Microsoft.FSharp.Collections [] let tryHead (source:ISeq<'T>) = source.Fold (fun pipeIdx -> - upcast { new Folder<'T, Option<'T>> (None) with + upcast { new Folder<'T, Option<'T>,NoValue> (None,Unchecked.defaultof) with override this.ProcessNext value = this.Result <- Some value this.StopFurtherProcessing pipeIdx @@ -950,7 +949,7 @@ namespace Microsoft.FSharp.Collections let inline except (itemsToExclude: seq<'T>) (source:ISeq<'T>) : ISeq<'T> when 'T:equality = source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = - upcast { new ActivityChained<'T,'V,Lazy>> + upcast { new Transform<'T,'V,Lazy>> (next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = if this.State.Value.Add input then TailCall.avoid (next.ProcessNext input) @@ -959,7 +958,7 @@ namespace Microsoft.FSharp.Collections [] let inline exists f (source:ISeq<'T>) = source.Fold (fun pipeIdx -> - upcast { new Folder<'T, bool> (false) with + upcast { new Folder<'T, bool,NoValue> (false,Unchecked.defaultof) with override this.ProcessNext value = if f value then this.Result <- true @@ -985,7 +984,7 @@ namespace Microsoft.FSharp.Collections [] let inline contains element (source:ISeq<'T>) = source.Fold (fun pipeIdx -> - upcast { new Folder<'T, bool> (false) with + upcast { new Folder<'T, bool,NoValue> (false,Unchecked.defaultof) with override this.ProcessNext value = if element = value then this.Result <- true @@ -995,7 +994,7 @@ namespace Microsoft.FSharp.Collections [] let inline forall predicate (source:ISeq<'T>) = source.Fold (fun pipeIdx -> - upcast { new Folder<'T, bool> (true) with + upcast { new Folder<'T, bool,NoValue> (true,Unchecked.defaultof) with override this.ProcessNext value = if not (predicate value) then this.Result <- false @@ -1022,7 +1021,7 @@ namespace Microsoft.FSharp.Collections let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = - upcast { new ActivityChained<'T,'V,NoValue>(next,Unchecked.defaultof) with + upcast { new Transform<'T,'V,NoValue>(next,Unchecked.defaultof) with override __.ProcessNext input = if f input then TailCall.avoid (next.ProcessNext input) else false } } @@ -1031,7 +1030,7 @@ namespace Microsoft.FSharp.Collections let inline map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = source.Compose { new SeqFactory<'T,'U>() with override __.Create _ _ next = - upcast { new ActivityChained<'T,'V,NoValue>(next,Unchecked.defaultof) with + upcast { new Transform<'T,'V,NoValue>(next,Unchecked.defaultof) with override __.ProcessNext input = TailCall.avoid (next.ProcessNext (f input)) } } @@ -1039,7 +1038,7 @@ namespace Microsoft.FSharp.Collections let inline mapi f (source:ISeq<_>) = source.Compose { new SeqFactory<'T,'U>() with override __.Create _ _ next = - upcast { new ActivityChained<'T,'V,int>(next, -1) with + 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)) } } @@ -1048,7 +1047,7 @@ namespace Microsoft.FSharp.Collections let inline map2<'First,'Second,'U> (map:'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = source1.Compose { new SeqFactory<'First,'U>() with override __.Create outOfBand pipeIdx (next:Activity<'U,'V>) = - upcast { new ActivityChainedWithPostProcessing<'First,'V, IEnumerator<'Second>>(next, (source2.GetEnumerator ())) with + upcast { new TransformWithPostProcessing<'First,'V, IEnumerator<'Second>>(next, (source2.GetEnumerator ())) with override self.ProcessNext input = if self.State.MoveNext () then TailCall.avoid (next.ProcessNext (map input self.State.Current)) @@ -1062,7 +1061,7 @@ namespace Microsoft.FSharp.Collections let inline mapi2<'First,'Second,'U> (map:int -> 'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = source1.Compose { new SeqFactory<'First,'U>() with override __.Create<'V> outOfBand pipeIdx next = - upcast { new ActivityChainedWithPostProcessing<'First,'V, Values>> + upcast { new TransformWithPostProcessing<'First,'V, Values>> (next, Values<_,_>(-1, source2.GetEnumerator ())) with override self.ProcessNext input = if self.State._2.MoveNext () then @@ -1079,7 +1078,7 @@ namespace Microsoft.FSharp.Collections (map:'First->'Second->'Third->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) (source3:ISeq<'Third>) : ISeq<'U> = source1.Compose { new SeqFactory<'First,'U>() with override __.Create<'V> outOfBand pipeIdx next = - upcast { new ActivityChainedWithPostProcessing<'First,'V, Values,IEnumerator<'Third>>> + upcast { new TransformWithPostProcessing<'First,'V, Values,IEnumerator<'Third>>> (next, Values<_,_>(source2.GetEnumerator(),source3.GetEnumerator())) with override self.ProcessNext input = if self.State._1.MoveNext() && self.State._2.MoveNext () then @@ -1092,7 +1091,6 @@ namespace Microsoft.FSharp.Collections self.State._1.Dispose () self.State._2.Dispose () }} - [] let inline compareWith (f:'T -> 'T -> int) (source1 :ISeq<'T>) (source2:ISeq<'T>) : int = source1.Fold (fun pipeIdx -> @@ -1116,7 +1114,7 @@ namespace Microsoft.FSharp.Collections let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = source.Compose { new SeqFactory<'T,'U>() with override __.Create _ _ next = - upcast { new ActivityChained<'T,'V,NoValue>(next,Unchecked.defaultof) with + upcast { new Transform<'T,'V,NoValue>(next,Unchecked.defaultof) with override __.ProcessNext input = match f input with | Some value -> TailCall.avoid (next.ProcessNext value) @@ -1126,7 +1124,7 @@ namespace Microsoft.FSharp.Collections let inline distinct (source:ISeq<'T>) : ISeq<'T> when 'T:equality = source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = - upcast { new ActivityChained<'T,'V,HashSet<'T>> + upcast { new Transform<'T,'V,HashSet<'T>> (next,(HashSet<'T>(HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = if this.State.Add input then TailCall.avoid (next.ProcessNext input) @@ -1136,7 +1134,7 @@ namespace Microsoft.FSharp.Collections let inline distinctBy (keyf:'T->'Key) (source:ISeq<'T>) :ISeq<'T> when 'Key:equality = source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = - upcast { new ActivityChained<'T,'V,HashSet<'Key>> + upcast { new Transform<'T,'V,HashSet<'Key>> (next,(HashSet<'Key>(HashIdentity.Structural<'Key>))) with override this.ProcessNext (input:'T) : bool = if this.State.Add (keyf input) then TailCall.avoid (next.ProcessNext input) @@ -1222,7 +1220,7 @@ namespace Microsoft.FSharp.Collections let pairwise (source:ISeq<'T>) : ISeq<'T*'T> = source.Compose { new SeqFactory<'T,'T * 'T>() with override __.Create _ _ next = - upcast { new ActivityChained<'T,'U,Values> + upcast { new Transform<'T,'U,Values> ( next , Values ((* isFirst = _1*) true @@ -1260,19 +1258,17 @@ namespace Microsoft.FSharp.Collections let inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = source.Compose { new SeqFactory<'T,'State>() with override __.Create _ _ next = - upcast { new ActivityChained<'T,'V,'State>(next, initialState) with + 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.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = upcast { - new ActivityChainedWithPostProcessing<'T,'U,int>(next,(*count*)0) with - + new TransformWithPostProcessing<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = if (*count*) self.State < skipCount then self.State <- self.State + 1 @@ -1289,19 +1285,18 @@ namespace Microsoft.FSharp.Collections interface ISkipping with member self.Skipping () = - let self = self :?> ActivityChained<'T,'U,int> + let self = self :?> TransformWithPostProcessing<'T,'U,int> if (*count*) self.State < skipCount then self.State <- self.State + 1 true else - false - }} + false }} [] let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source.Compose { new SeqFactory<'T,'T>() with override __.Create _ _ next = - upcast { new ActivityChained<'T,'V,bool>(next,true) with + upcast { new Transform<'T,'V,bool>(next,true) with override self.ProcessNext (input:'T) : bool = if self.State (*skip*) then self.State <- predicate input @@ -1317,7 +1312,7 @@ namespace Microsoft.FSharp.Collections when ^T:(static member Zero : ^T) and ^T:(static member (+) : ^T * ^T -> ^T) = source.Fold (fun _ -> - upcast { new Folder< ^T,^T> (LanguagePrimitives.GenericZero) with + 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 unsed in Fold context *) }) @@ -1327,7 +1322,7 @@ namespace Microsoft.FSharp.Collections when ^U:(static member Zero : ^U) and ^U:(static member (+) : ^U * ^U -> ^U) = source.Fold (fun _ -> - upcast { new Folder<'T,'U> (LanguagePrimitives.GenericZero< ^U>) with + 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 unsed in Fold context *) }) @@ -1337,7 +1332,7 @@ namespace Microsoft.FSharp.Collections source.Compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipelineIdx next = upcast { - new ActivityChainedWithPostProcessing<'T,'U,int>(next,(*count*)0) with + new TransformWithPostProcessing<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = if (*count*) self.State < takeCount then self.State <- self.State + 1 @@ -1359,20 +1354,19 @@ namespace Microsoft.FSharp.Collections let inline takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = source.Compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipeIdx next = - upcast { new ActivityChained<'T,'V,NoValue>(next,Unchecked.defaultof) with + 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 - }} + false }} [] let tail (source:ISeq<'T>) :ISeq<'T> = source.Compose { new SeqFactory<'T,'T>() with member __.Create _ _ next = - upcast { new ActivityChainedWithPostProcessing<'T,'V,bool>(next,(*first*) true) with + upcast { new TransformWithPostProcessing<'T,'V,bool>(next,(*first*) true) with override self.ProcessNext (input:'T) : bool = if (*first*) self.State then self.State <- false @@ -1390,7 +1384,7 @@ namespace Microsoft.FSharp.Collections source.Compose { new SeqFactory<'T,'T>() with member __.Create outOfBand pipeIdx next = upcast { - new ActivityChained<'T,'U,int>(next,(*count*)0) with + new Transform<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = if (*count*) self.State < truncateCount then self.State <- self.State + 1 @@ -1413,7 +1407,7 @@ namespace Microsoft.FSharp.Collections [] let inline tryPick f (source:ISeq<'T>) = source.Fold (fun pipeIdx -> - upcast { new Folder<'T, Option<'U>> (None) with + upcast { new Folder<'T, Option<'U>,NoValue> (None,Unchecked.defaultof) with override this.ProcessNext value = match f value with | (Some _) as some -> @@ -1425,7 +1419,7 @@ namespace Microsoft.FSharp.Collections [] let inline tryFind f (source:ISeq<'T>) = source.Fold (fun pipeIdx -> - upcast { new Folder<'T, Option<'T>> (None) with + upcast { new Folder<'T, Option<'T>,NoValue> (None,Unchecked.defaultof) with override this.ProcessNext value = if f value then this.Result <- Some value @@ -1463,7 +1457,7 @@ namespace Microsoft.FSharp.Collections source.Compose { new SeqFactory<'T,'T[]>() with member __.Create outOfBand pipeIdx next = upcast { - new ActivityChained<'T,'U,Values<'T[],int,int>> + new Transform<'T,'U,Values<'T[],int,int>> ( next , Values<'T[],int,int> ((*circularBuffer = _1 *) Array.zeroCreateUnchecked windowSize @@ -1489,9 +1483,7 @@ namespace Microsoft.FSharp.Collections let window = Array.zeroCreateUnchecked windowSize Array.Copy((*circularBuffer*)self.State._1, (* idx *)self.State._2, window, 0, windowSize - (* idx *)self.State._2) Array.Copy((*circularBuffer*)self.State._1, 0, window, windowSize - (* idx *)self.State._2, (* idx *)self.State._2) - TailCall.avoid (next.ProcessNext window) - - }} + TailCall.avoid (next.ProcessNext window) }} [] let concat (sources:ISeq<#ISeq<'T>>) : ISeq<'T> = @@ -1502,5 +1494,3 @@ namespace Microsoft.FSharp.Collections match source1 with | :? Enumerable.EnumerableBase<'T> as s -> s.Append source2 | _ -> Upcast.seq (new Enumerable.AppendEnumerable<_>([source2; source1])) - - diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index f9f638f1470..82df9ec42bd 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -60,52 +60,42 @@ namespace Microsoft.FSharp.Collections abstract member ProcessNext : input:'T -> bool [] - type Activity<'T,'U,'State> = + type Transform<'T,'U,'State> = inherit Activity<'T,'U> + new : next:Activity * 'State -> Transform<'T,'U,'State> val mutable State : 'State - new : 'State -> Activity<'T,'U,'State> - - [] - type ActivityChained<'T,'U,'State> = - inherit Activity<'T,'U,'State> val private Next : Activity - new : next:Activity * 'State -> ActivityChained<'T,'U,'State> [] - type ActivityChainedWithPostProcessing<'T,'U,'State> = - inherit ActivityChained<'T,'U,'State> - + type TransformWithPostProcessing<'T,'U,'State> = + inherit Activity<'T,'U> + new : next:Activity * 'State -> TransformWithPostProcessing<'T,'U,'State> + val mutable State : 'State + val private Next : Activity abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit - new : next:Activity * 'State -> ActivityChainedWithPostProcessing<'T,'U,'State> - /// 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,'State> + inherit Activity<'T,'T> new : 'Result*'State -> Folder<'T,'Result,'State> interface IOutOfBand - val mutable HaltedIdx : int + val mutable State : 'State val mutable Result : 'Result + val mutable HaltedIdx : int member StopFurtherProcessing : PipeIdx -> unit - [] - type Folder<'T,'Result> = - inherit Folder<'T,'Result,NoValue> - new : 'Result -> Folder<'T,'Result> - [] 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 - new : 'Result*'State -> FolderWithPostProcessing<'T,'Result,'State> - [] type SeqFactory<'T,'U> = new : unit -> SeqFactory<'T,'U> From 16cc8a49b48aaf2fec4e3dd01c9eababd6a4eee6 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 24 Dec 2016 19:45:35 +1100 Subject: [PATCH 271/286] Restored TransformWithPostProcessing hierarch - For symmetry with Folder - Fixed a spelling error --- src/fsharp/FSharp.Core/seqcomposer.fs | 67 +++++++++++--------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 5 +- 2 files changed, 30 insertions(+), 42 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index a450726b1c0..224828c9466 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -64,7 +64,7 @@ namespace Microsoft.FSharp.Collections } val mutable State : 'State - val private Next : Activity + val Next : Activity override this.ChainComplete (stopTailCall, terminatingIdx) = this.Next.ChainComplete (&stopTailCall, terminatingIdx) @@ -72,17 +72,8 @@ namespace Microsoft.FSharp.Collections this.Next.ChainDispose (&stopTailCall) [] - type TransformWithPostProcessing<'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 private Next : Activity + type TransformWithPostProcessing<'T,'U,'State>(next:Activity, initState:'State) = + inherit Transform<'T,'U,'State>(next, initState) abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit @@ -801,7 +792,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Result <- Checked.(+) this.Result value this.State <- this.State + 1 - Unchecked.defaultof<_> (* return value unsed in Fold context *) + Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = if this.State = 0 then @@ -819,7 +810,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Result <- Checked.(+) this.Result (f value) this.State <- this.State + 1 - Unchecked.defaultof<_> (* return value unsed in Fold context *) + Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = if this.State = 0 then @@ -841,7 +832,7 @@ namespace Microsoft.FSharp.Collections else this.State._2 <- true this.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in Fold context *) + Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = if this.State._1 then @@ -856,7 +847,7 @@ namespace Microsoft.FSharp.Collections upcast { new Folder<'T,'State,NoValue>(seed,Unchecked.defaultof) with override this.ProcessNext value = this.Result <- f this.Result value - Unchecked.defaultof<_> (* return value unsed in Fold context *) }) + 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>) = @@ -867,7 +858,7 @@ namespace Microsoft.FSharp.Collections self.Result <- folder self.Result value self.State.Current else self.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in Fold context *) + Unchecked.defaultof<_> (* return value unused in Fold context *) override self.OnComplete _ = () override self.OnDispose () = self.State.Dispose() }) @@ -892,7 +883,7 @@ namespace Microsoft.FSharp.Collections upcast { new Folder<'T,NoValue,NoValue> (Unchecked.defaultof,Unchecked.defaultof) with override this.ProcessNext value = f value - Unchecked.defaultof<_> (* return value unsed in Fold context *) }) + Unchecked.defaultof<_> (* return value unused in Fold context *) }) |> ignore [] @@ -904,7 +895,7 @@ namespace Microsoft.FSharp.Collections f value self.State.Current else self.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in Fold context *) + Unchecked.defaultof<_> (* return value unused in Fold context *) override self.OnComplete _ = () override self.OnDispose () = self.State.Dispose() }) @@ -933,7 +924,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = this.Result <- Some value this.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in Fold context *) }) + Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] let inline iteri f (source:ISeq<'T>) = @@ -942,7 +933,7 @@ namespace Microsoft.FSharp.Collections override this.ProcessNext value = f this.State value this.State <- this.State + 1 - Unchecked.defaultof<_> (* return value unsed in Fold context *) }) + Unchecked.defaultof<_> (* return value unused in Fold context *) }) |> ignore [] @@ -963,7 +954,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Result <- true this.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in Fold context *) }) + Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] let inline exists2 (predicate:'T->'U->bool) (source1: ISeq<'T>) (source2: ISeq<'U>) : bool = @@ -976,7 +967,7 @@ namespace Microsoft.FSharp.Collections self.StopFurtherProcessing pipeIdx else self.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in Fold context *) + Unchecked.defaultof<_> (* return value unused in Fold context *) override self.OnComplete _ = () override self.OnDispose () = self.State.Dispose() }) @@ -989,7 +980,7 @@ namespace Microsoft.FSharp.Collections if element = value then this.Result <- true this.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in Fold context *) }) + Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] let inline forall predicate (source:ISeq<'T>) = @@ -999,7 +990,7 @@ namespace Microsoft.FSharp.Collections if not (predicate value) then this.Result <- false this.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in Fold context *) }) + Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] let inline forall2 predicate (source1:ISeq<'T>) (source2:ISeq<'U>) : bool = @@ -1012,7 +1003,7 @@ namespace Microsoft.FSharp.Collections self.StopFurtherProcessing pipeIdx else self.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in Fold context *) + Unchecked.defaultof<_> (* return value unused in Fold context *) override self.OnComplete _ = () override self.OnDispose () = self.State.Dispose() }) @@ -1104,7 +1095,7 @@ namespace Microsoft.FSharp.Collections if c <> 0 then self.Result <- c self.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in Fold context *) + Unchecked.defaultof<_> (* return value unused in Fold context *) override self.OnComplete _ = if self.Result = 0 && self.State.MoveNext() then self.Result <- -1 @@ -1150,7 +1141,7 @@ namespace Microsoft.FSharp.Collections this.Result <- value elif value > this.Result then this.Result <- value - Unchecked.defaultof<_> (* return value unsed in Fold context *) + Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = if this.State then @@ -1171,7 +1162,7 @@ namespace Microsoft.FSharp.Collections this.State._2 <- valueU this.Result <- value | _ -> () - Unchecked.defaultof<_> (* return value unsed in Fold context *) + Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = if this.State._1 then @@ -1188,7 +1179,7 @@ namespace Microsoft.FSharp.Collections this.Result <- value elif value < this.Result then this.Result <- value - Unchecked.defaultof<_> (* return value unsed in Fold context *) + Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = if this.State then @@ -1209,7 +1200,7 @@ namespace Microsoft.FSharp.Collections this.State._2 <- valueU this.Result <- value | _ -> () - Unchecked.defaultof<_> (* return value unsed in Fold context *) + Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = if this.State._1 then @@ -1247,7 +1238,7 @@ namespace Microsoft.FSharp.Collections this.Result <- value else this.Result <- f this.Result value - Unchecked.defaultof<_> (* return value unsed in Fold context *) + Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = if this.State then @@ -1315,7 +1306,7 @@ namespace Microsoft.FSharp.Collections 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 unsed in Fold context *) }) + Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] let inline sumBy (f : 'T -> ^U) (source: ISeq<'T>) : ^U @@ -1325,7 +1316,7 @@ namespace Microsoft.FSharp.Collections 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 unsed in Fold context *) }) + Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] let take (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = @@ -1414,7 +1405,7 @@ namespace Microsoft.FSharp.Collections this.Result <- some this.StopFurtherProcessing pipeIdx | None -> () - Unchecked.defaultof<_> (* return value unsed in Fold context *) }) + Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] let inline tryFind f (source:ISeq<'T>) = @@ -1424,7 +1415,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Result <- Some value this.StopFurtherProcessing pipeIdx - Unchecked.defaultof<_> (* return value unsed in Fold context *) }) + Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] let inline tryFindIndex (predicate:'T->bool) (source:ISeq<'T>) : int option = @@ -1436,7 +1427,7 @@ namespace Microsoft.FSharp.Collections this.StopFurtherProcessing pipeIdx else this.State <- this.State + 1 - Unchecked.defaultof<_> (* return value unsed in Fold context *) }) + Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] let inline tryLast (source :ISeq<'T>) : 'T option = @@ -1446,7 +1437,7 @@ namespace Microsoft.FSharp.Collections if this.State._1 then this.State._1 <- false this.State._2 <- value - Unchecked.defaultof<_> (* return value unsed in Fold context *) + Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = if not this.State._1 then this.Result <- Some this.State._2 diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 82df9ec42bd..f1a673a15b1 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -68,10 +68,8 @@ namespace Microsoft.FSharp.Collections [] type TransformWithPostProcessing<'T,'U,'State> = - inherit Activity<'T,'U> + inherit Transform<'T,'U,'State> new : next:Activity * 'State -> TransformWithPostProcessing<'T,'U,'State> - val mutable State : 'State - val private Next : Activity abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit @@ -92,7 +90,6 @@ namespace Microsoft.FSharp.Collections 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 From 3530cd2764c271952ffdc32a7ae2c32a38a474e6 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 26 Dec 2016 15:42:48 +1100 Subject: [PATCH 272/286] More renaming - SeqFactory to TransformFactory - Compose to PushTransform - Create to Compose --- src/fsharp/FSharp.Core/seqcomposer.fs | 149 +++++++++++++------------ src/fsharp/FSharp.Core/seqcomposer.fsi | 12 +- 2 files changed, 81 insertions(+), 80 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 224828c9466..dbf71ec1e82 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -50,8 +50,6 @@ namespace Microsoft.FSharp.Collections type Activity<'T,'U> () = inherit Activity() abstract ProcessNext : input:'T -> bool - override this.ChainComplete (_,_) = () - override this.ChainDispose _ = () [] type Transform<'T,'U,'State> = @@ -89,10 +87,10 @@ namespace Microsoft.FSharp.Collections type Folder<'T,'Result,'State> = inherit Activity<'T,'T> - val mutable State : 'State val mutable Result : 'Result - val mutable HaltedIdx : int + 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 @@ -104,6 +102,9 @@ namespace Microsoft.FSharp.Collections Result = initalResult } + override this.ChainComplete (_,_) = () + override this.ChainDispose _ = () + [] type FolderWithPostProcessing<'T,'Result,'State>(initResult,initState) = inherit Folder<'T,'Result,'State>(initResult,initState) @@ -117,12 +118,12 @@ namespace Microsoft.FSharp.Collections this.OnDispose () [] - type SeqFactory<'T,'U> () = - abstract Create<'V> : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> + type TransformFactory<'T,'U> () = + abstract Compose<'V> : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> type ISeq<'T> = inherit IEnumerable<'T> - abstract member Compose<'U> : (SeqFactory<'T,'U>) -> ISeq<'U> + abstract member PushTransform<'U> : TransformFactory<'T,'U> -> ISeq<'U> abstract member Fold<'Result,'State> : f:(PipeIdx->Folder<'T,'Result,'State>) -> 'Result open Core @@ -142,22 +143,22 @@ namespace Microsoft.FSharp.Collections let inline enumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) let inline outOfBand (t:#IOutOfBand) : IOutOfBand = (# "" t : IOutOfBand #) - let createFold (factory:SeqFactory<_,_>) (folder:Folder<_,_,_>) pipeIdx = - factory.Create (Upcast.outOfBand folder) pipeIdx folder + let createFold (factory:TransformFactory<_,_>) (folder:Folder<_,_,_>) pipeIdx = + factory.Compose (Upcast.outOfBand folder) pipeIdx folder - type ComposedFactory<'T,'U,'V> private (first:SeqFactory<'T,'U>, second:SeqFactory<'U,'V>) = - inherit SeqFactory<'T,'V>() + type ComposedFactory<'T,'U,'V> private (first:TransformFactory<'T,'U>, second:TransformFactory<'U,'V>) = + inherit TransformFactory<'T,'V>() - override this.Create<'W> (outOfBand:IOutOfBand) (pipeIdx:PipeIdx) (next:Activity<'V,'W>) : Activity<'T,'W> = - first.Create outOfBand (pipeIdx-1) (second.Create 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:SeqFactory<'T,'U>) (second:SeqFactory<'U,'V>) : SeqFactory<'T,'V> = + static member Combine (first:TransformFactory<'T,'U>) (second:TransformFactory<'U,'V>) : TransformFactory<'T,'V> = upcast ComposedFactory(first, second) and IdentityFactory<'T> () = - inherit SeqFactory<'T,'T> () - static let singleton : SeqFactory<'T,'T> = upcast (IdentityFactory<'T>()) - override __.Create<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next + 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 ISkipping = @@ -264,7 +265,7 @@ namespace Microsoft.FSharp.Collections skip 0 |> iterate - let execute (f:PipeIdx->Folder<'U,'Result,'State>) (current:SeqFactory<'T,'U>) pipeIdx (executeOn:#IIterate<'T>) = + let execute (f:PipeIdx->Folder<'U,'Result,'State>) (current:TransformFactory<'T,'U>) pipeIdx (executeOn:#IIterate<'T>) = let mutable stopTailCall = () let result = f (pipeIdx+1) let consumer = createFold current result pipeIdx @@ -340,7 +341,7 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () : IEnumerator<'T> = derivedClassShouldImplement () interface ISeq<'T> with - member __.Compose _ = derivedClassShouldImplement () + member __.PushTransform _ = derivedClassShouldImplement () member __.Fold _ = derivedClassShouldImplement () and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:Activity<'T,'U>, result:Result<'U>) = @@ -371,7 +372,7 @@ namespace Microsoft.FSharp.Collections let mutable stopTailCall = () (seqComponent).ChainDispose (&stopTailCall) - and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqFactory<'T,'U>, pipeIdx:PipeIdx) = + and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() interface IEnumerable<'U> with @@ -380,7 +381,7 @@ namespace Microsoft.FSharp.Collections Upcast.enumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), createFold current result pipeIdx, result)) interface ISeq<'U> with - member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = + 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>) = @@ -393,7 +394,7 @@ namespace Microsoft.FSharp.Collections member this.GetEnumerator () = enumerable.GetEnumerator () interface ISeq<'T> with - member __.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = + 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>) = @@ -448,7 +449,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (AppendEnumerable (source::sources)) interface ISeq<'T> with - member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = + 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>) = @@ -462,7 +463,7 @@ namespace Microsoft.FSharp.Collections Upcast.enumerator (new ConcatEnumerator<_,_> (sources)) interface ISeq<'T> with - member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = + 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>) = @@ -485,7 +486,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (Enumerable.EnumerableThin<'T> source) interface ISeq<'T> with - member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = + 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>) = @@ -524,7 +525,7 @@ namespace Microsoft.FSharp.Collections initMoveNext () moveNext () - type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:SeqFactory<'T,'U>, pipeIdx:PipeIdx) = + type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with @@ -533,16 +534,16 @@ namespace Microsoft.FSharp.Collections Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, createFold current result pipeIdx, result)) interface ISeq<'U> with - member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next, 1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = Fold.execute f current pipeIdx (Fold.Array (delayedArray ())) - let createDelayed (delayedArray:unit->array<'T>) (current:SeqFactory<'T,'U>) = + let createDelayed (delayedArray:unit->array<'T>) (current:TransformFactory<'T,'U>) = Upcast.seq (Enumerable(delayedArray, current, 1)) - let create (array:array<'T>) (current:SeqFactory<'T,'U>) = + let create (array:array<'T>) (current:TransformFactory<'T,'U>) = createDelayed (fun () -> array) current let createDelayedId (delayedArray:unit -> array<'T>) = @@ -576,7 +577,7 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext list - type Enumerable<'T,'U>(alist:list<'T>, current:SeqFactory<'T,'U>, pipeIdx:PipeIdx) = + type Enumerable<'T,'U>(alist:list<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with @@ -585,7 +586,7 @@ namespace Microsoft.FSharp.Collections Upcast.enumerator (new Enumerator<'T,'U>(alist, createFold current result pipeIdx, result)) interface ISeq<'U> with - member __.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = + member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(alist, ComposedFactory.Combine current next, pipeIdx+1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = @@ -615,7 +616,7 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:SeqFactory<'T,'U>, pipeIdx:PipeIdx) = + type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with @@ -624,7 +625,7 @@ namespace Microsoft.FSharp.Collections Upcast.enumerator (new Enumerator<'T,'U,'GeneratorState>(generator, state, createFold current result pipeIdx, result)) interface ISeq<'U> with - member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = + member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V,'GeneratorState>(generator, state, ComposedFactory.Combine current next, pipeIdx+1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = @@ -690,7 +691,7 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqFactory<'T,'U>, pipeIdx:PipeIdx) = + type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit Enumerable.EnumerableBase<'U>() interface IEnumerable<'U> with @@ -699,7 +700,7 @@ namespace Microsoft.FSharp.Collections Upcast.enumerator (new Enumerator<'T,'U>(count, f, createFold current result pipeIdx, result)) interface ISeq<'U> with - member this.Compose (next:SeqFactory<'U,'V>) : ISeq<'V> = + member this.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = Upcast.seq (new Enumerable<'T,'V>(count, f, ComposedFactory.Combine current next, pipeIdx+1)) member this.Fold<'Result,'State> (createResult:PipeIdx->Folder<'U,'Result,'State>) = @@ -767,7 +768,7 @@ namespace Microsoft.FSharp.Collections upto (if count.HasValue then Some (count.Value-1) else None) f interface ISeq<'T> with - member this.Compose (next:SeqFactory<'T,'U>) : ISeq<'U> = + 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>) = @@ -938,8 +939,8 @@ namespace Microsoft.FSharp.Collections [] let inline except (itemsToExclude: seq<'T>) (source:ISeq<'T>) : ISeq<'T> when 'T:equality = - source.Compose { new SeqFactory<'T,'T>() with - override __.Create _ _ next = + 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 = @@ -1010,8 +1011,8 @@ namespace Microsoft.FSharp.Collections [] let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source.Compose { new SeqFactory<'T,'T>() with - override __.Create _ _ next = + 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) @@ -1019,16 +1020,16 @@ namespace Microsoft.FSharp.Collections [] let inline map<'T,'U> (f:'T->'U) (source:ISeq<'T>) : ISeq<'U> = - source.Compose { new SeqFactory<'T,'U>() with - override __.Create _ _ next = + 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.Compose { new SeqFactory<'T,'U>() with - override __.Create _ _ next = + 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 @@ -1036,8 +1037,8 @@ namespace Microsoft.FSharp.Collections [] let inline map2<'First,'Second,'U> (map:'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = - source1.Compose { new SeqFactory<'First,'U>() with - override __.Create outOfBand pipeIdx (next:Activity<'U,'V>) = + source1.PushTransform { new TransformFactory<'First,'U>() with + override __.Compose outOfBand pipeIdx (next:Activity<'U,'V>) = upcast { new TransformWithPostProcessing<'First,'V, IEnumerator<'Second>>(next, (source2.GetEnumerator ())) with override self.ProcessNext input = if self.State.MoveNext () then @@ -1050,8 +1051,8 @@ namespace Microsoft.FSharp.Collections [] let inline mapi2<'First,'Second,'U> (map:int -> 'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = - source1.Compose { new SeqFactory<'First,'U>() with - override __.Create<'V> outOfBand pipeIdx next = + source1.PushTransform { new TransformFactory<'First,'U>() with + override __.Compose<'V> outOfBand pipeIdx next = upcast { new TransformWithPostProcessing<'First,'V, Values>> (next, Values<_,_>(-1, source2.GetEnumerator ())) with override self.ProcessNext input = @@ -1067,8 +1068,8 @@ namespace Microsoft.FSharp.Collections [] let inline map3<'First,'Second,'Third,'U> (map:'First->'Second->'Third->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) (source3:ISeq<'Third>) : ISeq<'U> = - source1.Compose { new SeqFactory<'First,'U>() with - override __.Create<'V> outOfBand pipeIdx next = + source1.PushTransform { new TransformFactory<'First,'U>() with + override __.Compose<'V> outOfBand pipeIdx next = upcast { new TransformWithPostProcessing<'First,'V, Values,IEnumerator<'Third>>> (next, Values<_,_>(source2.GetEnumerator(),source3.GetEnumerator())) with override self.ProcessNext input = @@ -1103,8 +1104,8 @@ namespace Microsoft.FSharp.Collections [] let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = - source.Compose { new SeqFactory<'T,'U>() with - override __.Create _ _ next = + 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 @@ -1113,8 +1114,8 @@ namespace Microsoft.FSharp.Collections [] let inline distinct (source:ISeq<'T>) : ISeq<'T> when 'T:equality = - source.Compose { new SeqFactory<'T,'T>() with - override __.Create _ _ next = + source.PushTransform { new TransformFactory<'T,'T>() with + override __.Compose _ _ next = upcast { new Transform<'T,'V,HashSet<'T>> (next,(HashSet<'T>(HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = @@ -1123,8 +1124,8 @@ namespace Microsoft.FSharp.Collections [] let inline distinctBy (keyf:'T->'Key) (source:ISeq<'T>) :ISeq<'T> when 'Key:equality = - source.Compose { new SeqFactory<'T,'T>() with - override __.Create _ _ next = + source.PushTransform { new TransformFactory<'T,'T>() with + override __.Compose _ _ next = upcast { new Transform<'T,'V,HashSet<'Key>> (next,(HashSet<'Key>(HashIdentity.Structural<'Key>))) with override this.ProcessNext (input:'T) : bool = @@ -1209,8 +1210,8 @@ namespace Microsoft.FSharp.Collections [] let pairwise (source:ISeq<'T>) : ISeq<'T*'T> = - source.Compose { new SeqFactory<'T,'T * 'T>() with - override __.Create _ _ next = + source.PushTransform { new TransformFactory<'T,'T * 'T>() with + override __.Compose _ _ next = upcast { new Transform<'T,'U,Values> ( next , Values @@ -1247,8 +1248,8 @@ namespace Microsoft.FSharp.Collections [] let inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = - source.Compose { new SeqFactory<'T,'State>() with - override __.Create _ _ next = + 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 @@ -1256,8 +1257,8 @@ namespace Microsoft.FSharp.Collections [] let skip (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = - source.Compose { new SeqFactory<'T,'T>() with - override __.Create _ _ next = + source.PushTransform { new TransformFactory<'T,'T>() with + override __.Compose _ _ next = upcast { new TransformWithPostProcessing<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = @@ -1285,8 +1286,8 @@ namespace Microsoft.FSharp.Collections [] let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source.Compose { new SeqFactory<'T,'T>() with - override __.Create _ _ next = + source.PushTransform { new TransformFactory<'T,'T>() with + override __.Compose _ _ next = upcast { new Transform<'T,'V,bool>(next,true) with override self.ProcessNext (input:'T) : bool = if self.State (*skip*) then @@ -1320,8 +1321,8 @@ namespace Microsoft.FSharp.Collections [] let take (takeCount:int) (source:ISeq<'T>) : ISeq<'T> = - source.Compose { new SeqFactory<'T,'T>() with - member __.Create outOfBand pipelineIdx next = + source.PushTransform { new TransformFactory<'T,'T>() with + member __.Compose outOfBand pipelineIdx next = upcast { new TransformWithPostProcessing<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = @@ -1343,8 +1344,8 @@ namespace Microsoft.FSharp.Collections [] let inline takeWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = - source.Compose { new SeqFactory<'T,'T>() with - member __.Create outOfBand pipeIdx next = + 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 @@ -1355,8 +1356,8 @@ namespace Microsoft.FSharp.Collections [] let tail (source:ISeq<'T>) :ISeq<'T> = - source.Compose { new SeqFactory<'T,'T>() with - member __.Create _ _ next = + source.PushTransform { new TransformFactory<'T,'T>() with + member __.Compose _ _ next = upcast { new TransformWithPostProcessing<'T,'V,bool>(next,(*first*) true) with override self.ProcessNext (input:'T) : bool = if (*first*) self.State then @@ -1372,8 +1373,8 @@ namespace Microsoft.FSharp.Collections [] let truncate (truncateCount:int) (source:ISeq<'T>) : ISeq<'T> = - source.Compose { new SeqFactory<'T,'T>() with - member __.Create outOfBand pipeIdx next = + source.PushTransform { new TransformFactory<'T,'T>() with + member __.Compose outOfBand pipeIdx next = upcast { new Transform<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = @@ -1445,8 +1446,8 @@ namespace Microsoft.FSharp.Collections [] let windowed (windowSize:int) (source:ISeq<'T>) : ISeq<'T[]> = - source.Compose { new SeqFactory<'T,'T[]>() with - member __.Create outOfBand pipeIdx next = + source.PushTransform { new TransformFactory<'T,'T[]>() with + member __.Compose outOfBand pipeIdx next = upcast { new Transform<'T,'U,Values<'T[],int,int>> ( next diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index f1a673a15b1..6cab705cbff 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -94,13 +94,13 @@ namespace Microsoft.FSharp.Collections abstract OnComplete : PipeIdx -> unit [] - type SeqFactory<'T,'U> = - new : unit -> SeqFactory<'T,'U> - abstract member Create : IOutOfBand -> PipeIdx -> Activity<'U,'V> -> Activity<'T,'V> + 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 Compose : SeqFactory<'T,'U> -> ISeq<'U> + abstract member PushTransform : TransformFactory<'T,'U> -> ISeq<'U> abstract member Fold<'Result,'State> : f:(PipeIdx->Folder<'T,'Result,'State>) -> 'Result open Core @@ -281,8 +281,8 @@ namespace Microsoft.FSharp.Collections val append: source1:ISeq<'T> -> source2:ISeq<'T> -> ISeq<'T> module internal Array = begin - val createDelayed : (unit -> 'T array) -> SeqFactory<'T,'U> -> ISeq<'U> - val create : 'T array -> SeqFactory<'T,'U> -> ISeq<'U> + val createDelayed : (unit -> 'T array) -> TransformFactory<'T,'U> -> ISeq<'U> + val create : 'T array -> TransformFactory<'T,'U> -> ISeq<'U> val createDelayedId : (unit -> 'T array) -> ISeq<'T> val createId : 'T array -> ISeq<'T> end From aa4fba595a990e7cc758223511cf5cbfa236af72 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 26 Dec 2016 19:26:46 +1100 Subject: [PATCH 273/286] Fix Skipping logic on Fold - And removed unbox cast for performance --- src/fsharp/FSharp.Core/seqcomposer.fs | 58 +++++++++++++++------------ 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index dbf71ec1e82..871026ed0dc 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -235,35 +235,39 @@ namespace Microsoft.FSharp.Collections | _ -> () iterate state - let makeIsSkipping (consumer:Activity<'T,'U>) = - match box consumer with - | :? ISkipping as skip -> skip.Skipping - | _ -> fun () -> false - [] 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 terminatingIdx = terminatingIdx let f = f - let isSkipping = makeIsSkipping consumer - let rec skip idx = - if idx >= terminatingIdx || outOfBand.HaltedIdx <> 0 then - terminatingIdx - elif isSkipping () then - skip (idx+1) - else - idx + let firstIdx = + match box consumer with + | :? ISkipping as skipping -> + let rec skip idx = + if idx = terminatingIdx || outOfBand.HaltedIdx <> 0 then + terminatingIdx + elif skipping.Skipping () then + skip (idx+1) + else + idx + skip -1 + | _ -> -1 let rec iterate idx = if idx < terminatingIdx then - consumer.ProcessNext (f idx) |> ignore + consumer.ProcessNext (f (idx+1)) |> ignore if outOfBand.HaltedIdx = 0 then iterate (idx+1) + else + idx + else + idx - skip 0 - |> iterate + let finalIdx = iterate firstIdx + if outOfBand.HaltedIdx = 0 && finalIdx = System.Int32.MaxValue then + raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) let execute (f:PipeIdx->Folder<'U,'Result,'State>) (current:TransformFactory<'T,'U>) pipeIdx (executeOn:#IIterate<'T>) = let mutable stopTailCall = () @@ -655,7 +659,9 @@ namespace Microsoft.FSharp.Collections inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) let isSkipping = - Fold.makeIsSkipping seqComponent + match box seqComponent with + | :? ISkipping as skip -> skip.Skipping + | _ -> fun () -> false let terminatingIdx = getTerminatingIdx count @@ -664,7 +670,7 @@ namespace Microsoft.FSharp.Collections let mutable idx = -1 let rec moveNext () = - if (result.HaltedIdx = 0) && idx < terminatingIdx then + if result.HaltedIdx = 0 && idx < terminatingIdx then idx <- idx + 1 if maybeSkipping then @@ -678,7 +684,7 @@ namespace Microsoft.FSharp.Collections true else moveNext () - elif (result.HaltedIdx = 0) && idx = System.Int32.MaxValue then + elif result.HaltedIdx = 0 && idx = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) else result.SeqState <- SeqProcessNextStates.Finished @@ -1259,8 +1265,9 @@ namespace Microsoft.FSharp.Collections let skip (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = source.PushTransform { new TransformFactory<'T,'T>() with override __.Compose _ _ next = - upcast { - new TransformWithPostProcessing<'T,'U,int>(next,(*count*)0) with + let mutable self = Unchecked.defaultof> + let skipper = + { new TransformWithPostProcessing<'T,'U,int>(next,(*count*)0) with override self.ProcessNext (input:'T) : bool = if (*count*) self.State < skipCount then self.State <- self.State + 1 @@ -1276,13 +1283,14 @@ namespace Microsoft.FSharp.Collections override self.OnDispose () = () interface ISkipping with - member self.Skipping () = - let self = self :?> TransformWithPostProcessing<'T,'U,int> + member __.Skipping () = if (*count*) self.State < skipCount then self.State <- self.State + 1 true else - false }} + false } + self <- skipper + upcast self } [] let inline skipWhile (predicate:'T->bool) (source:ISeq<'T>) : ISeq<'T> = From de92712e3f1e7e62b24483b371689a2d83edc580 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 27 Dec 2016 10:49:57 +1100 Subject: [PATCH 274/286] Made "Upcast"s little safer --- src/fsharp/FSharp.Core/seqcomposer.fs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 871026ed0dc..c794d556d7e 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -137,11 +137,11 @@ namespace Microsoft.FSharp.Collections 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:#ISeq<'T>) : ISeq<'T> = (# "" t : ISeq<'T> #) - let inline enumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #) - let inline enumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #) - let inline enumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #) - let inline outOfBand (t:#IOutOfBand) : IOutOfBand = (# "" t : IOutOfBand #) + 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 From f52aecbda829215b788e582d078692aa6c36b64e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 27 Dec 2016 11:09:22 +1100 Subject: [PATCH 275/286] Tring to make variable naming consistent --- src/fsharp/FSharp.Core/seqcomposer.fs | 326 +++++++++++++------------- 1 file changed, 163 insertions(+), 163 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index c794d556d7e..55471b4c310 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -155,7 +155,7 @@ namespace Microsoft.FSharp.Collections static member Combine (first:TransformFactory<'T,'U>) (second:TransformFactory<'U,'V>) : TransformFactory<'T,'V> = upcast ComposedFactory(first, second) - and IdentityFactory<'T> () = + 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 @@ -269,10 +269,10 @@ namespace Microsoft.FSharp.Collections if outOfBand.HaltedIdx = 0 && finalIdx = System.Int32.MaxValue then raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue)) - let execute (f:PipeIdx->Folder<'U,'Result,'State>) (current:TransformFactory<'T,'U>) pipeIdx (executeOn:#IIterate<'T>) = + let execute (createFolder:PipeIdx->Folder<'U,'Result,'State>) (transformFactory:TransformFactory<'T,'U>) pipeIdx (executeOn:#IIterate<'T>) = let mutable stopTailCall = () - let result = f (pipeIdx+1) - let consumer = createFold current result pipeIdx + let result = createFolder (pipeIdx+1) + let consumer = createFold transformFactory result pipeIdx try executeOn.Iterate result consumer consumer.ChainComplete (&stopTailCall, result.HaltedIdx) @@ -280,9 +280,9 @@ namespace Microsoft.FSharp.Collections finally consumer.ChainDispose (&stopTailCall) - let executeThin (f:PipeIdx->Folder<'T,'Result,'State>) (executeOn:#IIterate<'T>) = + let executeThin (createFolder:PipeIdx->Folder<'T,'Result,'State>) (executeOn:#IIterate<'T>) = let mutable stopTailCall = () - let result = f 1 + let result = createFolder 1 try executeOn.Iterate result result result.ChainComplete (&stopTailCall, result.HaltedIdx) @@ -307,11 +307,11 @@ namespace Microsoft.FSharp.Collections static member Element = element [] - type EnumeratorBase<'T>(result:Result<'T>, seqComponent:Activity) = + type EnumeratorBase<'T>(result:Result<'T>, activity:Activity) = interface IDisposable with member __.Dispose() : unit = let mutable stopTailCall = () - seqComponent.ChainDispose (&stopTailCall) + activity.ChainDispose (&stopTailCall) interface IEnumerator with member this.Current : obj = box ((Upcast.enumerator this)).Current @@ -331,7 +331,7 @@ namespace Microsoft.FSharp.Collections 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> default this.Append source = Upcast.seq (AppendEnumerable [this; source]) @@ -348,19 +348,19 @@ namespace Microsoft.FSharp.Collections member __.PushTransform _ = derivedClassShouldImplement () member __.Fold _ = derivedClassShouldImplement () - and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:Activity<'T,'U>, result:Result<'U>) = - inherit EnumeratorBase<'U>(result, seqComponent) + 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 seqComponent.ProcessNext source.Current then + if activity.ProcessNext source.Current then true else moveNext () else result.SeqState <- SeqProcessNextStates.Finished let mutable stopTailCall = () - (seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) + activity.ChainComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -374,7 +374,7 @@ namespace Microsoft.FSharp.Collections source.Dispose () finally let mutable stopTailCall = () - (seqComponent).ChainDispose (&stopTailCall) + activity.ChainDispose (&stopTailCall) and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = inherit EnumerableBase<'U>() @@ -497,8 +497,8 @@ namespace Microsoft.FSharp.Collections Fold.executeThin f (Fold.enumerable this) module Array = - type Enumerator<'T,'U>(delayedArray:unit->array<'T>, seqComponent:Activity<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) + type Enumerator<'T,'U>(delayedArray:unit->array<'T>, activity:Activity<'T,'U>, result:Result<'U>) = + inherit Enumerable.EnumeratorBase<'U>(result, activity) let mutable idx = 0 let mutable array = Unchecked.defaultof<_> @@ -514,14 +514,14 @@ namespace Microsoft.FSharp.Collections let rec moveNext () = if (result.HaltedIdx = 0) && idx < array.Length then idx <- idx+1 - if seqComponent.ProcessNext array.[idx-1] then + if activity.ProcessNext array.[idx-1] then true else moveNext () else result.SeqState <- SeqProcessNextStates.Finished let mutable stopTailCall = () - (seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) + activity.ChainComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -529,20 +529,20 @@ namespace Microsoft.FSharp.Collections initMoveNext () moveNext () - type Enumerable<'T,'U>(delayedArray:unit->array<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + type Enumerable<'T,'U>(delayedArray:unit->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>(delayedArray, createFold current result pipeIdx, result)) + Upcast.enumerator (new Enumerator<'T,'U>(delayedArray, createFold transformFactory result pipeIdx, result)) interface ISeq<'U> with member __.PushTransform (next:TransformFactory<'U,'V>) : ISeq<'V> = - Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine current next, 1)) + Upcast.seq (new Enumerable<'T,'V>(delayedArray, ComposedFactory.Combine transformFactory next, 1)) member this.Fold<'Result,'State> (f:PipeIdx->Folder<'U,'Result,'State>) = - Fold.execute f current pipeIdx (Fold.Array (delayedArray ())) + Fold.execute f transformFactory pipeIdx (Fold.Array (delayedArray ())) let createDelayed (delayedArray:unit->array<'T>) (current:TransformFactory<'T,'U>) = Upcast.seq (Enumerable(delayedArray, current, 1)) @@ -557,15 +557,15 @@ namespace Microsoft.FSharp.Collections create array IdentityFactory.Instance module List = - type Enumerator<'T,'U>(alist:list<'T>, seqComponent:Activity<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) + 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 seqComponent.ProcessNext head then + if activity.ProcessNext head then list <- tail true else @@ -573,7 +573,7 @@ namespace Microsoft.FSharp.Collections | _ -> result.SeqState <- SeqProcessNextStates.Finished let mutable stopTailCall = () - (seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) + activity.ChainComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -581,27 +581,27 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext list - type Enumerable<'T,'U>(alist:list<'T>, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + 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 current result pipeIdx, result)) + 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 current next, pipeIdx+1)) + 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 current pipeIdx (Fold.List alist) + 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, seqComponent:Activity<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) + 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 @@ -609,7 +609,7 @@ namespace Microsoft.FSharp.Collections match result.HaltedIdx, generator current with | 0, Some (item, nextState) -> current <- nextState - if seqComponent.ProcessNext item then + if activity.ProcessNext item then true else moveNext () @@ -620,20 +620,20 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U,'GeneratorState>(generator:'GeneratorState->option<'T*'GeneratorState>, state:'GeneratorState, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + 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 current result pipeIdx, result)) + 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 current next, pipeIdx+1)) + 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 current pipeIdx (Fold.unfold (generator, 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 @@ -655,11 +655,11 @@ namespace Microsoft.FSharp.Collections else System.Int32.MaxValue - type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:Activity<'T,'U>, result:Result<'U>) = - inherit Enumerable.EnumeratorBase<'U>(result, seqComponent) + 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 seqComponent with + match box activity with | :? ISkipping as skip -> skip.Skipping | _ -> fun () -> false @@ -680,7 +680,7 @@ namespace Microsoft.FSharp.Collections if maybeSkipping then moveNext () - elif seqComponent.ProcessNext (f idx) then + elif activity.ProcessNext (f idx) then true else moveNext () @@ -689,7 +689,7 @@ namespace Microsoft.FSharp.Collections else result.SeqState <- SeqProcessNextStates.Finished let mutable stopTailCall = () - (seqComponent).ChainComplete (&stopTailCall, result.HaltedIdx) + activity.ChainComplete (&stopTailCall, result.HaltedIdx) false interface IEnumerator with @@ -697,21 +697,21 @@ namespace Microsoft.FSharp.Collections result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + 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 current result pipeIdx, result)) + 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 current next, pipeIdx+1)) + 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 current pipeIdx (Fold.init (f, terminatingIdx)) + Fold.execute createResult transformFactory pipeIdx (Fold.init (f, terminatingIdx)) let upto lastOption f = match lastOption with @@ -759,7 +759,7 @@ namespace Microsoft.FSharp.Collections setIndex (!index + 1) true ) - member self.Reset() = noReset() + member this.Reset() = noReset() interface System.IDisposable with member x.Dispose() = () } @@ -860,15 +860,15 @@ namespace Microsoft.FSharp.Collections 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 self.ProcessNext value = - if self.State.MoveNext() then - self.Result <- folder self.Result value self.State.Current + override this.ProcessNext value = + if this.State.MoveNext() then + this.Result <- folder this.Result value this.State.Current else - self.StopFurtherProcessing pipeIdx + this.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) - override self.OnComplete _ = () - override self.OnDispose () = self.State.Dispose() }) + override this.OnComplete _ = () + override this.OnDispose () = this.State.Dispose() }) [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = @@ -897,31 +897,31 @@ namespace Microsoft.FSharp.Collections let inline iter2 (f:'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = source1.Fold (fun pipeIdx -> upcast { new FolderWithPostProcessing<'T,NoValue,IEnumerator<'U>> (Unchecked.defaultof<_>,source2.GetEnumerator()) with - override self.ProcessNext value = - if self.State.MoveNext() then - f value self.State.Current + override this.ProcessNext value = + if this.State.MoveNext() then + f value this.State.Current else - self.StopFurtherProcessing pipeIdx + this.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) - override self.OnComplete _ = () - override self.OnDispose () = self.State.Dispose() }) + override this.OnComplete _ = () + override this.OnDispose () = this.State.Dispose() }) |> ignore [] let inline iteri2 (f:int->'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = source1.Fold (fun pipeIdx -> upcast { new FolderWithPostProcessing<'T,NoValue,Values>>(Unchecked.defaultof<_>,Values<_,_>(-1,source2.GetEnumerator())) with - override self.ProcessNext value = - if self.State._2.MoveNext() then - f self.State._1 value self.State._2.Current - self.State._1 <- self.State._1 + 1 + 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 - self.StopFurtherProcessing pipeIdx + this.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> - override self.OnComplete _ = () - override self.OnDispose () = self.State._2.Dispose() }) + override this.OnComplete _ = () + override this.OnDispose () = this.State._2.Dispose() }) |> ignore [] @@ -967,17 +967,17 @@ namespace Microsoft.FSharp.Collections 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 self.ProcessNext value = - if self.State.MoveNext() then - if predicate value self.State.Current then - self.Result <- true - self.StopFurtherProcessing pipeIdx + override this.ProcessNext value = + if this.State.MoveNext() then + if predicate value this.State.Current then + this.Result <- true + this.StopFurtherProcessing pipeIdx else - self.StopFurtherProcessing pipeIdx + this.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) - override self.OnComplete _ = () - override self.OnDispose () = self.State.Dispose() }) + override this.OnComplete _ = () + override this.OnDispose () = this.State.Dispose() }) [] let inline contains element (source:ISeq<'T>) = @@ -1003,17 +1003,17 @@ namespace Microsoft.FSharp.Collections 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 self.ProcessNext value = - if self.State.MoveNext() then - if not (predicate value self.State.Current) then - self.Result <- false - self.StopFurtherProcessing pipeIdx + override this.ProcessNext value = + if this.State.MoveNext() then + if not (predicate value this.State.Current) then + this.Result <- false + this.StopFurtherProcessing pipeIdx else - self.StopFurtherProcessing pipeIdx + this.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) - override self.OnComplete _ = () - override self.OnDispose () = self.State.Dispose() }) + override this.OnComplete _ = () + override this.OnDispose () = this.State.Dispose() }) [] let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = @@ -1046,14 +1046,14 @@ namespace Microsoft.FSharp.Collections source1.PushTransform { new TransformFactory<'First,'U>() with override __.Compose outOfBand pipeIdx (next:Activity<'U,'V>) = upcast { new TransformWithPostProcessing<'First,'V, IEnumerator<'Second>>(next, (source2.GetEnumerator ())) with - override self.ProcessNext input = - if self.State.MoveNext () then - TailCall.avoid (next.ProcessNext (map input self.State.Current)) + override this.ProcessNext input = + if this.State.MoveNext () then + TailCall.avoid (next.ProcessNext (map input this.State.Current)) else outOfBand.StopFurtherProcessing pipeIdx false - override self.OnComplete _ = () - override self.OnDispose () = self.State.Dispose () }} + override this.OnComplete _ = () + override this.OnDispose () = this.State.Dispose () }} [] let inline mapi2<'First,'Second,'U> (map:int -> 'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = @@ -1061,15 +1061,15 @@ namespace Microsoft.FSharp.Collections override __.Compose<'V> outOfBand pipeIdx next = upcast { new TransformWithPostProcessing<'First,'V, Values>> (next, Values<_,_>(-1, source2.GetEnumerator ())) with - override self.ProcessNext input = - if self.State._2.MoveNext () then - self.State._1 <- self.State._1 + 1 - TailCall.avoid (next.ProcessNext (map self.State._1 input self.State._2.Current)) + override this.ProcessNext input = + if this.State._2.MoveNext () then + this.State._1 <- this.State._1 + 1 + TailCall.avoid (next.ProcessNext (map this.State._1 input this.State._2.Current)) else outOfBand.StopFurtherProcessing pipeIdx false - override self.OnDispose () = self.State._2.Dispose () - override self.OnComplete _ = () }} + override this.OnDispose () = this.State._2.Dispose () + override this.OnComplete _ = () }} [] let inline map3<'First,'Second,'Third,'U> @@ -1078,35 +1078,35 @@ namespace Microsoft.FSharp.Collections override __.Compose<'V> outOfBand pipeIdx next = upcast { new TransformWithPostProcessing<'First,'V, Values,IEnumerator<'Third>>> (next, Values<_,_>(source2.GetEnumerator(),source3.GetEnumerator())) with - override self.ProcessNext input = - if self.State._1.MoveNext() && self.State._2.MoveNext () then - TailCall.avoid (next.ProcessNext (map input self.State._1 .Current self.State._2.Current)) + override this.ProcessNext input = + if this.State._1.MoveNext() && this.State._2.MoveNext () then + TailCall.avoid (next.ProcessNext (map input this.State._1 .Current this.State._2.Current)) else outOfBand.StopFurtherProcessing pipeIdx false - override self.OnComplete _ = () - override self.OnDispose () = - self.State._1.Dispose () - self.State._2.Dispose () }} + 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 self.ProcessNext value = - if not (self.State.MoveNext()) then - self.Result <- 1 - self.StopFurtherProcessing pipeIdx + override this.ProcessNext value = + if not (this.State.MoveNext()) then + this.Result <- 1 + this.StopFurtherProcessing pipeIdx else - let c = f value self.State.Current + let c = f value this.State.Current if c <> 0 then - self.Result <- c - self.StopFurtherProcessing pipeIdx + this.Result <- c + this.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> (* return value unused in Fold context *) - override self.OnComplete _ = - if self.Result = 0 && self.State.MoveNext() then - self.Result <- -1 - override self.OnDispose () = self.State.Dispose() }) + 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> = @@ -1153,7 +1153,7 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if this.State then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - override self.OnDispose () = () }) + override this.OnDispose () = () }) [] let inline maxBy (f :'T -> 'U) (source: ISeq<'T>) : 'T when 'U:comparison = @@ -1174,7 +1174,7 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if this.State._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - override self.OnDispose () = () }) + override this.OnDispose () = () }) [] let inline min (source: ISeq< 'T>) : 'T when 'T:comparison = @@ -1191,7 +1191,7 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if this.State then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - override self.OnDispose () = () }) + override this.OnDispose () = () }) [] let inline minBy (f : 'T -> 'U) (source: ISeq<'T>) : 'T = @@ -1212,7 +1212,7 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if this.State._1 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - override self.OnDispose () = () }) + override this.OnDispose () = () }) [] let pairwise (source:ISeq<'T>) : ISeq<'T*'T> = @@ -1225,14 +1225,14 @@ namespace Microsoft.FSharp.Collections ,(* lastValue = _2*) Unchecked.defaultof<'T> ) ) with - override self.ProcessNext (input:'T) : bool = - if (*isFirst*) self.State._1 then - self.State._2 (*lastValue*)<- input - self.State._1 (*isFirst*)<- false + override this.ProcessNext (input:'T) : bool = + if (*isFirst*) this.State._1 then + this.State._2 (*lastValue*)<- input + this.State._1 (*isFirst*)<- false false else - let currentPair = self.State._2, input - self.State._2 (*lastValue*)<- input + let currentPair = this.State._2, input + this.State._2 (*lastValue*)<- input TailCall.avoid (next.ProcessNext currentPair) }} [] @@ -1250,7 +1250,7 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if this.State then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - override self.OnDispose () = () }) + override this.OnDispose () = () }) [] let inline scan (folder:'State->'T->'State) (initialState:'State) (source:ISeq<'T>) :ISeq<'State> = @@ -1265,42 +1265,42 @@ namespace Microsoft.FSharp.Collections let skip (skipCount:int) (source:ISeq<'T>) : ISeq<'T> = source.PushTransform { new TransformFactory<'T,'T>() with override __.Compose _ _ next = - let mutable self = Unchecked.defaultof> + let mutable this = Unchecked.defaultof> let skipper = { new TransformWithPostProcessing<'T,'U,int>(next,(*count*)0) with - override self.ProcessNext (input:'T) : bool = - if (*count*) self.State < skipCount then - self.State <- self.State + 1 + override this.ProcessNext (input:'T) : bool = + if (*count*) this.State < skipCount then + this.State <- this.State + 1 false else TailCall.avoid (next.ProcessNext input) - override self.OnComplete _ = - if (*count*) self.State < skipCount then - let x = skipCount - self.State + override this.OnComplete _ = + if (*count*) 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 self.OnDispose () = () + override this.OnDispose () = () interface ISkipping with member __.Skipping () = - if (*count*) self.State < skipCount then - self.State <- self.State + 1 + if (*count*) this.State < skipCount then + this.State <- this.State + 1 true else false } - self <- skipper - upcast self } + 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 - override self.ProcessNext (input:'T) : bool = - if self.State (*skip*) then - self.State <- predicate input - if self.State (*skip*) then + override this.ProcessNext (input:'T) : bool = + if this.State (*skip*) then + this.State <- predicate input + if this.State (*skip*) then false else TailCall.avoid (next.ProcessNext input) @@ -1333,10 +1333,10 @@ namespace Microsoft.FSharp.Collections member __.Compose outOfBand pipelineIdx next = upcast { new TransformWithPostProcessing<'T,'U,int>(next,(*count*)0) with - override self.ProcessNext (input:'T) : bool = - if (*count*) self.State < takeCount then - self.State <- self.State + 1 - if self.State = takeCount then + override this.ProcessNext (input:'T) : bool = + if (*count*) this.State < takeCount then + this.State <- this.State + 1 + if this.State = takeCount then outOfBand.StopFurtherProcessing pipelineIdx TailCall.avoid (next.ProcessNext input) else @@ -1367,17 +1367,17 @@ namespace Microsoft.FSharp.Collections source.PushTransform { new TransformFactory<'T,'T>() with member __.Compose _ _ next = upcast { new TransformWithPostProcessing<'T,'V,bool>(next,(*first*) true) with - override self.ProcessNext (input:'T) : bool = - if (*first*) self.State then - self.State <- false + override this.ProcessNext (input:'T) : bool = + if (*first*) this.State then + this.State <- false false else TailCall.avoid (next.ProcessNext input) - override self.OnComplete _ = - if (*first*) self.State then + override this.OnComplete _ = + if (*first*) this.State then invalidArg "source" (SR.GetString SR.notEnoughElements) - override self.OnDispose () = () }} + override this.OnDispose () = () }} [] let truncate (truncateCount:int) (source:ISeq<'T>) : ISeq<'T> = @@ -1385,10 +1385,10 @@ namespace Microsoft.FSharp.Collections member __.Compose outOfBand pipeIdx next = upcast { new Transform<'T,'U,int>(next,(*count*)0) with - override self.ProcessNext (input:'T) : bool = - if (*count*) self.State < truncateCount then - self.State <- self.State + 1 - if self.State = truncateCount then + override this.ProcessNext (input:'T) : bool = + if (*count*) this.State < truncateCount then + this.State <- this.State + 1 + if this.State = truncateCount then outOfBand.StopFurtherProcessing pipeIdx TailCall.avoid (next.ProcessNext input) else @@ -1450,7 +1450,7 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if not this.State._1 then this.Result <- Some this.State._2 - override self.OnDispose () = () }) + override this.OnDispose () = () }) [] let windowed (windowSize:int) (source:ISeq<'T>) : ISeq<'T[]> = @@ -1465,24 +1465,24 @@ namespace Microsoft.FSharp.Collections ,(* priming = _3 *) windowSize-1 ) ) with - override self.ProcessNext (input:'T) : bool = - self.State._1.[(* idx *)self.State._2] <- input + override this.ProcessNext (input:'T) : bool = + this.State._1.[(* idx *)this.State._2] <- input - self.State._2 <- (* idx *)self.State._2 + 1 - if (* idx *) self.State._2 = windowSize then - self.State._2 <- 0 + this.State._2 <- (* idx *)this.State._2 + 1 + if (* idx *) this.State._2 = windowSize then + this.State._2 <- 0 - if (* priming *) self.State._3 > 0 then - self.State._3 <- self.State._3 - 1 + if (* priming *) this.State._3 > 0 then + this.State._3 <- this.State._3 - 1 false else if windowSize < 32 then - let window :'T [] = Array.init windowSize (fun i -> self.State._1.[((* idx *)self.State._2+i) % windowSize]: 'T) + let window :'T [] = Array.init windowSize (fun i -> this.State._1.[((* idx *)this.State._2+i) % windowSize]: 'T) TailCall.avoid (next.ProcessNext window) else let window = Array.zeroCreateUnchecked windowSize - Array.Copy((*circularBuffer*)self.State._1, (* idx *)self.State._2, window, 0, windowSize - (* idx *)self.State._2) - Array.Copy((*circularBuffer*)self.State._1, 0, window, windowSize - (* idx *)self.State._2, (* idx *)self.State._2) + Array.Copy((*circularBuffer*)this.State._1, (* idx *)this.State._2, window, 0, windowSize - (* idx *)this.State._2) + Array.Copy((*circularBuffer*)this.State._1, 0, window, windowSize - (* idx *)this.State._2, (* idx *)this.State._2) TailCall.avoid (next.ProcessNext window) }} [] From b7f01c0494215e91a898cb36794a33c8028b8add Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 27 Dec 2016 13:34:48 +1100 Subject: [PATCH 276/286] Consistency work; naming, spacing --- src/fsharp/FSharp.Core/seqcomposer.fs | 283 ++++++++++++-------------- 1 file changed, 131 insertions(+), 152 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 55471b4c310..066a7d320a8 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -161,10 +161,10 @@ namespace Microsoft.FSharp.Collections override __.Compose<'V> (_outOfBand:IOutOfBand) (_pipeIdx:PipeIdx) (next:Activity<'T,'V>) : Activity<'T,'V> = next static member Instance = singleton - and ISkipping = + and ISkipable = // Seq.init(Infinite)? lazily uses Current. The only Composer component that can do that is Skip // and it can only do it at the start of a sequence - abstract Skipping : unit -> bool + abstract CanSkip : unit -> bool type SeqProcessNextStates = | InProcess = 0 @@ -244,11 +244,11 @@ namespace Microsoft.FSharp.Collections let firstIdx = match box consumer with - | :? ISkipping as skipping -> + | :? ISkipable as skipping -> let rec skip idx = if idx = terminatingIdx || outOfBand.HaltedIdx <> 0 then terminatingIdx - elif skipping.Skipping () then + elif skipping.CanSkip () then skip (idx+1) else idx @@ -309,7 +309,7 @@ namespace Microsoft.FSharp.Collections [] type EnumeratorBase<'T>(result:Result<'T>, activity:Activity) = interface IDisposable with - member __.Dispose() : unit = + member __.Dispose () : unit = let mutable stopTailCall = () activity.ChainDispose (&stopTailCall) @@ -369,7 +369,7 @@ namespace Microsoft.FSharp.Collections moveNext () interface IDisposable with - member __.Dispose() = + member __.Dispose () = try source.Dispose () finally @@ -438,7 +438,7 @@ namespace Microsoft.FSharp.Collections member __.Reset () = noReset () interface IDisposable with - member __.Dispose() = + member __.Dispose () = main.Dispose () active.Dispose () @@ -660,7 +660,7 @@ namespace Microsoft.FSharp.Collections let isSkipping = match box activity with - | :? ISkipping as skip -> skip.Skipping + | :? ISkipable as skip -> skip.CanSkip | _ -> fun () -> false let terminatingIdx = @@ -761,7 +761,7 @@ namespace Microsoft.FSharp.Collections ) member this.Reset() = noReset() interface System.IDisposable with - member x.Dispose() = () } + member x.Dispose () = () } type EnumerableDecider<'T>(count:Nullable, f:int->'T, pipeIdx:PipeIdx) = inherit Enumerable.EnumerableBase<'T>() @@ -790,12 +790,9 @@ namespace Microsoft.FSharp.Collections | _ -> Upcast.seq (Enumerable.EnumerableThin<'T> source) [] - let 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) = + let inline average (source:ISeq<'T>) = source.Fold (fun _ -> - upcast { new FolderWithPostProcessing< ^T, ^T, int> (LanguagePrimitives.GenericZero, 0) with + 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 @@ -804,16 +801,13 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if this.State = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - this.Result <- LanguagePrimitives.DivideByInt< ^T> this.Result this.State + this.Result <- LanguagePrimitives.DivideByInt<'T> this.Result this.State override this.OnDispose () = () }) [] - let 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) = + let inline averageBy (f:'T->'U) (source:ISeq<'T>) = source.Fold (fun _ -> - upcast { new FolderWithPostProcessing<'T,'U, int>(LanguagePrimitives.GenericZero, 0) with + 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 @@ -822,7 +816,7 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if this.State = 0 then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - this.Result <- LanguagePrimitives.DivideByInt< ^U> this.Result this.State + this.Result <- LanguagePrimitives.DivideByInt<'U> this.Result this.State override this.OnDispose () = () }) [] @@ -868,7 +862,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = () - override this.OnDispose () = this.State.Dispose() }) + override this.OnDispose () = this.State.Dispose () }) [] let unfold (generator:'State->option<'T * 'State>) (state:'State) : ISeq<'T> = @@ -887,16 +881,15 @@ namespace Microsoft.FSharp.Collections [] let inline iter f (source:ISeq<'T>) = source.Fold (fun _ -> - upcast { new Folder<'T,NoValue,NoValue> (Unchecked.defaultof,Unchecked.defaultof) with + upcast { new Folder<'T,unit,NoValue> ((),Unchecked.defaultof) with override this.ProcessNext value = f value Unchecked.defaultof<_> (* return value unused in Fold context *) }) - |> ignore [] let inline iter2 (f:'T->'U->unit) (source1:ISeq<'T>) (source2:ISeq<'U>) : unit = source1.Fold (fun pipeIdx -> - upcast { new FolderWithPostProcessing<'T,NoValue,IEnumerator<'U>> (Unchecked.defaultof<_>,source2.GetEnumerator()) with + upcast { new FolderWithPostProcessing<'T,unit,IEnumerator<'U>> ((),source2.GetEnumerator()) with override this.ProcessNext value = if this.State.MoveNext() then f value this.State.Current @@ -905,13 +898,12 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = () - override this.OnDispose () = this.State.Dispose() }) - |> ignore + 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,NoValue,Values>>(Unchecked.defaultof<_>,Values<_,_>(-1,source2.GetEnumerator())) with + 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 @@ -921,8 +913,7 @@ namespace Microsoft.FSharp.Collections this.StopFurtherProcessing pipeIdx Unchecked.defaultof<_> override this.OnComplete _ = () - override this.OnDispose () = this.State._2.Dispose() }) - |> ignore + override this.OnDispose () = this.State._2.Dispose () }) [] let tryHead (source:ISeq<'T>) = @@ -936,22 +927,19 @@ namespace Microsoft.FSharp.Collections [] let inline iteri f (source:ISeq<'T>) = source.Fold (fun _ -> - { new Folder<'T,NoValue,int> (Unchecked.defaultof<_>,0) with + { 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 *) }) - |> ignore [] 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 + upcast { new Transform<'T,'V,Lazy>>(next,lazy(HashSet<'T>(itemsToExclude,HashIdentity.Structural<'T>))) with override this.ProcessNext (input:'T) : bool = - if this.State.Value.Add input then TailCall.avoid (next.ProcessNext input) - else false }} + this.State.Value.Add input && TailCall.avoid (next.ProcessNext input) }} [] let inline exists f (source:ISeq<'T>) = @@ -977,7 +965,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = () - override this.OnDispose () = this.State.Dispose() }) + override this.OnDispose () = this.State.Dispose () }) [] let inline contains element (source:ISeq<'T>) = @@ -1013,7 +1001,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unused in Fold context *) override this.OnComplete _ = () - override this.OnDispose () = this.State.Dispose() }) + override this.OnDispose () = this.State.Dispose () }) [] let inline filter<'T> (f:'T->bool) (source:ISeq<'T>) : ISeq<'T> = @@ -1042,10 +1030,10 @@ namespace Microsoft.FSharp.Collections TailCall.avoid (next.ProcessNext (f this.State input)) } } [] - let inline map2<'First,'Second,'U> (map:'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = - source1.PushTransform { new TransformFactory<'First,'U>() with - override __.Compose outOfBand pipeIdx (next:Activity<'U,'V>) = - upcast { new TransformWithPostProcessing<'First,'V, IEnumerator<'Second>>(next, (source2.GetEnumerator ())) with + 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)) @@ -1056,15 +1044,16 @@ namespace Microsoft.FSharp.Collections override this.OnDispose () = this.State.Dispose () }} [] - let inline mapi2<'First,'Second,'U> (map:int -> 'First->'Second->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) : ISeq<'U> = - source1.PushTransform { new TransformFactory<'First,'U>() with - override __.Compose<'V> outOfBand pipeIdx next = - upcast { new TransformWithPostProcessing<'First,'V, Values>> - (next, Values<_,_>(-1, source2.GetEnumerator ())) with - override this.ProcessNext input = - if this.State._2.MoveNext () then - this.State._1 <- this.State._1 + 1 - TailCall.avoid (next.ProcessNext (map this.State._1 input this.State._2.Current)) + 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 @@ -1072,15 +1061,15 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = () }} [] - let inline map3<'First,'Second,'Third,'U> - (map:'First->'Second->'Third->'U) (source1:ISeq<'First>) (source2:ISeq<'Second>) (source3:ISeq<'Third>) : ISeq<'U> = - source1.PushTransform { new TransformFactory<'First,'U>() with - override __.Compose<'V> outOfBand pipeIdx next = - upcast { new TransformWithPostProcessing<'First,'V, Values,IEnumerator<'Third>>> - (next, Values<_,_>(source2.GetEnumerator(),source3.GetEnumerator())) with - override this.ProcessNext input = - if this.State._1.MoveNext() && this.State._2.MoveNext () then - TailCall.avoid (next.ProcessNext (map input this.State._1 .Current this.State._2.Current)) + 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 @@ -1090,7 +1079,7 @@ namespace Microsoft.FSharp.Collections this.State._2.Dispose () }} [] - let inline compareWith (f:'T -> 'T -> int) (source1 :ISeq<'T>) (source2:ISeq<'T>) : int = + 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 = @@ -1106,7 +1095,7 @@ namespace Microsoft.FSharp.Collections override this.OnComplete _ = if this.Result = 0 && this.State.MoveNext() then this.Result <- -1 - override this.OnDispose () = this.State.Dispose() }) + override this.OnDispose () = this.State.Dispose () }) [] let inline choose (f:'T->option<'U>) (source:ISeq<'T>) : ISeq<'U> = @@ -1122,24 +1111,20 @@ namespace Microsoft.FSharp.Collections 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<'T>(HashIdentity.Structural<'T>))) with + upcast { new Transform<'T,'V,HashSet<'T>>(next,HashSet HashIdentity.Structural) with override this.ProcessNext (input:'T) : bool = - if this.State.Add input then TailCall.avoid (next.ProcessNext input) - else false } } + 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<'Key>(HashIdentity.Structural<'Key>))) with + upcast { new Transform<'T,'V,HashSet<'Key>> (next,HashSet HashIdentity.Structural) with override this.ProcessNext (input:'T) : bool = - if this.State.Add (keyf input) then TailCall.avoid (next.ProcessNext input) - else false } } + this.State.Add (keyf input) && TailCall.avoid (next.ProcessNext input) }} [] - let inline max (source: ISeq<'T>) : 'T when 'T:comparison = + 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 = @@ -1156,7 +1141,7 @@ namespace Microsoft.FSharp.Collections override this.OnDispose () = () }) [] - let inline maxBy (f :'T -> 'U) (source: ISeq<'T>) : 'T when 'U:comparison = + 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 = @@ -1177,7 +1162,7 @@ namespace Microsoft.FSharp.Collections override this.OnDispose () = () }) [] - let inline min (source: ISeq< 'T>) : 'T when 'T:comparison = + 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 = @@ -1194,7 +1179,7 @@ namespace Microsoft.FSharp.Collections override this.OnDispose () = () }) [] - let inline minBy (f : 'T -> 'U) (source: ISeq<'T>) : 'T = + 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 = @@ -1218,21 +1203,17 @@ namespace Microsoft.FSharp.Collections 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 - ((* isFirst = _1*) true - ,(* lastValue = _2*) Unchecked.defaultof<'T> - ) - ) with + 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 (*isFirst*) this.State._1 then - this.State._2 (*lastValue*)<- input - this.State._1 (*isFirst*)<- false + if this.State._1 then + this.State._2 <- input + this.State._1 <- false false else let currentPair = this.State._2, input - this.State._2 (*lastValue*)<- input + this.State._2 <- input TailCall.avoid (next.ProcessNext currentPair) }} [] @@ -1268,23 +1249,24 @@ namespace Microsoft.FSharp.Collections 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 (*count*) this.State < skipCount then + if this.State < skipCount then this.State <- this.State + 1 false else TailCall.avoid (next.ProcessNext input) override this.OnComplete _ = - if (*count*) this.State < skipCount then + 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 ISkipping with - member __.Skipping () = - if (*count*) this.State < skipCount then + interface ISkipable with + member __.CanSkip () = + if this.State < skipCount then this.State <- this.State + 1 true else @@ -1297,10 +1279,11 @@ namespace Microsoft.FSharp.Collections 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 (*skip*) then + if this.State then this.State <- predicate input - if this.State (*skip*) then + if this.State then false else TailCall.avoid (next.ProcessNext input) @@ -1308,21 +1291,17 @@ namespace Microsoft.FSharp.Collections TailCall.avoid (next.ProcessNext input) }} [] - let inline sum (source:ISeq< ^T>) : ^T - when ^T:(static member Zero : ^T) - and ^T:(static member (+) : ^T * ^T -> ^T) = + let inline sum (source:ISeq<'T>) = source.Fold (fun _ -> - upcast { new Folder< ^T,^T,NoValue> (LanguagePrimitives.GenericZero,Unchecked.defaultof) with + 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>) : ^U - when ^U:(static member Zero : ^U) - and ^U:(static member (+) : ^U * ^U -> ^U) = + let inline sumBy (f:'T->'U) (source:ISeq<'T>) = source.Fold (fun _ -> - upcast { new Folder<'T,'U,NoValue> (LanguagePrimitives.GenericZero< ^U>,Unchecked.defaultof) with + 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 *) }) @@ -1331,24 +1310,24 @@ 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 = - upcast { - new TransformWithPostProcessing<'T,'U,int>(next,(*count*)0) with - override this.ProcessNext (input:'T) : bool = - if (*count*) this.State < takeCount then - this.State <- this.State + 1 - if this.State = takeCount then - outOfBand.StopFurtherProcessing pipelineIdx - TailCall.avoid (next.ProcessNext input) - else + 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 - false + 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 () = () }} + 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> = @@ -1366,16 +1345,16 @@ namespace Microsoft.FSharp.Collections let tail (source:ISeq<'T>) :ISeq<'T> = source.PushTransform { new TransformFactory<'T,'T>() with member __.Compose _ _ next = - upcast { new TransformWithPostProcessing<'T,'V,bool>(next,(*first*) true) with + upcast { new TransformWithPostProcessing<'T,'V,bool>(next,true) with + // member this.isFirst = this.State override this.ProcessNext (input:'T) : bool = - if (*first*) this.State then + if this.State then this.State <- false false else TailCall.avoid (next.ProcessNext input) - override this.OnComplete _ = - if (*first*) this.State then + if this.State then invalidArg "source" (SR.GetString SR.notEnoughElements) override this.OnDispose () = () }} @@ -1383,17 +1362,17 @@ namespace Microsoft.FSharp.Collections 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 - override this.ProcessNext (input:'T) : bool = - if (*count*) this.State < truncateCount then - this.State <- this.State + 1 - if this.State = truncateCount then - outOfBand.StopFurtherProcessing pipeIdx - TailCall.avoid (next.ProcessNext input) - else + 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 - false }} + TailCall.avoid (next.ProcessNext input) + else + outOfBand.StopFurtherProcessing pipeIdx + false }} [] let indexed source = @@ -1430,6 +1409,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 + // member this.index = this.State override this.ProcessNext value = if predicate value then this.Result <- Some this.State @@ -1442,6 +1422,8 @@ namespace Microsoft.FSharp.Collections let inline 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 @@ -1457,33 +1439,30 @@ namespace Microsoft.FSharp.Collections 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> - ((*circularBuffer = _1 *) Array.zeroCreateUnchecked windowSize - ,(* idx = _2 *) 0 - ,(* priming = _3 *) windowSize-1 - ) - ) with + 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 = - this.State._1.[(* idx *)this.State._2] <- input + let circularBuffer = this.State._1 + let idx : byref<_> = &this.State._2 + let priming : byref<_> = &this.State._3 + + circularBuffer.[idx] <- input - this.State._2 <- (* idx *)this.State._2 + 1 - if (* idx *) this.State._2 = windowSize then - this.State._2 <- 0 + idx <- idx + 1 + if idx = windowSize then + idx <- 0 - if (* priming *) this.State._3 > 0 then - this.State._3 <- this.State._3 - 1 + 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 - if windowSize < 32 then - let window :'T [] = Array.init windowSize (fun i -> this.State._1.[((* idx *)this.State._2+i) % windowSize]: 'T) - TailCall.avoid (next.ProcessNext window) - else - let window = Array.zeroCreateUnchecked windowSize - Array.Copy((*circularBuffer*)this.State._1, (* idx *)this.State._2, window, 0, windowSize - (* idx *)this.State._2) - Array.Copy((*circularBuffer*)this.State._1, 0, window, windowSize - (* idx *)this.State._2, (* idx *)this.State._2) - TailCall.avoid (next.ProcessNext window) }} + 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> = From 8313ea91a1c973f32ef2d5f79dc3ab7fdd7834d7 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 27 Dec 2016 19:36:29 +1100 Subject: [PATCH 277/286] Composer.groupBy(Ref|Val) --- src/fsharp/FSharp.Core/seq.fs | 48 ++------ src/fsharp/FSharp.Core/seqcomposer.fs | 146 ++++++++++++++++++++++++- src/fsharp/FSharp.Core/seqcomposer.fsi | 36 +++++- 3 files changed, 181 insertions(+), 49 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 666fc06519b..7f5c1713e89 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -498,50 +498,20 @@ namespace Microsoft.FSharp.Collections checkNonNull "source" source mkSeq (fun () -> source.GetEnumerator()) - let inline groupByImpl (comparer:IEqualityComparer<'SafeKey>) (keyf:'T->'SafeKey) (getKey:'SafeKey->'Key) (seq:seq<'T>) = - checkNonNull "seq" seq - - let dict = Dictionary<_,ResizeArray<_>> comparer - - // Previously this was 1, but I think this is rather stingy, considering that we are already paying - // for at least a key, the ResizeArray reference, which includes an array reference, an Entry in the - // Dictionary, plus any empty space in the Dictionary of unfilled hash buckets. - let minimumBucketSize = 4 - - // Build the groupings - seq |> iter (fun v -> - let safeKey = keyf v - let mutable prev = Unchecked.defaultof<_> - match dict.TryGetValue (safeKey, &prev) with - | true -> prev.Add v - | false -> - let prev = ResizeArray () - dict.[safeKey] <- prev - prev.Add v) - - // Trim the size of each result group, don't trim very small buckets, as excessive work, and garbage for - // minimal gain - dict |> iter (fun group -> if group.Value.Count > minimumBucketSize then group.Value.TrimExcess()) - - // Return the sequence-of-sequences. Don't reveal the - // internal collections: just reveal them as sequences - dict |> map (fun group -> (getKey group.Key, readonly group.Value)) - - // We avoid wrapping a StructBox, because under 64 JIT we get some "hard" tailcalls which affect performance - let groupByValueType (keyf:'T->'Key) (seq:seq<'T>) = seq |> groupByImpl HashIdentity.Structural<'Key> keyf id - - // Wrap a StructBox around all keys in case the key type is itself a type using null as a representation - let groupByRefType (keyf:'T->'Key) (seq:seq<'T>) = seq |> groupByImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun t -> RuntimeHelpers.StructBox (keyf t)) (fun sb -> sb.Value) - [] let groupBy (keyf:'T->'Key) (seq:seq<'T>) = + let grouped = #if FX_RESHAPED_REFLECTION - if (typeof<'Key>).GetTypeInfo().IsValueType + if (typeof<'Key>).GetTypeInfo().IsValueType #else - if typeof<'Key>.IsValueType + if typeof<'Key>.IsValueType #endif - then mkDelayedSeq (fun () -> groupByValueType keyf seq) - else mkDelayedSeq (fun () -> groupByRefType keyf seq) + then seq |> toComposer |> Composer.groupByVal' keyf + else seq |> toComposer |> Composer.groupByRef' keyf + + grouped + |> Composer.map (fun (key,value) -> key, Upcast.enumerable value) + |> Upcast.enumerable [] let distinct source = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 066a7d320a8..d05cb1ee39e 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -23,6 +23,11 @@ namespace Microsoft.FSharp.Collections [] type NoValue = struct end + [] + type Value<'a> = + val mutable _1 : 'a + new (a:'a) = { _1 = a } + [] type Values<'a,'b> = val mutable _1 : 'a @@ -208,6 +213,18 @@ namespace Microsoft.FSharp.Collections 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 @@ -404,6 +421,19 @@ namespace Microsoft.FSharp.Collections 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 () @@ -474,7 +504,7 @@ namespace Microsoft.FSharp.Collections Fold.executeThin f (Fold.enumerable this) let create enumerable current = - Upcast.seq (Enumerable(enumerable, current, 1)) + Upcast.seq (Enumerable (enumerable, current, 1)) module EmptyEnumerable = type Enumerable<'T> () = @@ -556,6 +586,45 @@ namespace Microsoft.FSharp.Collections let createId (array:array<'T>) = create array IdentityFactory.Instance + 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) @@ -780,14 +849,26 @@ namespace Microsoft.FSharp.Collections 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> = + Upcast.seq (Array.Enumerable ((fun () -> 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 s -> s - | :? array<'T> as a -> Upcast.seq (Array.Enumerable((fun () -> a), IdentityFactory.Instance, 1)) - | :? list<'T> as a -> Upcast.seq (List.Enumerable(a, IdentityFactory.Instance, 1)) - | null -> nullArg "source" - | _ -> Upcast.seq (Enumerable.EnumerableThin<'T> source) + | :? 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>) = @@ -1473,3 +1554,56 @@ namespace Microsoft.FSharp.Collections match source1 with | :? Enumerable.EnumerableBase<'T> as s -> s.Append source2 | _ -> Upcast.seq (new Enumerable.AppendEnumerable<_>([source2; source1])) + + [] + let delayed (delayed:unit->ISeq<'T>) = + Upcast.seq (Enumerable.SeqDelayed (delayed, 1)) + + let inline groupByImpl (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 groupByVal' (keyf:'T->'Key) (source:ISeq<'T>) = + delayed (fun () -> + source + |> groupByImpl HashIdentity.Structural<'Key> keyf id) + + let inline groupByRef' (keyf:'T->'Key) (source:ISeq<'T>) = + delayed (fun () -> + let comparer = + let c = HashIdentity.Structural<'Key> + { new IEqualityComparer> with + member __.GetHashCode o = c.GetHashCode o._1 + member __.Equals (lhs,rhs) = c.Equals (lhs._1, rhs._1) } + source + |> groupByImpl comparer (fun t -> Value(keyf t)) (fun sb -> sb._1)) + + [] + let inline groupByVal<'T,'Key when 'Key : equality and 'T : struct> (keyf:'T->'Key) (source:ISeq<'T>) = + groupByVal' keyf source + + [] + let inline groupByRef<'T,'Key when 'Key : equality and 'T : not struct> (keyf:'T->'Key) (source:ISeq<'T>) = + groupByRef' keyf source + diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 6cab705cbff..36e399c3f67 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -14,6 +14,13 @@ 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. + [] + 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. [] @@ -105,8 +112,17 @@ namespace Microsoft.FSharp.Collections open Core + [] + val ofResizeArrayUnchecked : ResizeArray<'T> -> ISeq<'T> + + [] + val ofList : list<'T> -> ISeq<'T> + + [] + val ofArray : array<'T> -> ISeq<'T> + [] - val ofSeq : source:seq<'T> -> ISeq<'T> + val ofSeq : seq<'T> -> ISeq<'T> [] val inline average : source: ISeq< ^T> -> ^T @@ -274,15 +290,27 @@ namespace Microsoft.FSharp.Collections [] val windowed : windowSize:int -> source:ISeq<'T> -> ISeq<'T[]> - [] + [] val concat : sources:ISeq<'Collection> -> ISeq<'T> when 'Collection :> ISeq<'T> - [] + [] val append: source1:ISeq<'T> -> source2:ISeq<'T> -> ISeq<'T> + [] + val delayed : (unit -> ISeq<'T>) -> ISeq<'T> + + val inline internal groupByVal' : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * ISeq<'T>> when 'Key : equality + val inline internal groupByRef' : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * ISeq<'T>> when 'Key : equality + + [] + val inline groupByVal : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * ISeq<'T>> when 'Key : equality and 'T : struct + + [] + val inline groupByRef : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * ISeq<'T>> when 'Key : equality and 'T : not struct + module internal Array = begin val createDelayed : (unit -> 'T array) -> TransformFactory<'T,'U> -> ISeq<'U> val create : 'T array -> TransformFactory<'T,'U> -> ISeq<'U> val createDelayedId : (unit -> 'T array) -> ISeq<'T> val createId : 'T array -> ISeq<'T> - end + end \ No newline at end of file From c977ab189d68b229e0528014b09821a1a7ceb111 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 28 Dec 2016 14:04:10 +1100 Subject: [PATCH 278/286] Fixed constraint (applied on wrong argument) --- src/fsharp/FSharp.Core/seqcomposer.fs | 4 ++-- src/fsharp/FSharp.Core/seqcomposer.fsi | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index d05cb1ee39e..cb922b9da6e 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -1600,10 +1600,10 @@ namespace Microsoft.FSharp.Collections |> groupByImpl comparer (fun t -> Value(keyf t)) (fun sb -> sb._1)) [] - let inline groupByVal<'T,'Key when 'Key : equality and 'T : struct> (keyf:'T->'Key) (source:ISeq<'T>) = + let inline groupByVal<'T,'Key when 'Key : equality and 'Key : struct> (keyf:'T->'Key) (source:ISeq<'T>) = groupByVal' keyf source [] - let inline groupByRef<'T,'Key when 'Key : equality and 'T : not struct> (keyf:'T->'Key) (source:ISeq<'T>) = + let inline groupByRef<'T,'Key when 'Key : equality and 'Key : not struct> (keyf:'T->'Key) (source:ISeq<'T>) = groupByRef' keyf source diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 36e399c3f67..57e02eed60f 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -303,10 +303,10 @@ namespace Microsoft.FSharp.Collections val inline internal groupByRef' : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * ISeq<'T>> when 'Key : equality [] - val inline groupByVal : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * ISeq<'T>> when 'Key : equality and 'T : struct + 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 'T : not struct + val inline groupByRef : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * ISeq<'T>> when 'Key : equality and 'Key : not struct module internal Array = begin val createDelayed : (unit -> 'T array) -> TransformFactory<'T,'U> -> ISeq<'U> From a2780c296988a79cdfb71bf598b7734ca56056a3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 28 Dec 2016 17:05:21 +1100 Subject: [PATCH 279/286] Added module for GroupBy - also renamed delayed as delay to match seq --- src/fsharp/FSharp.Core/seq.fs | 4 +- src/fsharp/FSharp.Core/seqcomposer.fs | 85 +++++++++++++------------- src/fsharp/FSharp.Core/seqcomposer.fsi | 11 ++-- 3 files changed, 51 insertions(+), 49 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 7f5c1713e89..580556eec0e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -506,8 +506,8 @@ namespace Microsoft.FSharp.Collections #else if typeof<'Key>.IsValueType #endif - then seq |> toComposer |> Composer.groupByVal' keyf - else seq |> toComposer |> Composer.groupByRef' keyf + then seq |> toComposer |> Composer.GroupBy.byVal keyf + else seq |> toComposer |> Composer.GroupBy.byRef keyf grouped |> Composer.map (fun (key,value) -> key, Upcast.enumerable value) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index cb922b9da6e..d4c7cd852ff 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -1555,55 +1555,56 @@ namespace Microsoft.FSharp.Collections | :? Enumerable.EnumerableBase<'T> as s -> s.Append source2 | _ -> Upcast.seq (new Enumerable.AppendEnumerable<_>([source2; source1])) - [] - let delayed (delayed:unit->ISeq<'T>) = + [] + let delay (delayed:unit->ISeq<'T>) = Upcast.seq (Enumerable.SeqDelayed (delayed, 1)) - let inline groupByImpl (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 () + module internal GroupBy = + let inline groupByImpl (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 *) - this.Result <- - this.State - |> ofSeq - |> map (fun kv -> getKey kv.Key, ofResizeArrayUnchecked kv.Value) - - override this.OnDispose () = () }) - - let inline groupByVal' (keyf:'T->'Key) (source:ISeq<'T>) = - delayed (fun () -> - source - |> groupByImpl HashIdentity.Structural<'Key> keyf id) - - let inline groupByRef' (keyf:'T->'Key) (source:ISeq<'T>) = - delayed (fun () -> - let comparer = - let c = HashIdentity.Structural<'Key> - { new IEqualityComparer> with - member __.GetHashCode o = c.GetHashCode o._1 - member __.Equals (lhs,rhs) = c.Equals (lhs._1, rhs._1) } - source - |> groupByImpl comparer (fun t -> Value(keyf t)) (fun sb -> sb._1)) + 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 () -> + source + |> groupByImpl HashIdentity.Structural<'Key> keyf id) + + let inline byRef (keyf:'T->'Key) (source:ISeq<'T>) = + delay (fun () -> + let comparer = + let c = HashIdentity.Structural<'Key> + { new IEqualityComparer> with + member __.GetHashCode o = c.GetHashCode o._1 + member __.Equals (lhs,rhs) = c.Equals (lhs._1, rhs._1) } + source + |> groupByImpl comparer (fun t -> Value(keyf t)) (fun sb -> sb._1)) [] let inline groupByVal<'T,'Key when 'Key : equality and 'Key : struct> (keyf:'T->'Key) (source:ISeq<'T>) = - groupByVal' keyf source + GroupBy.byVal keyf source [] let inline groupByRef<'T,'Key when 'Key : equality and 'Key : not struct> (keyf:'T->'Key) (source:ISeq<'T>) = - groupByRef' keyf source + GroupBy.byRef keyf source diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 57e02eed60f..96ec17b37d5 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -296,11 +296,8 @@ namespace Microsoft.FSharp.Collections [] val append: source1:ISeq<'T> -> source2:ISeq<'T> -> ISeq<'T> - [] - val delayed : (unit -> ISeq<'T>) -> ISeq<'T> - - val inline internal groupByVal' : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * ISeq<'T>> when 'Key : equality - val inline internal groupByRef' : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * ISeq<'T>> when 'Key : equality + [] + 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 @@ -308,6 +305,10 @@ namespace Microsoft.FSharp.Collections [] val inline groupByRef : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * ISeq<'T>> when 'Key : equality and 'Key : not struct + 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 Array = begin val createDelayed : (unit -> 'T array) -> TransformFactory<'T,'U> -> ISeq<'U> val create : 'T array -> TransformFactory<'T,'U> -> ISeq<'U> From 479b628d1373c59c0862bba76db6cf3afc08829d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 28 Dec 2016 19:15:06 +1100 Subject: [PATCH 280/286] Moved Array based function to Composer sorts/rev/permute --- src/fsharp/FSharp.Core/seq.fs | 52 +++------------- src/fsharp/FSharp.Core/seqcomposer.fs | 85 +++++++++++++++++--------- src/fsharp/FSharp.Core/seqcomposer.fsi | 25 +++++--- 3 files changed, 83 insertions(+), 79 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 580556eec0e..9ae45b8a7cd 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -46,6 +46,7 @@ namespace Microsoft.FSharp.Collections [] let toComposer (source:seq<'T>): Composer.Core.ISeq<'T> = + checkNonNull "source" source Composer.ofSeq source [] @@ -320,23 +321,11 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source : 'T array) = checkNonNull "source" source - Upcast.enumerable (Composer.Array.createId source) + Upcast.enumerable (Composer.ofArray source) [] let toArray (source : seq<'T>) = - checkNonNull "source" source - 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 = Array.zeroCreateUnchecked res.Count - res.CopyTo(arr, 0) - arr - | _ -> - let res = ResizeArray<_>(source) - res.ToArray() + source |> toComposer |> Composer.toArray let foldArraySubRight (f:OptimizedClosures.FSharpFunc<'T,_,_>) (arr: 'T[]) start fin acc = let mutable state = acc @@ -523,30 +512,15 @@ namespace Microsoft.FSharp.Collections [] let sortBy keyf source = - checkNonNull "source" source - let delayedSort () = - let array = source |> toArray - Array.stableSortInPlaceBy keyf array - array - Upcast.enumerable (Composer.Array.createDelayedId delayedSort) + source |> toComposer |> Composer.sortBy keyf |> Upcast.enumerable [] let sort source = - checkNonNull "source" source - let delayedSort () = - let array = source |> toArray - Array.stableSortInPlace array - array - Upcast.enumerable (Composer.Array.createDelayedId delayedSort) + source |> toComposer |> Composer.sort |> Upcast.enumerable [] let sortWith f source = - checkNonNull "source" source - let delayedSort () = - let array = source |> toArray - Array.stableSortInPlaceWith f array - array - Upcast.enumerable (Composer.Array.createDelayedId delayedSort) + source |> toComposer |> Composer.sortWith f |> Upcast.enumerable [] let inline sortByDescending keyf source = @@ -715,21 +689,11 @@ namespace Microsoft.FSharp.Collections [] let rev source = - checkNonNull "source" source - let delayedReverse () = - let array = source |> toArray - Array.Reverse array - array - Upcast.enumerable (Composer.Array.createDelayedId delayedReverse) + source |> toComposer |> Composer.rev |> Upcast.enumerable [] let permute f (source:seq<_>) = - checkNonNull "source" source - let delayedPermute () = - source - |> toArray - |> Array.permute f - Upcast.enumerable (Composer.Array.createDelayedId delayedPermute) + source |> toComposer |> Composer.permute f |> Upcast.enumerable [] let mapFold<'T,'State,'Result> (f: 'State -> 'T -> 'Result * 'State) acc source = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index d4c7cd852ff..f044471e023 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -527,19 +527,10 @@ namespace Microsoft.FSharp.Collections Fold.executeThin f (Fold.enumerable this) module Array = - type Enumerator<'T,'U>(delayedArray:unit->array<'T>, activity:Activity<'T,'U>, result:Result<'U>) = + 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 mutable array = Unchecked.defaultof<_> - - let mutable initMoveNext = Unchecked.defaultof<_> - do - initMoveNext <- - fun () -> - result.SeqState <- SeqProcessNextStates.InProcess - array <- delayedArray () - initMoveNext <- ignore let rec moveNext () = if (result.HaltedIdx = 0) && idx < array.Length then @@ -556,35 +547,23 @@ namespace Microsoft.FSharp.Collections interface IEnumerator with member __.MoveNext () = - initMoveNext () + result.SeqState <- SeqProcessNextStates.InProcess moveNext () - type Enumerable<'T,'U>(delayedArray:unit->array<'T>, transformFactory:TransformFactory<'T,'U>, pipeIdx:PipeIdx) = + 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>(delayedArray, createFold transformFactory result pipeIdx, result)) + 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>(delayedArray, ComposedFactory.Combine transformFactory next, 1)) + 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 (delayedArray ())) - - let createDelayed (delayedArray:unit->array<'T>) (current:TransformFactory<'T,'U>) = - Upcast.seq (Enumerable(delayedArray, current, 1)) - - let create (array:array<'T>) (current:TransformFactory<'T,'U>) = - createDelayed (fun () -> array) current - - let createDelayedId (delayedArray:unit -> array<'T>) = - createDelayed delayedArray IdentityFactory.Instance - - let createId (array:array<'T>) = - create array IdentityFactory.Instance + Fold.execute f transformFactory pipeIdx (Fold.Array array) module ResizeArray = type Enumerator<'T,'U>(array:ResizeArray<'T>, activity:Activity<'T,'U>, result:Result<'U>) = @@ -855,7 +834,7 @@ namespace Microsoft.FSharp.Collections [] let ofArray (source:array<'T>) : ISeq<'T> = - Upcast.seq (Array.Enumerable ((fun () -> source), IdentityFactory.Instance, 1)) + Upcast.seq (Array.Enumerable (source, IdentityFactory.Instance, 1)) [] let ofList (source:list<'T>) : ISeq<'T> = @@ -1608,3 +1587,53 @@ namespace Microsoft.FSharp.Collections let inline groupByRef<'T,'Key when 'Key : equality and 'Key : not struct> (keyf:'T->'Key) (source:ISeq<'T>) = GroupBy.byRef keyf source + [] + let toArray (source:ISeq<'T>) = + match box 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 = Array.zeroCreateUnchecked res.Count + res.CopyTo(arr, 0) + arr + | _ -> + let res = ResizeArray source + res.ToArray() + + [] + let sortBy keyf source = + delay (fun () -> + let array = source |> toArray + Array.stableSortInPlaceBy keyf array + Upcast.seq (Array.Enumerable (array, IdentityFactory.Instance, 1))) + + [] + let sort source = + delay (fun () -> + let array = source |> toArray + Array.stableSortInPlace array + Upcast.seq (Array.Enumerable (array, IdentityFactory.Instance, 1))) + + [] + let sortWith f source = + delay (fun () -> + let array = source |> toArray + Array.stableSortInPlaceWith f array + Upcast.seq (Array.Enumerable (array, IdentityFactory.Instance, 1))) + + [] + let rev source = + delay (fun () -> + let array = source |> toArray + Array.Reverse array + Upcast.seq (Array.Enumerable (array, IdentityFactory.Instance, 1))) + + [] + let permute f (source:ISeq<_>) = + delay (fun () -> + source + |> toArray + |> Array.permute f + |> fun array -> Upcast.seq (Array.Enumerable (array, IdentityFactory.Instance, 1))) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 96ec17b37d5..b139fe98d4b 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -305,13 +305,24 @@ namespace Microsoft.FSharp.Collections [] val inline groupByRef : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * ISeq<'T>> when 'Key : equality and 'Key : not struct + [] + val toArray: source:ISeq<'T> -> '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> + 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 Array = begin - val createDelayed : (unit -> 'T array) -> TransformFactory<'T,'U> -> ISeq<'U> - val create : 'T array -> TransformFactory<'T,'U> -> ISeq<'U> - val createDelayedId : (unit -> 'T array) -> ISeq<'T> - val createId : 'T array -> ISeq<'T> - end \ No newline at end of file From 64786bb3eeef805eff35bb0a29bcf6943348634f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Dec 2016 15:27:17 +1100 Subject: [PATCH 281/286] ToArray via Fold - and moved creating Value comparer to a helper function --- src/fsharp/FSharp.Core/seqcomposer.fs | 29 +++++++++++++++------------ 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index f044471e023..5678ce1160f 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -151,6 +151,12 @@ namespace Microsoft.FSharp.Collections 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>() @@ -1565,19 +1571,10 @@ namespace Microsoft.FSharp.Collections override this.OnDispose () = () }) let inline byVal (keyf:'T->'Key) (source:ISeq<'T>) = - delay (fun () -> - source - |> groupByImpl HashIdentity.Structural<'Key> keyf id) + delay (fun () -> groupByImpl HashIdentity.Structural<'Key> keyf id source) let inline byRef (keyf:'T->'Key) (source:ISeq<'T>) = - delay (fun () -> - let comparer = - let c = HashIdentity.Structural<'Key> - { new IEqualityComparer> with - member __.GetHashCode o = c.GetHashCode o._1 - member __.Equals (lhs,rhs) = c.Equals (lhs._1, rhs._1) } - source - |> groupByImpl comparer (fun t -> Value(keyf t)) (fun sb -> sb._1)) + delay (fun () -> groupByImpl (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>) = @@ -1599,8 +1596,14 @@ namespace Microsoft.FSharp.Collections res.CopyTo(arr, 0) arr | _ -> - let res = ResizeArray source - res.ToArray() + 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 = From 32a9b995c098606e4d20598ca77f139441c8a838 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Dec 2016 15:39:25 +1100 Subject: [PATCH 282/286] null checks handled in toComposer --- src/fsharp/FSharp.Core/seq.fs | 53 +++++++++++------------------------ 1 file changed, 16 insertions(+), 37 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 9ae45b8a7cd..7683191d60b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -49,6 +49,10 @@ namespace Microsoft.FSharp.Collections checkNonNull "source" source Composer.ofSeq source + let toComposer' name (source:seq<'T>): Composer.Core.ISeq<'T> = + checkNonNull name source + Composer.ofSeq source + [] let delay f = mkDelayedSeq f @@ -121,22 +125,16 @@ namespace Microsoft.FSharp.Collections [] let iter2 (f:'T->'U->unit) (source1 : seq<'T>) (source2 : seq<'U>) = - checkNonNull "source1" source1 - checkNonNull "source2" source2 let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - (source1|>toComposer, source2|>toComposer) + (source1 |> toComposer' "source1", source2 |> toComposer' "source2") ||> Composer.iter2 (fun a b -> f.Invoke(a,b)) - [] let iteri2 (f:int->'T->'U->unit) (source1 : seq<_>) (source2 : seq<_>) = - checkNonNull "source1" source1 - checkNonNull "source2" source2 let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) - (source1|>toComposer, source2|>toComposer) + (source1 |> toComposer' "source1", source2 |> toComposer' "source2") ||> Composer.iteri2 (fun idx a b -> f.Invoke(idx,a,b)) - // Build an IEnumerble by wrapping/transforming iterators as they get generated. let revamp f (ie : seq<_>) = mkSeq (fun () -> f (ie.GetEnumerator())) let revamp2 f (ie1 : seq<_>) (source2 : seq<_>) = @@ -162,24 +160,18 @@ namespace Microsoft.FSharp.Collections [] let mapi2 (mapfn:int->'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) = - checkNonNull "source1" source1 - checkNonNull "source2" source2 let f = OptimizedClosures.FSharpFunc.Adapt mapfn - (source1|>toComposer, source2|>toComposer) + (source1 |> toComposer' "source1", source2 |> toComposer' "source2") ||> Composer.mapi2 (fun idx a b ->f.Invoke(idx,a,b)) |> Upcast.enumerable [] let map2<'T,'U,'V> (mapfn:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> = - checkNonNull "source1" source1 - checkNonNull "source2" source2 - (source1|>toComposer, source2|>toComposer) + (source1 |> toComposer' "source1", source2 |> toComposer' "source2") ||> Composer.map2 mapfn |> Upcast.enumerable [] let map3 mapfn source1 source2 source3 = - checkNonNull "source2" source2 - checkNonNull "source3" source3 - (source1|>toComposer, source2|>toComposer, source3|>toComposer) + (source1 |> toComposer' "source1", source2 |> toComposer' "source2", source3 |> toComposer' "source3") |||> Composer.map3 mapfn |> Upcast.enumerable [] @@ -243,8 +235,7 @@ namespace Microsoft.FSharp.Collections [] let concat (sources:seq<#seq<'T>>) : seq<'T> = - checkNonNull "sources" sources - sources |> toComposer |> Composer.map toComposer |> Composer.concat |> Upcast.enumerable + sources |> toComposer' "sources" |> Composer.map toComposer |> Composer.concat |> Upcast.enumerable [] let length (source : seq<'T>) = @@ -269,10 +260,8 @@ namespace Microsoft.FSharp.Collections [] let fold2<'T1,'T2,'State> f (state:'State) (source1: seq<'T1>) (source2: seq<'T2>) = - checkNonNull "source1" source1 - checkNonNull "source2" source2 let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) - (source1 |> toComposer, source2|>toComposer) + (source1 |> toComposer' "source1", source2 |> toComposer' "source2") ||> Composer.fold2(fun s a b -> f.Invoke(s,a,b)) state [] @@ -289,25 +278,20 @@ namespace Microsoft.FSharp.Collections seq { for _ in 1 .. count -> x } #endif - [] let append (source1: seq<'T>) (source2: seq<'T>) = - checkNonNull "source1" source1 - checkNonNull "source2" source2 - Composer.append (toComposer source1) (toComposer source2) |> Upcast.enumerable + (source1 |> toComposer' "source1", source2 |> toComposer' "source2") + ||> Composer.append |> Upcast.enumerable [] let collect f sources = map f sources |> concat [] let compareWith (f:'T -> 'T -> int) (source1 : seq<'T>) (source2: seq<'T>) = - checkNonNull "source1" source1 - checkNonNull "source2" source2 let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) - (source1|>toComposer, source2|>toComposer) + (source1 |> toComposer' "source1", source2 |> toComposer' "source2") ||> Composer.compareWith (fun a b -> f.Invoke(a,b)) - [] let ofList (source : 'T list) = (source :> seq<'T>) @@ -642,18 +626,14 @@ namespace Microsoft.FSharp.Collections [] let forall2 p (source1: seq<_>) (source2: seq<_>) = - checkNonNull "source1" source1 - checkNonNull "source2" source2 let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt p - (source1|>toComposer, source2|>toComposer) + (source1 |> toComposer' "source1", source2 |> toComposer' "source2") ||> Composer.forall2 (fun a b -> p.Invoke(a,b)) [] let exists2 p (source1: seq<_>) (source2: seq<_>) = - checkNonNull "source1" source1 - checkNonNull "source2" source2 let p = OptimizedClosures.FSharpFunc<_,_,_>.Adapt p - (source1|>toComposer, source2|>toComposer) + (source1 |> toComposer' "source1", source2 |> toComposer' "source2") ||> Composer.exists2 (fun a b -> p.Invoke(a,b)) [] @@ -710,7 +690,6 @@ namespace Microsoft.FSharp.Collections [] let except (itemsToExclude: seq<'T>) (source: seq<'T>) = - checkNonNull "itemsToExclude" itemsToExclude if isEmpty itemsToExclude then source else source |> toComposer |> Composer.except itemsToExclude |> Upcast.enumerable From b68df175c82b6164c7394cff5abf2ec334900c62 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Dec 2016 16:10:11 +1100 Subject: [PATCH 283/286] countBy --- src/fsharp/FSharp.Core/seq.fs | 33 ++++----------------- src/fsharp/FSharp.Core/seqcomposer.fs | 40 ++++++++++++++++++++++++-- src/fsharp/FSharp.Core/seqcomposer.fsi | 10 +++++++ 3 files changed, 52 insertions(+), 31 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 7683191d60b..f79e22cdaee 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -472,15 +472,15 @@ namespace Microsoft.FSharp.Collections mkSeq (fun () -> source.GetEnumerator()) [] - let groupBy (keyf:'T->'Key) (seq:seq<'T>) = + let groupBy (keyf:'T->'Key) (source:seq<'T>) = let grouped = #if FX_RESHAPED_REFLECTION if (typeof<'Key>).GetTypeInfo().IsValueType #else if typeof<'Key>.IsValueType #endif - then seq |> toComposer |> Composer.GroupBy.byVal keyf - else seq |> toComposer |> Composer.GroupBy.byRef keyf + then source |> toComposer |> Composer.GroupBy.byVal keyf + else source |> toComposer |> Composer.GroupBy.byRef keyf grouped |> Composer.map (fun (key,value) -> key, Upcast.enumerable value) @@ -518,38 +518,15 @@ namespace Microsoft.FSharp.Collections let inline compareDescending a b = compare b a sortWith compareDescending source - let inline countByImpl (comparer:IEqualityComparer<'SafeKey>) (keyf:'T->'SafeKey) (getKey:'SafeKey->'Key) (source:seq<'T>) = - checkNonNull "source" source - - let dict = Dictionary comparer - - // Build the groupings - source |> iter (fun v -> - let safeKey = keyf v - let mutable prev = Unchecked.defaultof<_> - if dict.TryGetValue(safeKey, &prev) - then dict.[safeKey] <- prev + 1 - else dict.[safeKey] <- 1) - - dict |> map (fun group -> (getKey group.Key, group.Value)) - - // We avoid wrapping a StructBox, because under 64 JIT we get some "hard" tailcalls which affect performance - let countByValueType (keyf:'T->'Key) (seq:seq<'T>) = seq |> countByImpl HashIdentity.Structural<'Key> keyf id - - // Wrap a StructBox around all keys in case the key type is itself a type using null as a representation - let countByRefType (keyf:'T->'Key) (seq:seq<'T>) = seq |> countByImpl RuntimeHelpers.StructBox<'Key>.Comparer (fun t -> RuntimeHelpers.StructBox (keyf t)) (fun sb -> sb.Value) - [] let countBy (keyf:'T->'Key) (source:seq<'T>) = - checkNonNull "source" source - #if FX_RESHAPED_REFLECTION if (typeof<'Key>).GetTypeInfo().IsValueType #else if typeof<'Key>.IsValueType #endif - then mkDelayedSeq (fun () -> countByValueType keyf source) - else mkDelayedSeq (fun () -> countByRefType keyf source) + then source |> toComposer |> Composer.CountBy.byVal keyf |> Upcast.enumerable + else source |> toComposer |> Composer.CountBy.byRef keyf |> Upcast.enumerable [] let inline sum (source:seq<'a>) : 'a = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 5678ce1160f..1a3fa49f063 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -1545,7 +1545,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (Enumerable.SeqDelayed (delayed, 1)) module internal GroupBy = - let inline groupByImpl (comparer:IEqualityComparer<'SafeKey>) (keyf:'T->'SafeKey) (getKey:'SafeKey->'Key) (source:ISeq<'T>) = + 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 = @@ -1571,10 +1571,10 @@ namespace Microsoft.FSharp.Collections override this.OnDispose () = () }) let inline byVal (keyf:'T->'Key) (source:ISeq<'T>) = - delay (fun () -> groupByImpl HashIdentity.Structural<'Key> keyf id source) + delay (fun () -> impl HashIdentity.Structural<'Key> keyf id source) let inline byRef (keyf:'T->'Key) (source:ISeq<'T>) = - delay (fun () -> groupByImpl (valueComparer<'Key> ()) (keyf >> Value) (fun v -> v._1) source) + 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>) = @@ -1584,6 +1584,40 @@ namespace Microsoft.FSharp.Collections 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 toArray (source:ISeq<'T>) = match box source with diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index b139fe98d4b..03ab21f9394 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -305,6 +305,12 @@ namespace Microsoft.FSharp.Collections [] 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 toArray: source:ISeq<'T> -> 'T[] @@ -326,3 +332,7 @@ namespace Microsoft.FSharp.Collections 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 dddc8dc7dcba0d437a7f58d0d3b7917eb19136c7 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Dec 2016 19:27:04 +1100 Subject: [PATCH 284/286] Remove comented minValBy/maxValBy --- src/fsharp/FSharp.Core/seq.fs | 35 +---------------------------------- 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index f79e22cdaee..c1d6abb482d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -551,23 +551,7 @@ namespace Microsoft.FSharp.Collections [] let inline minBy (projection: 'T -> 'U when 'U:comparison) (source: seq<'T>) : 'T = source |> toComposer |> Composer.minBy projection -(* - [] - let inline minValBy (f : 'T -> 'U) (source: seq<'T>) : 'U = - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" InputSequenceEmptyString - let first = e.Current - let mutable acc = f first - while e.MoveNext() do - let currv = e.Current - let curr = f currv - if curr < acc then - acc <- curr - acc - -*) + [] let inline max (source: seq<'T>) = source |> toComposer |> Composer.max @@ -576,23 +560,6 @@ namespace Microsoft.FSharp.Collections let inline maxBy (projection: 'T -> 'U) (source: seq<'T>) : 'T = source |> toComposer |> Composer.maxBy projection -(* - [] - let inline maxValBy (f : 'T -> 'U) (source: seq<'T>) : 'U = - checkNonNull "source" source - use e = source.GetEnumerator() - if not (e.MoveNext()) then - invalidArg "source" InputSequenceEmptyString - let first = e.Current - let mutable acc = f first - while e.MoveNext() do - let currv = e.Current - let curr = f currv - if curr > acc then - acc <- curr - acc - -*) [] let takeWhile predicate (source: seq<_>) = source |> toComposer |> Composer.takeWhile predicate |> Upcast.enumerable From ed74c52e1c09f6300fa4aeae64a10d9c171af9b2 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Dec 2016 19:40:55 +1100 Subject: [PATCH 285/286] head/last into Composer - more consistency formatting --- src/fsharp/FSharp.Core/seq.fs | 8 +-- src/fsharp/FSharp.Core/seqcomposer.fs | 24 ++++++--- src/fsharp/FSharp.Core/seqcomposer.fsi | 74 ++++++++++++++------------ 3 files changed, 60 insertions(+), 46 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index c1d6abb482d..ab333fe3e0b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -582,9 +582,7 @@ namespace Microsoft.FSharp.Collections [] let head (source : seq<_>) = - match tryHead source with - | None -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - | Some x -> x + source |> toComposer |> Composer.head [] let tail (source: seq<'T>) = @@ -596,9 +594,7 @@ namespace Microsoft.FSharp.Collections [] let last (source : seq<_>) = - match tryLast source with - | None -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - | Some x -> x + source |> toComposer |> Composer.last [] let exactlyOne (source : seq<_>) = diff --git a/src/fsharp/FSharp.Core/seqcomposer.fs b/src/fsharp/FSharp.Core/seqcomposer.fs index 1a3fa49f063..0026fa3a2b8 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fs +++ b/src/fsharp/FSharp.Core/seqcomposer.fs @@ -917,7 +917,7 @@ namespace Microsoft.FSharp.Collections 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>) = + 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 = @@ -990,6 +990,12 @@ namespace Microsoft.FSharp.Collections 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 _ -> @@ -1018,7 +1024,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] - let inline exists2 (predicate:'T->'U->bool) (source1: ISeq<'T>) (source2: ISeq<'U>) : bool = + 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 = @@ -1283,7 +1289,7 @@ namespace Microsoft.FSharp.Collections TailCall.avoid (next.ProcessNext currentPair) }} [] - let inline reduce (f:'T->'T->'T) (source : ISeq<'T>) : 'T = + 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 = @@ -1408,7 +1414,7 @@ namespace Microsoft.FSharp.Collections false }} [] - let tail (source:ISeq<'T>) :ISeq<'T> = + 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 @@ -1485,7 +1491,7 @@ namespace Microsoft.FSharp.Collections Unchecked.defaultof<_> (* return value unused in Fold context *) }) [] - let inline tryLast (source :ISeq<'T>) : 'T option = + 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 @@ -1500,6 +1506,12 @@ namespace Microsoft.FSharp.Collections 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[]> = source.PushTransform { new TransformFactory<'T,'T[]>() with @@ -1535,7 +1547,7 @@ namespace Microsoft.FSharp.Collections Upcast.seq (Enumerable.ConcatEnumerable sources) [] - let append (source1: ISeq<'T>) (source2: ISeq<'T>) : ISeq<'T> = + 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])) diff --git a/src/fsharp/FSharp.Core/seqcomposer.fsi b/src/fsharp/FSharp.Core/seqcomposer.fsi index 03ab21f9394..1df1b9ee772 100644 --- a/src/fsharp/FSharp.Core/seqcomposer.fsi +++ b/src/fsharp/FSharp.Core/seqcomposer.fsi @@ -113,16 +113,16 @@ namespace Microsoft.FSharp.Collections open Core [] - val ofResizeArrayUnchecked : ResizeArray<'T> -> ISeq<'T> + val ofResizeArrayUnchecked : ResizeArray<'T> -> ISeq<'T> [] - val ofList : list<'T> -> ISeq<'T> + val ofList : list<'T> -> ISeq<'T> [] - val ofArray : array<'T> -> ISeq<'T> + val ofArray : array<'T> -> ISeq<'T> [] - val ofSeq : seq<'T> -> ISeq<'T> + val ofSeq : seq<'T> -> ISeq<'T> [] val inline average : source: ISeq< ^T> -> ^T @@ -149,16 +149,16 @@ namespace Microsoft.FSharp.Collections val inline fold2<'T1,'T2,'State> : folder:('State->'T1->'T2->'State) -> state:'State -> source1: ISeq<'T1> -> source2: ISeq<'T2> -> 'State [] - val unfold : generator:('State -> ('T * 'State) option) -> state:'State -> ISeq<'T> + val unfold : generator:('State -> option<'T*'State>) -> state:'State -> ISeq<'T> [] - val initInfinite : f:(int -> 'T) -> ISeq<'T> + val initInfinite : f:(int -> 'T) -> ISeq<'T> [] - val init : count:int -> 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 iter : f:('T -> unit) -> source:ISeq<'T> -> unit [] val inline iter2 : f:('T->'U->unit) -> source1 : ISeq<'T> -> source2 : ISeq<'U> -> unit @@ -167,76 +167,79 @@ namespace Microsoft.FSharp.Collections val inline iteri2 : f:(int->'T->'U->unit) -> source1:ISeq<'T> -> source2:ISeq<'U> -> unit [] - val tryHead : ISeq<'T> -> 'T option + 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 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 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 contains : element:'T -> source:ISeq<'T> -> bool when 'T : equality [] - val inline forall : f:('T -> bool) -> source: ISeq<'T> -> bool + 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 filter : f:('T -> bool) -> source:ISeq<'T> -> ISeq<'T> [] - val inline map : f:('T -> 'U) -> source: ISeq<'T> -> ISeq<'U> + 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<'First,'Second,'U> : map:('First->'Second->'U) -> source1:ISeq<'First> -> source2:ISeq<'Second> -> ISeq<'U> + val inline map2<'T,'U,'V> : map:('T->'U->'V) -> source1:ISeq<'T> -> source2:ISeq<'U> -> ISeq<'V> [] - val inline mapi2<'First,'Second,'U> : map:(int -> 'First->'Second->'U) -> source1:ISeq<'First> -> source2:ISeq<'Second> -> ISeq<'U> + val inline mapi2<'T,'U,'V> : map:(int -> 'T->'U->'V) -> source1:ISeq<'T> -> source2:ISeq<'U> -> ISeq<'V> [] - val inline map3<'First,'Second,'Third,'U> : map:('First->'Second->'Third->'U) -> source1:ISeq<'First> -> source2:ISeq<'Second> -> source3:ISeq<'Third> -> ISeq<'U> + 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 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 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 distinctBy : keyf:('T->'Key) -> source:ISeq<'T> -> ISeq<'T> when 'Key:equality [] - val inline max : source: ISeq<'T> -> 'T when 'T:comparison + 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 maxBy : f:('T->'U) -> source:ISeq<'T> -> 'T when 'U:comparison [] - val inline min : source: ISeq<'T> -> 'T when 'T: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 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 reduce : f:('T->'T->'T) -> source:ISeq<'T> -> 'T [] val inline scan : folder:('State->'T->'State) -> initialState:'State -> source:ISeq<'T> -> ISeq<'State> @@ -253,7 +256,7 @@ namespace Microsoft.FSharp.Collections and 'T:(static member (+) : ^T * ^T -> ^T) [] - val inline sumBy : f :('T -> ^U) -> source: ISeq<'T> -> ^U + val inline sumBy : f :('T -> ^U) -> source:ISeq<'T> -> ^U when ^U:(static member Zero : ^U) and ^U:(static member (+) : ^U * ^U -> ^U) @@ -273,22 +276,25 @@ namespace Microsoft.FSharp.Collections val indexed : source: ISeq<'a> -> ISeq [] - val tryItem : index:int -> source: ISeq<'T> -> 'T option + val tryItem : index:int -> source:ISeq<'T> -> option<'T> [] - val inline tryPick : f:('T -> 'U option) -> source: ISeq<'T> -> Option<'U> + 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 tryFind : f:('T -> bool) -> source:ISeq<'T> -> option<'T> [] - val inline tryFindIndex: predicate:('T->bool) -> source:ISeq<'T> -> int option + val inline tryFindIndex: predicate:('T->bool) -> source:ISeq<'T> -> option + + [] + val last: source:ISeq<'T> -> 'T [] - val inline tryLast : source:ISeq<'T> -> 'T option + val tryLast : source:ISeq<'T> -> option<'T> [] - val windowed : windowSize:int -> source:ISeq<'T> -> ISeq<'T[]> + val windowed : windowSize:int -> source:ISeq<'T> -> ISeq> [] val concat : sources:ISeq<'Collection> -> ISeq<'T> when 'Collection :> ISeq<'T> @@ -312,7 +318,7 @@ namespace Microsoft.FSharp.Collections val inline countByRef : projection:('T -> 'Key) -> source:ISeq<'T> -> ISeq<'Key * int> when 'Key : equality and 'Key : not struct [] - val toArray: source:ISeq<'T> -> 'T[] + val toArray: source:ISeq<'T> -> array<'T> [] val sortBy : projection:('T->'Key) -> source:ISeq<'T> -> ISeq<'T> when 'Key : comparison From 1e37872be9e7f6235d0ccf5cda0af7b712e52a5a Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sat, 4 Mar 2017 10:07:28 +0100 Subject: [PATCH 286/286] fix compile issue --- src/fsharp/FSharp.Core/seq.fs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ab333fe3e0b..8aba11bd9ac 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -600,13 +600,6 @@ namespace Microsoft.FSharp.Collections let exactlyOne (source : seq<_>) = source |> toComposer |> Composer.exactlyOne - member this.OnComplete _ = - if this.Value._1 then - invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString - elif this.Value._3 then - invalidArg "source" (SR.GetString(SR.inputSequenceTooLong)) }) - |> fun one -> one.Value._2 - [] let rev source = source |> toComposer |> Composer.rev |> Upcast.enumerable