From d24b92874e297eb6f795741cfece681d8bc62243 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 28 Sep 2016 19:42:15 +1000 Subject: [PATCH 001/327] 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 ddf73fb5cc1..bbe26ef30ab 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 @@ -108,18 +317,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) @@ -215,23 +412,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 @@ -963,17 +1143,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 = @@ -1257,15 +1441,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 44e4266184b00aa000c4ce91a66c6e3f40e5ca4c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Sep 2016 16:05:23 +1000 Subject: [PATCH 002/327] 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 33929d183b5f7b975b09c242fc760c666dde236c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Sep 2016 18:05:20 +1000 Subject: [PATCH 003/327] 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 bbe26ef30ab..60282de76fe 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 @@ -1022,6 +812,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 @@ -1142,27 +1321,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 = @@ -1246,16 +1428,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>) = @@ -1442,10 +1618,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>) = @@ -1883,14 +2056,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 33864577d82714b73ff29ee53b664ce7dd4a5f3c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Sep 2016 18:49:22 +1000 Subject: [PATCH 004/327] 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 60282de76fe..0e1022bc3f1 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -812,8 +812,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 @@ -1152,21 +1152,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>() @@ -1183,22 +1183,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 8173087960f301c8ea886869172b1047139fa5fc Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Sep 2016 19:59:49 +1000 Subject: [PATCH 005/327] 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 0e1022bc3f1..50f59dafef1 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -854,7 +854,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 @@ -1012,6 +1012,7 @@ namespace Microsoft.FSharp.Collections if count < takeCount then count <- count + 1 output <- input + halted <- count = takeCount true else halted <- true @@ -1037,6 +1038,7 @@ namespace Microsoft.FSharp.Collections elif count < endIdx then count <- count + 1 output <- input + halted <- count = endIdx true else halted <- true From 4beba0085a6dc0f09b95f8ec5300ced8bc46bd0d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 2 Oct 2016 18:26:16 +1100 Subject: [PATCH 006/327] 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 50f59dafef1..3910f3f6332 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1095,8 +1095,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 @@ -1132,8 +1131,7 @@ namespace Microsoft.FSharp.Collections match state with | SeqProcessNextStates.NotStarted -> notStarted() | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> () - current + | _ -> current [] type ComposableEnumerable<'T> () = From f34b5000a504e595daedf3f0da98500a48c0b64e Mon Sep 17 00:00:00 2001 From: liboz Date: Mon, 3 Oct 2016 16:34:00 -0400 Subject: [PATCH 007/327] 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 3910f3f6332..72d3bdaea04 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -833,21 +833,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>() @@ -870,16 +870,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 @@ -902,17 +902,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 @@ -923,7 +923,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 = @@ -931,12 +931,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 = @@ -946,7 +946,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 @@ -973,10 +973,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) @@ -1002,9 +1002,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) @@ -1026,7 +1026,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 @@ -1053,13 +1053,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 @@ -1078,7 +1087,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<_> @@ -1091,13 +1100,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 @@ -1117,7 +1126,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 @@ -1127,7 +1136,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() @@ -1141,7 +1186,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 ()) @@ -1172,7 +1217,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 ()) @@ -1200,6 +1245,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 @@ -1326,6 +1385,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>) = @@ -1367,8 +1427,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 96e4dc912b197e1ae4e6a49a5a5192cba001db30 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 4 Oct 2016 20:00:31 +1100 Subject: [PATCH 008/327] 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 72d3bdaea04..e2467d25473 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -827,6 +827,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 @@ -1093,7 +1097,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 () @@ -1129,7 +1133,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 () @@ -1186,16 +1190,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 = @@ -1217,16 +1221,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 = @@ -1384,9 +1388,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 12fbe9946c0a12ec079736df8e1c27956e157703 Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 4 Oct 2016 22:13:24 -0400 Subject: [PATCH 009/327] 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 e2467d25473..75588427834 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -107,21 +107,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 a294c86f55de9e9ee36ea661161152017c136ce5 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 5 Oct 2016 10:09:17 -0400 Subject: [PATCH 010/327] 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 75588427834..3d1b6a0903c 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1042,7 +1042,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>() @@ -2096,11 +2124,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<_>) = @@ -2108,15 +2132,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 19879ea4e18b1ade29a76f6c9711df75b457f58b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 7 Oct 2016 20:18:45 +1100 Subject: [PATCH 011/327] 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 3d1b6a0903c..4936a6bf0a4 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -816,167 +816,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 @@ -984,25 +954,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 @@ -1013,73 +974,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 @@ -1197,13 +1131,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 ()) @@ -1211,8 +1145,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 = @@ -1230,11 +1164,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 ()) @@ -1242,8 +1176,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 = @@ -1262,11 +1196,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 ()) @@ -1274,8 +1208,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 @@ -1405,23 +1339,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 = @@ -1444,7 +1375,7 @@ namespace Microsoft.FSharp.Collections [] let choose f source = - source |> seqFactoryForImmutable (SeqComposer.Choose f) + source |> seqFactory (SeqComposer.ChooseFactory f) [] let indexed source = @@ -1507,7 +1438,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>) = @@ -1694,7 +1625,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>) = @@ -2124,15 +2055,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 896f01d2d3726bd147ccb8c13341ccf4df8c8f01 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 7 Oct 2016 20:30:18 +1100 Subject: [PATCH 012/327] 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 4936a6bf0a4..97e0c919788 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -818,8 +818,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 ed56658be342232985581c5f401b7d5a1a769383 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Oct 2016 06:55:59 +1100 Subject: [PATCH 013/327] 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 97e0c919788..2608ce8a27e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -816,107 +816,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>() @@ -924,7 +940,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 @@ -932,19 +948,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 @@ -952,18 +968,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 () = @@ -972,44 +1004,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 = @@ -1017,16 +1026,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 () @@ -1053,19 +1060,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 () @@ -1089,20 +1094,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 () @@ -1125,7 +1128,7 @@ namespace Microsoft.FSharp.Collections match state with | SeqProcessNextStates.NotStarted -> notStarted() | SeqProcessNextStates.Finished -> alreadyFinished() - | _ -> current + | _ -> result.Current [] type ComposableEnumerable<'T> () = @@ -1135,7 +1138,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 ()) @@ -1166,7 +1170,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 ()) @@ -1198,7 +1203,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 72a651aef1125282c36566d8dda4cd40cdbc8556 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Oct 2016 10:36:05 +1100 Subject: [PATCH 014/327] 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 2608ce8a27e..d79d81945f1 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -890,7 +890,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 512f90d0b5ca13667ce1bd34ee7f8017e03105fe Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Oct 2016 19:35:08 +1100 Subject: [PATCH 015/327] 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 d79d81945f1..04d763c1c79 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -929,10 +929,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>() @@ -1155,14 +1156,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 @@ -1187,14 +1188,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 61d886a76bf9db9e945d9c4bfdec1dd2c1ca5a71 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Oct 2016 20:19:46 +1100 Subject: [PATCH 016/327] 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 04d763c1c79..b29e64202a8 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -816,9 +816,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 @@ -1022,15 +1029,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 @@ -1039,32 +1056,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 @@ -1076,77 +1081,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))) @@ -1170,15 +1156,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))) @@ -1202,15 +1183,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 8ce97ee17964a86bcecf24bf64891404267bc06e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Oct 2016 20:38:54 +1100 Subject: [PATCH 017/327] 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 b29e64202a8..8e64a12307d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1126,16 +1126,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 = @@ -1153,16 +1165,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 = @@ -1180,16 +1192,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 17b3464ef3574cbd6e6f3ecba7e151e9f18401d7 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 05:36:56 +1100 Subject: [PATCH 018/327] 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 8e64a12307d..98298a14914 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -877,12 +877,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) @@ -963,6 +969,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 @@ -1203,6 +1216,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 @@ -1225,12 +1311,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 8cf65123d0b3bb8ebf4725e73eab192f172222da Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 06:00:07 +1100 Subject: [PATCH 019/327] 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 98298a14914..8aa873a869a 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -816,63 +816,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 @@ -1004,7 +998,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 @@ -1013,10 +1007,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 () = @@ -1025,25 +1019,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 = () @@ -1054,62 +1057,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 @@ -1117,13 +1120,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 [] @@ -1147,17 +1150,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)) @@ -1183,8 +1186,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)) @@ -1210,8 +1213,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)) @@ -1226,8 +1229,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 @@ -1241,7 +1244,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 @@ -1253,16 +1256,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>) = @@ -1270,8 +1273,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 04d8b39fe54e700ee6845532d6a5b77d37edbebd Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 06:12:42 +1100 Subject: [PATCH 020/327] 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 8aa873a869a..2e1584a2c7a 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1045,6 +1045,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 @@ -1062,73 +1064,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> @@ -1154,6 +1089,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) @@ -1170,17 +1129,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) @@ -1197,17 +1180,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) @@ -1219,6 +1227,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 f1792619d79514635d03db3457d7ee04fa803760 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 06:32:14 +1100 Subject: [PATCH 021/327] 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 2e1584a2c7a..8bac6bfed9a 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1262,7 +1262,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 beaedd5b285c766bbbd19d4e2e647431905488e9 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 08:19:24 +1100 Subject: [PATCH 022/327] 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 8bac6bfed9a..b29e64202a8 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -816,73 +816,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) @@ -963,13 +963,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 @@ -998,7 +991,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 @@ -1007,10 +1000,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 () = @@ -1019,36 +1012,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 = () @@ -1059,147 +1041,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 @@ -1207,102 +1104,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 @@ -1326,14 +1213,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 71d273a8f980f834f5f39cf98f4f10a5df61252b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 13:32:57 +1100 Subject: [PATCH 023/327] 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 b29e64202a8..4596e6b1700 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -878,11 +878,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) @@ -963,6 +969,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 @@ -1192,6 +1205,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 @@ -1213,12 +1302,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 496d637fd371b205f702a81ec85e02f069768d59 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 14:12:59 +1100 Subject: [PATCH 024/327] 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 4596e6b1700..325cfcd3166 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1276,7 +1276,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 c4e7de4b6d9e8a25f352568afe8cee0f88f5adf6 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 16:29:19 +1100 Subject: [PATCH 025/327] 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 325cfcd3166..270c83fe38e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1042,244 +1042,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 @@ -1303,13 +1308,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>) = @@ -1405,10 +1410,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 3825fa59de70548aba39d02fded28336a53767dc Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 19:09:42 +1100 Subject: [PATCH 026/327] 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 270c83fe38e..89293b410a1 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 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) @@ -850,6 +831,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) @@ -928,6 +917,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>() @@ -1437,10 +1458,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 ffc4fd2133318a9a848ddaa8c6819fae01fba178 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 19:29:55 +1100 Subject: [PATCH 027/327] 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 89293b410a1..5ac6d90ceda 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -784,6 +784,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 = @@ -796,6 +800,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 @@ -812,6 +817,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> @@ -863,9 +873,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 @@ -874,7 +883,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 @@ -882,7 +893,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 @@ -890,7 +901,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) @@ -901,7 +912,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 @@ -910,7 +921,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) @@ -918,7 +929,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 @@ -930,11 +941,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 @@ -946,11 +959,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 @@ -960,7 +975,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 @@ -970,7 +985,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> @@ -986,7 +1001,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 @@ -1004,14 +1019,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 @@ -1026,7 +1043,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 @@ -1040,14 +1057,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 @@ -1057,7 +1076,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 @@ -1065,9 +1084,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 @@ -1096,18 +1116,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 @@ -1116,8 +1136,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>() @@ -1147,21 +1168,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 @@ -1197,22 +1218,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 @@ -1242,8 +1263,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 @@ -1263,11 +1284,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 () @@ -1275,7 +1296,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 977083970fc7e216dc634ed99d452f12b43269bd Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 10 Oct 2016 19:35:48 +1100 Subject: [PATCH 028/327] 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 5ac6d90ceda..0c77bfb9e65 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -317,149 +317,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 @@ -1082,9 +939,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 () @@ -1101,10 +958,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 = @@ -1115,9 +973,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 @@ -1140,8 +997,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> = @@ -1167,9 +1024,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 @@ -1191,7 +1098,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> = @@ -1219,7 +1126,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 @@ -1242,7 +1149,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> = @@ -1264,7 +1171,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 @@ -1305,7 +1212,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> = @@ -1316,7 +1223,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> = @@ -1452,7 +1359,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)) @@ -1483,7 +1390,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)) [] @@ -1628,9 +1535,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 = #if FX_ATLEAST_40 @@ -1645,7 +1549,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 7e9cb8b3744aec00488b4ead3db465bf5de05790 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 10 Oct 2016 19:42:40 +1100 Subject: [PATCH 029/327] 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 0c77bfb9e65..a63df1b7719 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -660,9 +660,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 @@ -953,10 +953,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> @@ -1045,10 +1047,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 026551f71b3979f8f96301463a6737777db182d0 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 10 Oct 2016 19:46:35 +1100 Subject: [PATCH 030/327] 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 a63df1b7719..60c228b0530 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1055,7 +1055,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 5acb7dffc9edccaac79a5d04bc49eb0bf525d515 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 11 Oct 2016 19:32:19 +1100 Subject: [PATCH 031/327] 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 60c228b0530..24e42f51c14 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -963,6 +963,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]) @@ -1010,21 +1011,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 @@ -1078,6 +1078,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) @@ -1112,21 +1124,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>) = @@ -1163,6 +1174,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. @@ -1174,16 +1203,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 @@ -1226,6 +1259,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>() @@ -1239,6 +1295,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 @@ -1503,14 +1570,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 6775b56595c77f3845489ad82433e01f1b248aa4 Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 11 Oct 2016 16:28:24 -0400 Subject: [PATCH 032/327] 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 24e42f51c14..7c7c92376f6 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -718,13 +718,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 23b72bba48a2b906c92afab4e8e53aed28cdbe1e Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 11 Oct 2016 21:16:38 -0400 Subject: [PATCH 033/327] 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 7c7c92376f6..f2c5b5c8db0 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -729,6 +729,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 @@ -939,6 +943,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) = @@ -1716,12 +1735,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 5013d453b8c33f8bbda8c3f58e73e983f3661815 Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 11 Oct 2016 22:36:09 -0400 Subject: [PATCH 034/327] 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 f2c5b5c8db0..e7f40e14e69 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -904,24 +904,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 () @@ -943,15 +931,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 10130c9d15db0e7c160dbea22cac39c36a6ed965 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 12 Oct 2016 19:08:05 +1100 Subject: [PATCH 035/327] 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 e7f40e14e69..09686d63970 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -804,8 +804,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) @@ -822,8 +824,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) @@ -1006,8 +1010,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 e7d7d059e5b395f89a07c88515ed4e259e0d9fe6 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 12 Oct 2016 20:23:43 +1100 Subject: [PATCH 036/327] 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 09686d63970..4ff4fa947ab 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1731,6 +1731,7 @@ namespace Microsoft.FSharp.Collections [] let truncate n (source: seq<'T>) = + if n <= 0 then empty else source |> seqFactory (SeqComposer.TruncateFactory n) [] From 9daf01d46a7881706182a01648915371accf353a Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 12 Oct 2016 21:46:26 -0400 Subject: [PATCH 037/327] 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 4ff4fa947ab..429525ff527 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -689,6 +689,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> () @@ -761,6 +769,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) @@ -1944,19 +1974,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 dc3789d531a844d74f6c9baaddeac3a0238ff795 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 13 Oct 2016 06:19:09 -0400 Subject: [PATCH 038/327] 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 429525ff527..31c7afea626 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -697,6 +697,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> () @@ -791,6 +795,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) @@ -2311,17 +2326,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 aca3d9c06c400d12289e32149e9fc30fd93d4763 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 13 Oct 2016 21:55:52 -0400 Subject: [PATCH 039/327] 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 31c7afea626..6311a0a09dc 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1537,8 +1537,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 928b9e3f0cd999e9fabe9920916836b29b006864 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 13 Oct 2016 22:53:06 -0400 Subject: [PATCH 040/327] 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 6311a0a09dc..b651c4982c1 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1541,15 +1541,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 d1a4146ff1f1bcb9936ff6db58e9dded5f378f69 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:31:04 +1100 Subject: [PATCH 041/327] 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 b651c4982c1..1169538d4f7 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -150,24 +150,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 a99a32324571024ad09122ca6832c98d12a3709b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:46:05 +1100 Subject: [PATCH 042/327] 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 1169538d4f7..6b02279944d 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) @@ -1324,6 +1275,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 e647bc87ba4e96d5ae8dd56a2ac5ef771e35fc22 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:52:39 +1100 Subject: [PATCH 043/327] cleaning up SeqComposer.Helpers - better comments - consistent casing --- src/fsharp/FSharp.Core/seq.fs | 87 +++++++++++++++++------------------ 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 6b02279944d..a7eb140faf7 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -580,17 +580,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 @@ -785,7 +784,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) @@ -805,7 +804,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) @@ -868,7 +867,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) @@ -894,7 +893,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) @@ -938,7 +937,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 () @@ -956,13 +955,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)" @@ -978,7 +977,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.UpcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -991,7 +990,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>() @@ -999,10 +998,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 @@ -1048,7 +1047,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 () @@ -1063,18 +1062,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 @@ -1098,7 +1097,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.UpcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -1112,10 +1111,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 @@ -1148,7 +1147,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (Helpers.UpcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -1162,10 +1161,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 @@ -1233,7 +1232,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 @@ -1247,10 +1246,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 @@ -1336,12 +1335,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 @@ -1371,13 +1370,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>) = @@ -1474,9 +1473,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> = @@ -1662,7 +1661,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 ed07de8f84e233a9312409c99716677e4246362d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:59:00 +1100 Subject: [PATCH 044/327] 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 a7eb140faf7..d0f337f8baa 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 @@ -650,6 +626,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) @@ -806,6 +786,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) @@ -1511,7 +1515,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 99c615746ead3025214abc54d33035c7cccb40ba Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 06:06:25 +1100 Subject: [PATCH 045/327] 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 d0f337f8baa..7208276990b 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 @@ -634,6 +615,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 @@ -830,6 +815,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) @@ -1500,7 +1507,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 18250fca00ed3ef4e9604da87b4519d341b12737 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 06:09:39 +1100 Subject: [PATCH 046/327] 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 7208276990b..1093a88cc89 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -599,13 +599,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> () @@ -731,7 +727,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 () @@ -751,26 +747,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) @@ -1513,9 +1489,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 384b7b358c994dfd9b6845f8288a143df0612fa1 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 10:15:33 +1100 Subject: [PATCH 047/327] 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 1093a88cc89..d7bad40a393 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) @@ -1171,6 +1118,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. @@ -1263,7 +1260,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) @@ -1343,14 +1340,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 4dbd4114c48b428ab28534462b2e12f846e109bb Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 10:35:24 +1100 Subject: [PATCH 048/327] 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 d7bad40a393..e5608348bb4 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -517,11 +517,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) @@ -542,6 +555,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 @@ -935,7 +953,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 @@ -1048,7 +1066,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 @@ -1098,7 +1116,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 @@ -1148,7 +1166,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 @@ -1233,7 +1251,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 @@ -1347,7 +1365,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 85fa6edeee25cbc27e2c738d3b49ae1ae47ae5b6 Mon Sep 17 00:00:00 2001 From: liboz Date: Fri, 14 Oct 2016 20:13:25 -0400 Subject: [PATCH 049/327] 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 e5608348bb4..2c1a765272b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -564,9 +564,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> () @@ -692,7 +696,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 () @@ -712,6 +716,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) @@ -1496,19 +1520,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 d5b7b971fb3ce0eaf32c8969e2b434974e2ca462 Mon Sep 17 00:00:00 2001 From: liboz Date: Fri, 14 Oct 2016 20:31:55 -0400 Subject: [PATCH 050/327] 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 2c1a765272b..27454cfb56b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1525,7 +1525,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 aa96657f3d31ef00266ec12734f3e5f7b8a2b40a Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 15 Oct 2016 00:06:36 -0400 Subject: [PATCH 051/327] seq.tail and a fix to takewhile to use avoidtailcall --- src/fsharp/FSharp.Core/seq.fs | 51 +++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 27454cfb56b..8214e8cc7c9 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -604,6 +604,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) @@ -876,7 +880,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 @@ -888,6 +892,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) @@ -974,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)) @@ -985,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 @@ -1087,7 +1109,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)) @@ -1097,7 +1119,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 @@ -1137,7 +1159,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)) @@ -1146,7 +1168,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 @@ -1187,7 +1209,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)) @@ -1196,7 +1218,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 @@ -1272,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)) @@ -1281,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 @@ -2253,12 +2275,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 79c7d3a77cad8a86841161bb4cdbf1abd34ddce5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 16:57:55 +1100 Subject: [PATCH 052/327] 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 8214e8cc7c9..b7a01b5c6e0 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 @@ -1744,7 +1719,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 4946571879e51ab21eb5056b089804615df432b1 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 18:25:43 +1100 Subject: [PATCH 053/327] 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 b7a01b5c6e0..f7854075d38 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1056,10 +1056,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 @@ -1075,19 +1084,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 @@ -1096,6 +1108,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 @@ -2290,10 +2303,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 586fd1d602dd650603cc27a14577c5c44a8b33f6 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 18:48:47 +1100 Subject: [PATCH 054/327] 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 f7854075d38..c2c84010c0b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1091,7 +1091,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 a617bafec479b834e7350698cb985637e80ddded Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 19:02:09 +1100 Subject: [PATCH 055/327] 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 c2c84010c0b..27c2314d362 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2303,18 +2303,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 df4368a68dfa73cde71a6001b611e1d676ca730d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 19:07:03 +1100 Subject: [PATCH 056/327] 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 27c2314d362..3fd784cba26 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2007,26 +2007,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 54e091c8f007644f9357d2853ac5fb3f0e0d4029 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 19:24:50 +1100 Subject: [PATCH 057/327] 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 3fd784cba26..d574484a543 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1055,6 +1055,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) @@ -1090,9 +1093,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> () @@ -1117,6 +1117,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) @@ -1170,6 +1182,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> = @@ -1732,7 +1747,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>) = @@ -2008,19 +2023,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 = @@ -2298,13 +2313,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 12654bd2fed1f9eb015e5d44d83473281f9d4484 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 05:10:24 +1100 Subject: [PATCH 058/327] 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 d574484a543..5f7de1538c4 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1059,7 +1059,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 @@ -1070,7 +1070,7 @@ namespace Microsoft.FSharp.Collections initMoveNext <- fun () -> result.SeqState <- SeqProcessNextStates.InProcess - array <- lazyArray.Value + array <- delayedArray () initMoveNext <- ignore let rec moveNext () = @@ -1090,16 +1090,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 @@ -1108,7 +1108,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 @@ -1117,14 +1117,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 ()) @@ -2022,20 +2022,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 = @@ -2312,14 +2321,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 ea1f5c7d59a1b715b16f28cc47bda707c21d2217 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 05:15:23 +1100 Subject: [PATCH 059/327] 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 5f7de1538c4..d1dcc8640c5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -860,13 +860,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) @@ -902,6 +895,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 @@ -1096,7 +1097,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)) @@ -1106,7 +1107,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 @@ -1159,7 +1160,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)) @@ -1168,7 +1169,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 @@ -1212,7 +1213,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)) @@ -1221,7 +1222,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 4e37eaa5374e0a5d4f156014959bf61cb17556cc Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 06:11:37 +1100 Subject: [PATCH 060/327] 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 d1dcc8640c5..6eddb6b5c78 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -925,9 +925,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]) @@ -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 @@ -1044,6 +1055,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 @@ -1102,6 +1120,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 @@ -1165,6 +1194,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 @@ -1218,6 +1264,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 c91e32863607faea19a0592d82373a2781272b8c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 06:16:48 +1100 Subject: [PATCH 061/327] 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 6eddb6b5c78..ad8c9487a2b 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>) = @@ -2198,12 +2202,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 46d352ce3561744985919bfb59d314911c2f5027 Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 15 Oct 2016 11:34:13 -0400 Subject: [PATCH 062/327] 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 ad8c9487a2b..dbbbd57e51b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -532,7 +532,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) = @@ -667,6 +667,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 36cc32f952fd032a67e8323fa695eebace52ba16 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 10:09:42 +1100 Subject: [PATCH 063/327] 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 0d77c961210e429bbd852d458ded0bee801d12c8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 18:11:25 +1100 Subject: [PATCH 064/327] 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 dbbbd57e51b..2dd2752cf08 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 @@ -1137,6 +1142,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 @@ -1151,6 +1159,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>) = @@ -1207,7 +1217,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 @@ -1226,7 +1236,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 @@ -1277,7 +1289,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 @@ -1296,7 +1308,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 1b2927a54907fd00b95d8e334ae15a52a22f3aa4 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 17 Oct 2016 20:17:23 +1100 Subject: [PATCH 065/327] 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 2dd2752cf08..0f183bcd5f6 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -447,9 +447,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 @@ -457,6 +454,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 @@ -470,20 +493,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 @@ -491,14 +500,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) = @@ -512,83 +522,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 @@ -606,7 +622,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 = @@ -614,7 +630,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>) @@ -625,7 +641,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>) @@ -636,7 +652,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)) @@ -647,7 +663,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) @@ -658,7 +674,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 = @@ -667,13 +683,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) @@ -681,7 +697,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 () @@ -701,7 +717,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 () @@ -721,7 +737,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 () @@ -745,7 +761,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 = @@ -755,7 +771,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 @@ -765,7 +781,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 @@ -787,7 +803,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 @@ -803,7 +819,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 @@ -830,7 +846,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 @@ -845,7 +861,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 @@ -856,7 +872,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 = @@ -866,7 +882,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 @@ -884,7 +900,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 @@ -901,9 +917,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 @@ -931,6 +962,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 @@ -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> () @@ -1066,6 +1102,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 () @@ -1089,7 +1127,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 @@ -1131,6 +1169,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> () @@ -1176,7 +1233,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 @@ -1210,6 +1267,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) @@ -1251,7 +1310,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 @@ -1282,6 +1341,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 () @@ -2208,12 +2287,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 6619d6eeeca3267a0f537b1cf9e1c89fc16ac557 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 18:25:12 +1100 Subject: [PATCH 066/327] 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 0f183bcd5f6..f24e82f93a8 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -465,16 +465,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>() = @@ -2290,9 +2285,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 747f8d2b718d0a134acf01a6e7ab56bb5b766a50 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 19:50:47 +1100 Subject: [PATCH 067/327] 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 f24e82f93a8..0027ce261e5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -487,6 +487,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 () @@ -1097,7 +1112,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) @@ -1262,7 +1293,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> () @@ -1336,7 +1385,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 c224a03efaf8fa5a80f590ce42488dc51a4768de Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 19:56:59 +1100 Subject: [PATCH 068/327] Removed Fold --- src/fsharp/FSharp.Core/seq.fs | 139 +++------------------------------- 1 file changed, 9 insertions(+), 130 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 0027ce261e5..b216c65b66e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -962,7 +962,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]) @@ -1042,24 +1041,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 @@ -1137,18 +1118,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)) @@ -1227,25 +1196,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)) @@ -1330,26 +1280,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)) @@ -1422,26 +1352,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 +1479,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 +1565,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 +1827,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 3a6c338780381100ff86595e584ffb821aaa7bbb Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 20:01:20 +1100 Subject: [PATCH 069/327] 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 b216c65b66e..7e4a0387c1e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -962,7 +962,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]) @@ -1029,18 +1028,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 @@ -1111,13 +1098,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)) @@ -1183,19 +1163,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)) @@ -1263,23 +1230,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)) @@ -1335,23 +1285,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. @@ -1456,29 +1389,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" @@ -1559,12 +1469,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 @@ -1597,10 +1501,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 94663dc6c7c4adec0b90070fb719702a512b1046 Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 18 Oct 2016 20:18:13 -0400 Subject: [PATCH 070/327] 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 7e4a0387c1e..18396af622d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2196,66 +2196,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 (* [] @@ -2276,33 +2360,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 c2ab12662cf4b3126320d5fd8e4c3dc3922c5842 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 19 Oct 2016 18:20:55 +1100 Subject: [PATCH 071/327] 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 18396af622d..b0e712d67bf 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -487,8 +487,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 @@ -1086,7 +1084,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 () @@ -1458,7 +1456,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 41db490829b2cabea78eee8a289d045664857452 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 19 Oct 2016 21:39:49 +1100 Subject: [PATCH 072/327] 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 c48d546916f2997bff82854be23ac2f759be439a Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 18:27:37 -0400 Subject: [PATCH 073/327] 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 b0e712d67bf..2623354ccea 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2173,24 +2173,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 075b526c10cfd41d5b1bcc63c252b7c1b6744169 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 18:48:31 -0400 Subject: [PATCH 074/327] 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 2623354ccea..3286e36ce3d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -542,6 +542,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> = @@ -1168,10 +1170,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>) = @@ -1482,7 +1484,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>) @@ -2178,10 +2180,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 cde2e650a8fb57dd3c789ecee32f0088e224e5b2 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 18:54:59 -0400 Subject: [PATCH 075/327] 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 3286e36ce3d..9d88b503ff5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2187,9 +2187,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 @@ -2198,151 +2198,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 = @@ -2362,74 +2306,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 afd392bc58565f7650b6dccf4c48e10836989022 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 19:58:41 -0400 Subject: [PATCH 076/327] 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 9d88b503ff5..ff9b61bb32d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2248,13 +2248,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 @@ -2268,18 +2270,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() = @@ -2308,14 +2314,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() = @@ -2328,18 +2337,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 037e520b0e71e1c38939cddc2671eced9b6e2db3 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 21:32:50 -0400 Subject: [PATCH 077/327] 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 ff9b61bb32d..ee54cfe8422 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2276,13 +2276,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 @@ -2320,8 +2320,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 @@ -2343,12 +2343,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 71067167c373f225f785343a2f40351084a4e680 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 16:55:58 +1100 Subject: [PATCH 078/327] 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 ee54cfe8422..b2e5cad0789 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -936,6 +936,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) = @@ -1013,15 +1018,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 () @@ -1081,9 +1084,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 @@ -1091,7 +1092,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 () @@ -1146,16 +1147,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 @@ -1211,15 +1209,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 -> @@ -1266,15 +1262,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) -> @@ -1361,9 +1355,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 @@ -1376,7 +1368,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 () @@ -1453,16 +1445,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 6e03110c499e21b62cc18cafd6824ce361475ff8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 17:56:26 +1100 Subject: [PATCH 079/327] 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 b2e5cad0789..9c38abad361 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2170,7 +2170,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 cb5eb6fa5cacd0439ed1883e6f51199ca63efc2e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 18:24:25 +1100 Subject: [PATCH 080/327] 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 9c38abad361..9f18bf2e5a8 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -495,9 +495,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> () @@ -505,14 +502,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> () @@ -539,10 +529,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> () @@ -679,12 +668,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 bf63f41a9dba7a1bdd5fc5b9a01a031e20666207 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 19:25:47 +1100 Subject: [PATCH 081/327] 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 9f18bf2e5a8..58ab6664e92 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -465,11 +465,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>() = @@ -2158,6 +2173,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 @@ -2182,22 +2199,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 ccb32e4e7b0d085269a263eb8dbdf4611988006c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 20:08:10 +1100 Subject: [PATCH 082/327] 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 58ab6664e92..49293b05877 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1007,6 +1007,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> () @@ -1017,17 +1021,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 @@ -1071,6 +1073,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)) @@ -1083,19 +1089,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)) @@ -1135,6 +1138,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> () @@ -1144,20 +1153,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)) @@ -1195,6 +1199,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>() @@ -1208,21 +1222,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)) @@ -1251,6 +1258,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> () @@ -1261,21 +1279,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 @@ -1344,6 +1355,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> () @@ -1354,30 +1377,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 @@ -1432,6 +1441,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 @@ -1444,18 +1457,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 ca926d95a4e9b9a28e130a884e37ea95073999fa Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 20 Oct 2016 07:24:44 -0400 Subject: [PATCH 083/327] 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 49293b05877..4e8025fe4bf 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1476,6 +1476,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 @@ -1499,17 +1510,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>) = @@ -1530,41 +1537,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<_>) = @@ -1659,33 +1691,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 @@ -1730,24 +1774,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>) = @@ -1767,14 +1802,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 = @@ -2174,17 +2220,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 @@ -2432,28 +2467,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 2f2fb4c1169be1e66f01e8719a8acb3d176ec5f5 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 20 Oct 2016 14:03:04 -0400 Subject: [PATCH 084/327] 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 4e8025fe4bf..a516d95d70c 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1560,9 +1560,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 @@ -1576,9 +1577,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 @@ -1592,9 +1594,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 @@ -1699,9 +1702,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 @@ -1722,9 +1726,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 daf36a779d087987de8893f69f33a2e058a9e01a Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 20 Oct 2016 16:29:50 -0400 Subject: [PATCH 085/327] 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 a516d95d70c..7bab85cff57 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1241,9 +1241,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 170751b6f14a35cbfadfdbd9f8ce9ef0f6d79632 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 13:36:33 +1100 Subject: [PATCH 086/327] 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 7bab85cff57..e1f5ab2b073 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -466,7 +466,7 @@ namespace Microsoft.FSharp.Collections member __.OnDispose() = () [] - type MutableData<'a,'b> = + type Values<'a,'b> = val mutable _1 : 'a val mutable _2 : 'b @@ -476,14 +476,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 } [] @@ -1557,16 +1557,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>) = @@ -1574,16 +1574,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>) = @@ -1591,16 +1591,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<_>) = @@ -1699,16 +1699,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 = @@ -1722,17 +1722,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 = @@ -1784,11 +1784,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>) = @@ -1813,20 +1813,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 = @@ -2231,22 +2231,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 = @@ -2254,18 +2254,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 = @@ -2273,9 +2273,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 @@ -2283,7 +2283,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<_>) = @@ -2292,20 +2292,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 = @@ -2315,25 +2315,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 = @@ -2358,21 +2358,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 = @@ -2382,25 +2382,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 (* [] @@ -2481,16 +2481,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 1dfec9fd5929fc9e81cb297c15fe23bc959baaeb Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 13:53:33 +1100 Subject: [PATCH 087/327] 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 e1f5ab2b073..96c1eee06d5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1695,20 +1695,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 95b52a1732eb491302ca6aab9e44e6961ce02c6b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 14:02:20 +1100 Subject: [PATCH 088/327] 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 96c1eee06d5..2731c350aa0 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1716,21 +1716,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 4b1bfc1710989c5c42f52091357001133b68aab4 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:31:38 +1100 Subject: [PATCH 089/327] 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 2731c350aa0..4af199f53d4 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -475,6 +475,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> @@ -2223,112 +2235,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 = @@ -2348,54 +2352,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 4571b0df8beda717fce9da1df1586ea0f5795716 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:49:17 +1100 Subject: [PATCH 090/327] 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 4af199f53d4..22b1e27a14b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1565,54 +1565,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 ab0dab3d20f8cd5fa62bd22d54e9b4fe94386355 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:53:22 +1100 Subject: [PATCH 091/327] 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 22b1e27a14b..cb7d84f8f02 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1784,15 +1784,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>) = @@ -1812,25 +1813,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 8398058e6f1b63902818793414e70556c867c933 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:57:34 +1100 Subject: [PATCH 092/327] 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 cb7d84f8f02..ae0bc7aa580 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1826,6 +1826,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 @@ -2468,21 +2469,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 27ce377117c80ee8e2b66e74f8618495ea152ddc Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 16:44:03 +1100 Subject: [PATCH 093/327] 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 ae0bc7aa580..ae6457bfbc1 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1499,7 +1499,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 @@ -1524,7 +1527,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 = @@ -1566,7 +1568,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 = @@ -1582,7 +1583,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 = @@ -1598,7 +1598,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 = @@ -1705,7 +1704,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 = @@ -1726,7 +1724,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 = @@ -1787,7 +1784,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 = @@ -1816,7 +1812,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 = @@ -2235,7 +2230,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 = @@ -2246,7 +2240,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 = @@ -2257,7 +2250,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 = @@ -2274,7 +2266,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 = @@ -2290,7 +2281,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 = @@ -2311,7 +2301,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 = @@ -2352,7 +2341,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 = @@ -2373,7 +2361,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 = @@ -2470,7 +2457,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 ddc334acd78c3e1f084f67ae2ae40467f49fbff1 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 19:37:46 +1100 Subject: [PATCH 094/327] 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 ae6457bfbc1..427cacdf521 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -515,6 +515,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() = () @@ -1530,7 +1533,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 [] @@ -1552,17 +1556,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 [] @@ -1574,9 +1575,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Value <- true pipeline.StopFurtherProcessing () - false - else - true + SeqComposer.Helpers.processNextInForeach }) |> fun exists -> exists.Value @@ -1589,9 +1588,7 @@ namespace Microsoft.FSharp.Collections if element = value then this.Value <- true pipeline.StopFurtherProcessing() - false - else - true + SeqComposer.Helpers.processNextInForeach }) |> fun contains -> contains.Value @@ -1601,12 +1598,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 @@ -1708,11 +1703,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 [] @@ -1730,9 +1725,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 [] @@ -1788,7 +1781,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 [] @@ -1820,7 +1813,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() = @@ -2234,7 +2227,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 [] @@ -2244,7 +2237,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 [] @@ -2255,7 +2248,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() = @@ -2271,7 +2264,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 @@ -2289,7 +2282,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() = @@ -2313,7 +2306,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- valueU this.Value._3 <- value | _ -> () - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2349,7 +2342,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() = @@ -2373,7 +2366,7 @@ namespace Microsoft.FSharp.Collections this.Value._2 <- valueU this.Value._3 <- value | _ -> () - true + SeqComposer.Helpers.processNextInForeach interface SeqComposer.ISeqComponent with member this.OnComplete() = @@ -2463,7 +2456,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 ca6433e084d9b885cd55afd0e82e59c5e168b930 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 22 Oct 2016 12:38:03 +1100 Subject: [PATCH 095/327] 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 427cacdf521..0050a1a8567 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -515,9 +515,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() = () @@ -1534,7 +1531,7 @@ namespace Microsoft.FSharp.Collections { new SeqComposer.SeqConsumer<'T,'T> () with override this.ProcessNext value = f value - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> ignore [] @@ -1563,7 +1560,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 [] @@ -1575,7 +1572,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Value <- true pipeline.StopFurtherProcessing () - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof }) |> fun exists -> exists.Value @@ -1588,7 +1585,7 @@ namespace Microsoft.FSharp.Collections if element = value then this.Value <- true pipeline.StopFurtherProcessing() - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof }) |> fun contains -> contains.Value @@ -1601,7 +1598,7 @@ namespace Microsoft.FSharp.Collections if not (f value) then this.Value <- false pipeline.StopFurtherProcessing() - SeqComposer.Helpers.processNextInForeach + Unchecked.defaultof }) |> fun forall -> forall.Value @@ -1707,7 +1704,7 @@ namespace Microsoft.FSharp.Collections this.Value <- some pipeline.StopFurtherProcessing() | None -> () - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> fun pick -> pick.Value [] @@ -1725,7 +1722,7 @@ namespace Microsoft.FSharp.Collections if f value then this.Value <- Some value pipeline.StopFurtherProcessing() - SeqComposer.Helpers.processNextInForeach }) + Unchecked.defaultof }) |> fun find -> find.Value [] @@ -1781,7 +1778,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 [] @@ -1813,7 +1810,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() = @@ -2227,7 +2224,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 [] @@ -2237,7 +2234,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 [] @@ -2248,7 +2245,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() = @@ -2264,7 +2261,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 @@ -2282,7 +2279,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() = @@ -2306,7 +2303,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() = @@ -2342,7 +2339,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() = @@ -2366,7 +2363,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() = @@ -2456,7 +2453,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 7f40a233891a11c79e370977d17a565794528816 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 22 Oct 2016 13:42:57 +1100 Subject: [PATCH 096/327] 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 0050a1a8567..969a16da25b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -951,6 +951,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) = @@ -1019,10 +1081,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> () @@ -1032,16 +1090,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 @@ -1085,10 +1134,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)) @@ -1100,17 +1145,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)) @@ -1150,12 +1186,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> () @@ -1165,15 +1195,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)) @@ -1211,16 +1233,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>() @@ -1233,15 +1245,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)) @@ -1271,17 +1275,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> () @@ -1291,15 +1284,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 @@ -1321,16 +1306,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 @@ -1368,18 +1348,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> () @@ -1389,17 +1357,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 @@ -1454,10 +1413,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 @@ -1469,16 +1424,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 67490503106ac2e52b9247dfdedd81eb41506441 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 22 Oct 2016 18:06:21 +1100 Subject: [PATCH 097/327] 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 969a16da25b..56e15606fb4 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 @@ -1014,6 +1014,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 @@ -1092,24 +1107,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 = @@ -1129,6 +1145,7 @@ namespace Microsoft.FSharp.Collections interface IDisposable with member __.Dispose() = + main.Dispose () active.Dispose () and AppendEnumerable<'T> (sources:list>) = @@ -1136,7 +1153,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)) @@ -1145,8 +1162,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)) @@ -1695,11 +1724,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 65378ee67c1f3d97b30d4ea540c06f0fe291065f Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 22 Oct 2016 07:29:55 -0400 Subject: [PATCH 098/327] 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 56e15606fb4..c3f1cedf26c 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1936,31 +1936,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 696c0d1de2ff0b15c8aed5fcf5515798859232c9 Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 22 Oct 2016 10:38:32 -0400 Subject: [PATCH 099/327] 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 c3f1cedf26c..8c1190475a8 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1111,10 +1111,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 d3a87005c9ac51c7c3d9325e51aee20a60498ea1 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 23 Oct 2016 19:30:44 +1100 Subject: [PATCH 100/327] 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 8c1190475a8..9869954c74c 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -451,18 +451,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() = () [] @@ -517,133 +517,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>) @@ -653,8 +655,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>) @@ -664,8 +666,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)) @@ -675,10 +677,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 @@ -686,8 +688,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 @@ -695,16 +697,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 @@ -713,7 +715,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 @@ -723,8 +725,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 @@ -733,7 +735,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 @@ -743,8 +745,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 () @@ -754,7 +756,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 @@ -767,8 +769,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 @@ -777,8 +779,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 @@ -787,8 +789,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 () @@ -799,7 +801,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 @@ -809,8 +811,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> @@ -825,8 +827,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 @@ -845,15 +847,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 @@ -867,29 +869,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 @@ -901,13 +903,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 @@ -917,10 +919,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 = @@ -929,14 +931,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>) = @@ -947,40 +949,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 @@ -993,7 +993,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 () @@ -1005,10 +1005,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 () @@ -1071,14 +1071,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 @@ -1099,7 +1099,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)) @@ -1193,7 +1193,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 @@ -1201,7 +1201,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 @@ -1215,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>(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)) @@ -1243,7 +1243,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 @@ -1251,7 +1251,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 @@ -1265,7 +1265,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)) @@ -1284,14 +1284,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 () = @@ -1304,7 +1303,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)) @@ -1345,7 +1344,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 @@ -1359,11 +1358,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 @@ -1377,7 +1376,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)) @@ -1543,7 +1542,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 @@ -1556,7 +1555,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 @@ -1569,7 +1568,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 @@ -1674,7 +1673,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 @@ -1693,7 +1692,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 @@ -1784,7 +1783,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 }) @@ -1941,7 +1940,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 @@ -2214,7 +2213,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 @@ -2229,7 +2228,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 @@ -2248,7 +2247,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 }) @@ -2272,7 +2271,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 }) @@ -2308,7 +2307,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 }) @@ -2332,7 +2331,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 1a5a64a1fa60c845c344c56ada34001c00c9d7cf Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 22 Oct 2016 17:04:03 -0400 Subject: [PATCH 101/327] 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 9869954c74c..7781c258f4e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -591,6 +591,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) @@ -827,6 +831,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) @@ -1904,15 +1918,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 d5ac0b32d89b77a013e83c3f3d9bbda6c0532b4d Mon Sep 17 00:00:00 2001 From: liboz Date: Sun, 23 Oct 2016 10:05:30 -0400 Subject: [PATCH 102/327] 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 7781c258f4e..725d07f59f7 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1528,10 +1528,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 @@ -2387,7 +2395,6 @@ namespace Microsoft.FSharp.Collections ok <- p.Invoke(e1.Current, e2.Current) ok - [] let exists2 p (source1: seq<_>) (source2: seq<_>) = checkNonNull "source1" source1 @@ -2399,20 +2406,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>) = @@ -2442,16 +2452,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 f47a9aa900576912064eb2a31902334459bb8115 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 24 Oct 2016 20:17:12 +1100 Subject: [PATCH 103/327] 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 725d07f59f7..a6145eda8cf 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -500,7 +500,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 @@ -521,135 +521,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>) @@ -659,8 +673,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>) @@ -670,8 +684,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)) @@ -681,10 +695,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 @@ -692,8 +706,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 @@ -701,16 +715,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 @@ -719,7 +733,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 @@ -729,8 +743,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 @@ -739,7 +753,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 @@ -749,8 +763,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 () @@ -760,7 +774,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 @@ -773,8 +787,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 @@ -783,8 +797,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 @@ -793,8 +807,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 () @@ -805,7 +819,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 @@ -815,8 +829,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> @@ -831,8 +845,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 @@ -841,8 +855,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 @@ -861,15 +875,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 @@ -883,29 +897,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 @@ -917,13 +931,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 @@ -933,10 +947,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 = @@ -945,14 +959,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>) = @@ -963,9 +977,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>) = @@ -1016,10 +1030,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 @@ -1113,12 +1127,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>) = @@ -1172,7 +1186,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>) = @@ -1185,7 +1199,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 = @@ -1229,12 +1243,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>) = @@ -1279,12 +1293,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 = @@ -1317,12 +1331,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 = @@ -1390,12 +1404,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) @@ -1462,7 +1476,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 @@ -1530,12 +1544,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 }) @@ -1559,12 +1573,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 @@ -1572,12 +1586,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 @@ -1585,12 +1599,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 @@ -1689,13 +1703,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 @@ -1709,12 +1723,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 @@ -1952,12 +1966,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 @@ -2410,11 +2424,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 @@ -2453,7 +2467,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 @@ -2461,7 +2475,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 25e561cbd3d9f3ec526559900eb98bc1868244a6 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 25 Oct 2016 19:21:05 +1100 Subject: [PATCH 104/327] 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 a6145eda8cf..ad5f84700dc 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -450,12 +450,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> () = @@ -520,52 +526,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) @@ -573,67 +568,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>() @@ -646,7 +641,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 @@ -723,7 +718,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 () @@ -733,7 +728,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 @@ -743,7 +738,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 () @@ -753,7 +748,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 @@ -763,7 +758,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 () @@ -774,7 +769,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 @@ -807,7 +802,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 @@ -819,7 +814,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 @@ -875,12 +870,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) @@ -897,25 +892,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>) = @@ -931,12 +926,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 @@ -947,10 +942,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 = @@ -959,14 +954,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>) = @@ -977,25 +972,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 @@ -1004,7 +999,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 @@ -1021,7 +1016,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 () @@ -1032,11 +1027,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 () @@ -1099,14 +1094,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 @@ -1127,7 +1122,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)) @@ -1221,7 +1216,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 @@ -1229,7 +1224,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 @@ -1243,7 +1238,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)) @@ -1270,7 +1265,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 @@ -1279,7 +1274,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 @@ -1293,7 +1288,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)) @@ -1311,7 +1306,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 @@ -1331,7 +1326,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)) @@ -1372,7 +1367,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 @@ -1386,11 +1381,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 @@ -1404,7 +1399,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 c74d0bcb5f2fb155654692fdee51b1138d444a67 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 26 Oct 2016 19:46:49 +1100 Subject: [PATCH 105/327] 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 ad5f84700dc..295887477e8 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -467,9 +467,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> = @@ -521,11 +529,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> @@ -641,8 +644,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 @@ -731,12 +738,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) @@ -751,12 +754,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) @@ -772,15 +771,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) @@ -817,12 +810,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) @@ -869,13 +858,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) @@ -895,13 +882,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) @@ -925,11 +910,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) @@ -1813,9 +1796,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 @@ -2238,9 +2220,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 @@ -2253,9 +2234,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 @@ -2272,9 +2253,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 @@ -2296,9 +2276,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 @@ -2332,9 +2311,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 @@ -2356,9 +2334,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 @@ -2472,14 +2449,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 9db469a9877ead047892b9a7b56891634ec66c83 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 26 Oct 2016 20:24:17 +1100 Subject: [PATCH 106/327] 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 295887477e8..edd149c2021 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -447,74 +447,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 @@ -527,10 +532,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) @@ -539,7 +544,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> = @@ -547,23 +552,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) @@ -571,79 +576,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 @@ -656,7 +661,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 = @@ -664,7 +669,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>) @@ -675,7 +680,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>) @@ -686,7 +691,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)) @@ -697,7 +702,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) @@ -708,7 +713,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 = @@ -717,7 +722,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) @@ -725,7 +730,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 () @@ -741,7 +746,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 () @@ -757,7 +762,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 () @@ -775,7 +780,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 = @@ -785,7 +790,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 @@ -795,7 +800,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 @@ -813,7 +818,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 @@ -829,7 +834,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 @@ -839,7 +844,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 @@ -864,7 +869,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 @@ -879,7 +884,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 = @@ -888,7 +893,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 = @@ -898,7 +903,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 @@ -914,7 +919,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 @@ -943,12 +948,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 @@ -956,22 +961,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 -> @@ -980,7 +985,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) -> @@ -990,12 +995,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 @@ -1008,9 +1013,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 @@ -1036,7 +1041,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 () @@ -1073,7 +1078,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 () = @@ -1110,7 +1115,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>) = @@ -1164,7 +1169,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>) = @@ -1177,14 +1182,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 @@ -1226,7 +1231,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>) = @@ -1242,7 +1247,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 @@ -1276,14 +1281,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 @@ -1314,7 +1319,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 = @@ -1337,7 +1342,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 = @@ -1387,7 +1392,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) @@ -1454,7 +1459,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 @@ -1468,13 +1473,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 @@ -1486,26 +1491,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 }) @@ -1523,7 +1528,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 @@ -1541,7 +1546,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 @@ -1552,7 +1557,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 @@ -1565,7 +1570,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 @@ -1578,7 +1583,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 @@ -1619,51 +1624,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 = @@ -1682,7 +1687,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 -> @@ -1702,7 +1707,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 @@ -1721,7 +1726,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>) = @@ -1737,7 +1742,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>) = @@ -1759,7 +1764,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 }) @@ -1787,7 +1792,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 @@ -1817,8 +1822,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])) [] @@ -1856,7 +1861,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>) = @@ -1910,17 +1915,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>) = @@ -1944,7 +1949,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) @@ -2112,11 +2117,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 = @@ -2125,7 +2130,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 = @@ -2134,7 +2139,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 = @@ -2143,7 +2148,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 = @@ -2194,7 +2199,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 }) @@ -2204,7 +2209,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 }) @@ -2214,7 +2219,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 @@ -2229,7 +2234,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 @@ -2244,7 +2249,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 @@ -2263,7 +2268,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 -> @@ -2302,7 +2307,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 @@ -2321,7 +2326,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 -> @@ -2359,15 +2364,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<_>) = @@ -2397,7 +2402,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 () @@ -2412,13 +2417,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 @@ -2440,7 +2445,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 @@ -2464,7 +2469,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<_>) = @@ -2473,7 +2478,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 = @@ -2491,7 +2496,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 b81f0a943417ea90be98b4c5883324e00ba66584 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 26 Oct 2016 22:09:06 -0400 Subject: [PATCH 107/327] 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 edd149c2021..1c3ce9ebaa3 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1831,22 +1831,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 527440cfebf247d64fbcc1384ceebeeb05e61dbc Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 27 Oct 2016 17:49:21 +1100 Subject: [PATCH 108/327] 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 1c3ce9ebaa3..840886105fc 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1835,34 +1835,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 cfb12f0dce0eb431ec2577eecc96250cb77ff82c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 27 Oct 2016 18:59:23 +1100 Subject: [PATCH 109/327] 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 840886105fc..0678094ac08 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1838,7 +1838,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 f4191ddc474598095eaf572d51f81e5ed1cc4bc9 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 13:17:25 +1100 Subject: [PATCH 110/327] 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 0678094ac08..dc1d1454eb6 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -515,9 +515,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 @@ -529,114 +534,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>() @@ -1013,7 +1040,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 @@ -1061,9 +1088,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]) @@ -1075,8 +1102,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) @@ -1104,7 +1134,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 @@ -1112,11 +1142,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 @@ -1163,14 +1194,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>() @@ -1179,14 +1211,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>) = @@ -1220,7 +1253,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 @@ -1228,16 +1261,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>) = @@ -1270,7 +1304,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 @@ -1278,14 +1312,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>) = @@ -1308,7 +1343,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 @@ -1316,11 +1351,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 @@ -1381,7 +1417,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 @@ -1389,12 +1425,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 @@ -1456,11 +1493,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 @@ -1473,7 +1511,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 @@ -1624,10 +1662,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> = @@ -1653,7 +1691,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)) [] @@ -1867,7 +1905,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>) = @@ -2136,7 +2174,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 = @@ -2145,7 +2183,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 = @@ -2154,7 +2192,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 = @@ -2475,7 +2513,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<_>) = @@ -2484,7 +2522,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 6586aba979c7552f1bb3f50ba1f9709761a8a531 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 13:36:13 +1100 Subject: [PATCH 111/327] 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 dc1d1454eb6..b3c1275d6da 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -461,7 +461,7 @@ namespace Microsoft.FSharp.Collections abstract OnComplete : PipeIdx -> unit abstract OnDispose : unit -> unit - type IPipeline = + type IOutOfBand = abstract StopFurtherProcessing : PipeIdx -> unit [] @@ -517,7 +517,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> @@ -538,7 +538,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) @@ -551,8 +551,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) @@ -560,27 +560,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) @@ -589,13 +589,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) @@ -603,67 +603,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>() @@ -757,7 +757,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 () @@ -767,13 +767,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 () @@ -783,13 +783,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 () @@ -800,7 +800,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 () = @@ -827,7 +827,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 @@ -839,7 +839,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 () = @@ -911,8 +911,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 @@ -920,14 +920,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>) = @@ -946,7 +946,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 @@ -957,10 +957,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 = @@ -975,7 +975,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 @@ -986,35 +986,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 @@ -1027,11 +1027,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 () @@ -1041,15 +1041,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>() = @@ -1119,7 +1119,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 @@ -1132,7 +1132,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>() @@ -1245,7 +1245,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 @@ -1296,7 +1296,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 @@ -1323,13 +1323,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 @@ -1340,7 +1340,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>) = @@ -1378,8 +1378,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 @@ -1391,7 +1391,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 @@ -1405,16 +1405,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 4b466941d31a249ae51849042f061ba6529cdb0f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 13:40:36 +1100 Subject: [PATCH 112/327] 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 b3c1275d6da..6cbd2f174dc 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1551,7 +1551,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 [] @@ -1573,7 +1573,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 [] @@ -1588,7 +1588,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 [] @@ -1600,7 +1600,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 @@ -1613,7 +1613,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 @@ -1626,7 +1626,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 @@ -1732,7 +1732,7 @@ namespace Microsoft.FSharp.Collections this.Value <- some halt () | None -> () - Unchecked.defaultof }) + Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun pick -> pick.Value [] @@ -1750,7 +1750,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 [] @@ -1805,7 +1805,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 [] @@ -1837,7 +1837,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 @@ -1886,7 +1886,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 }) @@ -2000,8 +2000,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 [] @@ -2246,7 +2245,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 [] @@ -2256,7 +2255,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 [] @@ -2267,7 +2266,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 @@ -2282,7 +2281,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 @@ -2300,7 +2299,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 @@ -2323,7 +2322,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 @@ -2358,7 +2357,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 @@ -2381,7 +2380,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 @@ -2450,7 +2449,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 [] @@ -2472,7 +2471,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 @@ -2497,7 +2496,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 a05dbe9abccc62e6bbee625f5096564a717fa9e5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 19:58:10 +1100 Subject: [PATCH 113/327] 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 6cbd2f174dc..22496b3c60b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -535,6 +535,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 #) @@ -555,7 +556,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> () @@ -590,7 +591,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> () @@ -1202,7 +1203,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>() @@ -1216,11 +1217,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) @@ -1275,10 +1298,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>) = @@ -1498,7 +1521,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 @@ -1512,47 +1695,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>) = @@ -1562,73 +1733,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<_>) = @@ -1669,18 +1794,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 = @@ -1701,12 +1829,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 = @@ -1723,17 +1853,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 = @@ -1743,15 +1863,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 6b20dbbb97afc35fda6149e07fea9181ba5c9ac9 Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 29 Oct 2016 22:26:16 -0400 Subject: [PATCH 114/327] Seq.item/iter2/iteri2/fold2/forall2/exists2 --- src/fsharp/FSharp.Core/seq.fs | 130 ++++++++++++++++++++++------------ 1 file changed, 83 insertions(+), 47 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 22496b3c60b..37bce20f958 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -56,19 +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 - invalidArgFmt "index" - "{0}\nseq was short by {1} {2}" - [|SR.GetString SR.notEnoughElements; index; (if index=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) @@ -1727,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>) = @@ -1757,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())) @@ -1922,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>) = @@ -2531,27 +2551,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 261aadaa493c1095a199147d6bd77a4217bf71f6 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 30 Oct 2016 14:56:56 +1100 Subject: [PATCH 115/327] 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 37bce20f958..fa917d6acb3 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) @@ -1164,7 +1166,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 () @@ -1180,14 +1182,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) @@ -1197,17 +1199,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> () = @@ -1220,11 +1222,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) @@ -1255,7 +1257,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 @@ -1269,17 +1271,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 @@ -1306,7 +1308,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 @@ -1320,17 +1322,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>) = @@ -1359,11 +1361,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 92d00771b304335e4474cbd641d1025ba5f65f96 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 30 Oct 2016 18:58:55 +1100 Subject: [PATCH 116/327] 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 5bbb608df760aeefeb27e8f2389a8d0f0531abb9 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 30 Oct 2016 19:08:45 +1100 Subject: [PATCH 117/327] 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 fa917d6acb3..6731fb656e0 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 5598710818c4147e5e66576190907433b7696f5c Mon Sep 17 00:00:00 2001 From: liboz Date: Mon, 31 Oct 2016 19:40:51 -0400 Subject: [PATCH 118/327] 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 6731fb656e0..bb30091c759 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 @@ -2156,27 +2189,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 81fe1416feda18238d0c207f83efdbc1798047a5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 1 Nov 2016 18:25:18 +1100 Subject: [PATCH 119/327] 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 bb30091c759..8311e051355 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 d0a667f1dd3cea5b21abfc2fbb3af60f2ab17149 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 3 Nov 2016 22:50:07 -0400 Subject: [PATCH 120/327] 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 4ab65e83f4f..19b4cdac8ca 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.fsproj +++ b/src/fsharp/FSharp.Core/FSharp.Core.fsproj @@ -82,6 +82,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 8311e051355..e3af860f12c 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 = - 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 - 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 @@ -2027,8 +350,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])) [] @@ -2043,7 +366,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 @@ -2072,7 +395,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>) = @@ -2126,17 +449,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>) = @@ -2160,7 +483,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) @@ -2191,7 +514,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>) = @@ -2295,7 +618,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>) = @@ -2309,11 +632,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 = @@ -2322,7 +645,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 = @@ -2331,7 +654,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 = @@ -2340,7 +663,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 = @@ -2373,7 +696,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>) = @@ -2391,7 +714,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 *) }) @@ -2401,7 +724,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 *) }) @@ -2411,7 +734,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 @@ -2426,7 +749,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 @@ -2441,7 +764,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 @@ -2460,7 +783,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 -> @@ -2499,7 +822,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 @@ -2518,7 +841,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 -> @@ -2556,15 +879,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<_>) = @@ -2575,7 +898,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 @@ -2595,7 +918,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 @@ -2610,7 +933,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 () @@ -2625,13 +948,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 @@ -2653,7 +976,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 @@ -2677,7 +1000,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<_>) = @@ -2686,7 +1009,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 = @@ -2704,7 +1027,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 a9d165b7f5e37bece9dc30d54776cd38fcd8c624 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 5 Nov 2016 10:59:20 +1100 Subject: [PATCH 121/327] 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 e3af860f12c..8317b9429bd 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 = @@ -351,7 +355,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])) [] @@ -395,7 +399,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>) = @@ -645,7 +649,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 = @@ -654,7 +658,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 = @@ -663,7 +667,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 = @@ -1000,7 +1004,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<_>) = @@ -1009,7 +1013,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 b3a73775ddf5c28ec459a2adbb718c815ebb8f59 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 5 Nov 2016 11:02:40 +1100 Subject: [PATCH 122/327] 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 4eb712e3750af2d2471314ed0710a467625bfe73 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 5 Nov 2016 15:37:03 +1100 Subject: [PATCH 123/327] 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 8317b9429bd..8e1395eda70 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) @@ -885,10 +882,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) @@ -933,17 +926,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 38d3b143a5b2b83e876bb0f51b06971c4f422ef3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 6 Nov 2016 08:56:59 +1100 Subject: [PATCH 124/327] 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 10c4389cb95..932a849aa54 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.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 @@ -404,6 +461,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 c452c3f31c4..46020db9e40 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 8e5337ef4a8..0464eb1580f 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 531eebf0e8f..15ceb66e7d8 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 7d320ad8483..8e71c1daaee 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 f731fcdbcc0..c5601ff12ef 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 01fe5030a71f55a3bd6094138b03cb3d83d5ec6a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 13 Nov 2016 19:23:54 +1100 Subject: [PATCH 125/327] 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 8e1395eda70..d447c1ddf6d 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 7cf952b72c6c9320ebba04eb0c6e41eeaa9e172d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 16 Nov 2016 19:54:50 +1100 Subject: [PATCH 126/327] 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 c1df69c68e2371bcb10b01c6fbbe0818a457cde8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 17 Nov 2016 19:50:07 +1100 Subject: [PATCH 127/327] 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 27e57932b946a27845c735d1a13ad7c8b8ecd574 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 21 Nov 2016 19:50:23 +1100 Subject: [PATCH 128/327] 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 d447c1ddf6d..31a60648ee3 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 d381d6c7cafba966ebc9368a1f7d0d7783a3c108 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 28 Sep 2016 19:42:15 +1000 Subject: [PATCH 129/327] 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 d2cfe54622e..55269ffc245 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 dc2db6644232c9f7fc216553ccd033b8137d1724 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Sep 2016 16:05:23 +1000 Subject: [PATCH 130/327] 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 552021c1beaae563a6dd8de991a431c9b9242009 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Sep 2016 18:05:20 +1000 Subject: [PATCH 131/327] 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 55269ffc245..8b4805e909a 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 a18d44ec7fbe4ec483b5d774a3e46ab82f382cda Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Sep 2016 18:49:22 +1000 Subject: [PATCH 132/327] 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 8b4805e909a..15a86b01285 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 22f458552303517c45a584d897837abf68af884f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Sep 2016 19:59:49 +1000 Subject: [PATCH 133/327] 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 15a86b01285..4b67217a854 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 21a0daf924f9c6e6cde83b73352ed4533684f461 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 2 Oct 2016 18:26:16 +1100 Subject: [PATCH 134/327] 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 4b67217a854..7101c67e336 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 97e186e21009a6945e2fddabbf0a41729fb2d5ca Mon Sep 17 00:00:00 2001 From: liboz Date: Mon, 3 Oct 2016 16:34:00 -0400 Subject: [PATCH 135/327] 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 7101c67e336..eff35d83cc5 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 80a9feda4aef7c54a7519b3f7f36da7e1add80fa Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 4 Oct 2016 20:00:31 +1100 Subject: [PATCH 136/327] 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 eff35d83cc5..ffa450182d2 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 a9012ffff23491bc70d2f1a183649e1f2ce15191 Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 4 Oct 2016 22:13:24 -0400 Subject: [PATCH 137/327] 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 ffa450182d2..4241075d932 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 a2cd9d7fae04b6ba573b815e99ba98c3de2151a3 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 5 Oct 2016 10:09:17 -0400 Subject: [PATCH 138/327] 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 4241075d932..33e98c1973b 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 3c476e68744ec71557f1c12f24ffd4aa3472c8b1 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 7 Oct 2016 20:18:45 +1100 Subject: [PATCH 139/327] 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 33e98c1973b..d39f68e58bc 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 bbc5951bea0d4aa391e0e95c0bd19f0e024bad2b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 7 Oct 2016 20:30:18 +1100 Subject: [PATCH 140/327] 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 d39f68e58bc..32f4b7e031f 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 885297fa51c5818a56be38cc932c123a4323ac5c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Oct 2016 06:55:59 +1100 Subject: [PATCH 141/327] 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 32f4b7e031f..24447c21c96 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 7f9369a899a11bb70cd6b9b9fac0098542fd86cd Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Oct 2016 10:36:05 +1100 Subject: [PATCH 142/327] 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 24447c21c96..4a47b5a6e70 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 7ad19137bba037ebbf3a8281934e82720017385e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Oct 2016 19:35:08 +1100 Subject: [PATCH 143/327] 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 4a47b5a6e70..c28139bc771 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 7d8eda67ed8b0c1aa52ac015fe4ece88fd5359ac Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Oct 2016 20:19:46 +1100 Subject: [PATCH 144/327] 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 c28139bc771..bc9f0e8cf56 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 91a7ab5277c1f85e57fa26a42cf76ffcbf09fa1d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 8 Oct 2016 20:38:54 +1100 Subject: [PATCH 145/327] 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 bc9f0e8cf56..1cbf9680537 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 621bc0f85530f0b2d57abb5ef767be3e6bc13561 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 05:36:56 +1100 Subject: [PATCH 146/327] 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 1cbf9680537..a6c72fd49e7 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 1241312eef70dbed367b299661dcd446025d7570 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 06:00:07 +1100 Subject: [PATCH 147/327] 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 a6c72fd49e7..a76e80b5b72 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 c85e5b6a3c981db40d0ae56b3f37d080365ffdc5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 06:12:42 +1100 Subject: [PATCH 148/327] 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 a76e80b5b72..caf5919c31c 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 585d48576aea53da6a79dfaa4087f00527c307e3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 06:32:14 +1100 Subject: [PATCH 149/327] 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 caf5919c31c..b70ee2052b5 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 7444cfd5cde2acd019658f879fa9b87f97222d94 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 08:19:24 +1100 Subject: [PATCH 150/327] 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 b70ee2052b5..bc9f0e8cf56 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 f7d8ca4745d382717e25549ebcf9aa6b773df0f3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 13:32:57 +1100 Subject: [PATCH 151/327] 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 bc9f0e8cf56..f6e4825f66c 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 1b10b876583a15899ad01dfdb791a48178799840 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 14:12:59 +1100 Subject: [PATCH 152/327] 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 f6e4825f66c..d24712747a3 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 ae5ce1826cab5ebab81e7ec21d094f53ffca0ce5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 16:29:19 +1100 Subject: [PATCH 153/327] 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 d24712747a3..b1f73a1c76b 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 7094b918656187405b3bce53b66b969786c1c439 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 19:09:42 +1100 Subject: [PATCH 154/327] 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 b1f73a1c76b..47344afca10 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 e1ed2cf3928c80d8c6a5d36264578790a607d9c9 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 9 Oct 2016 19:29:55 +1100 Subject: [PATCH 155/327] 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 47344afca10..1502db75ef8 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 855723979828d5704039b19c645d5830e972304a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 10 Oct 2016 19:35:48 +1100 Subject: [PATCH 156/327] 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 1502db75ef8..1b20025b4e8 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 5462206cc566c5b6fb8100cad26188a7265f4b4a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 10 Oct 2016 19:42:40 +1100 Subject: [PATCH 157/327] 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 1b20025b4e8..437d2373100 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 0e0da17e13b9a931c339cc9ec675dc7eba9e377b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 10 Oct 2016 19:46:35 +1100 Subject: [PATCH 158/327] 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 437d2373100..ece6311ec57 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 dc44f6bbf727e0a1a8e69f526fdad29c1529da6a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 11 Oct 2016 19:32:19 +1100 Subject: [PATCH 159/327] 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 ece6311ec57..1931bef7ffb 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 69a2c7140007411a72057736cc4122728c159d02 Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 11 Oct 2016 16:28:24 -0400 Subject: [PATCH 160/327] 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 1931bef7ffb..e91b68202be 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 b68b00b128095977c80b756a79951533e7fd130d Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 11 Oct 2016 21:16:38 -0400 Subject: [PATCH 161/327] 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 e91b68202be..9dc2b45ad88 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 13a324e4623210af63bfba0162210d30d3a03ae5 Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 11 Oct 2016 22:36:09 -0400 Subject: [PATCH 162/327] 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 9dc2b45ad88..5f7e05a5b55 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 82f340419038260166b27019dfd4aac9faca0cda Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 12 Oct 2016 19:08:05 +1100 Subject: [PATCH 163/327] 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 5f7e05a5b55..7481b5809fe 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 5c105592764f98eec2d060878542d8289a9ce8a0 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 12 Oct 2016 20:23:43 +1100 Subject: [PATCH 164/327] 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 7481b5809fe..573921cf6ff 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 374304b5ae127de825a5fcd702c1b8e4e68a4747 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 12 Oct 2016 21:46:26 -0400 Subject: [PATCH 165/327] 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 573921cf6ff..5c2ed494117 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 d0508b5b76bc6b9e84eb96415f95eb96255756ef Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 13 Oct 2016 06:19:09 -0400 Subject: [PATCH 166/327] 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 5c2ed494117..ca783034f5b 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 b34f27d3b62b71be81f3d31a437ec9611fa921d6 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 13 Oct 2016 21:55:52 -0400 Subject: [PATCH 167/327] 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 ca783034f5b..1d3bd84c1cc 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 e5babc1a2202f02d5c3054de4939541507a91210 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 13 Oct 2016 22:53:06 -0400 Subject: [PATCH 168/327] 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 1d3bd84c1cc..b5be36b7d0e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1542,15 +1542,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 d7a3a104415eef600b23b19f69c3aacec5d30cdb Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:31:04 +1100 Subject: [PATCH 169/327] 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 b5be36b7d0e..abd7883ae2f 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 363625afe0666ef12d49db72677e2e5b03f04cd0 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:46:05 +1100 Subject: [PATCH 170/327] 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 abd7883ae2f..2392a6d082e 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) @@ -1325,6 +1276,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 c16e218524cd08515d6c9ed301f4959f7915efc0 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:52:39 +1100 Subject: [PATCH 171/327] cleaning up SeqComposer.Helpers - better comments - consistent casing --- src/fsharp/FSharp.Core/seq.fs | 87 +++++++++++++++++------------------ 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 2392a6d082e..e7326ad3940 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) @@ -939,7 +938,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 () @@ -957,13 +956,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)" @@ -979,7 +978,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.UpcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -992,7 +991,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>() @@ -1000,10 +999,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 @@ -1049,7 +1048,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 () @@ -1064,18 +1063,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 @@ -1099,7 +1098,7 @@ namespace Microsoft.FSharp.Collections moveNext () else result.SeqState <- SeqProcessNextStates.Finished - (Helpers.UpcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -1113,10 +1112,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 @@ -1149,7 +1148,7 @@ namespace Microsoft.FSharp.Collections moveNext tail | _ -> result.SeqState <- SeqProcessNextStates.Finished - (Helpers.UpcastISeqComponent seqComponent).OnComplete () + (Helpers.upcastISeqComponent seqComponent).OnComplete () false interface IEnumerator with @@ -1163,10 +1162,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 @@ -1234,7 +1233,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 @@ -1248,10 +1247,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 @@ -1337,12 +1336,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 @@ -1372,13 +1371,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>) = @@ -1475,9 +1474,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> = @@ -1657,7 +1656,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 882475659850a35ef9404bb9b592b66cce882627 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 05:59:00 +1100 Subject: [PATCH 172/327] 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 e7326ad3940..61e7fe0065d 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) @@ -1512,7 +1516,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 863c0742d3b7de7148dd7e2f84fc43a9f02b0fdc Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 06:06:25 +1100 Subject: [PATCH 173/327] 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 61e7fe0065d..e596d4c41db 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) @@ -1501,7 +1508,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 ddbd185afa588b010a9d0ad610d44b9f2d786fa4 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 06:09:39 +1100 Subject: [PATCH 174/327] 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 e596d4c41db..aa713d1e8ce 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) @@ -1514,9 +1490,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 6640064c2035e3934b72d99234f1b46ba7ad21c3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 10:15:33 +1100 Subject: [PATCH 175/327] 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 aa713d1e8ce..df79d975a69 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) @@ -1172,6 +1119,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. @@ -1264,7 +1261,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) @@ -1344,14 +1341,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 47f3f5d4a04cac7ebd94dce118d966fe7d76e3cf Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 10:35:24 +1100 Subject: [PATCH 176/327] 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 df79d975a69..83a33dcc56a 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 @@ -936,7 +954,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 @@ -1049,7 +1067,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 @@ -1099,7 +1117,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 @@ -1149,7 +1167,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 @@ -1234,7 +1252,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 @@ -1348,7 +1366,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 3011092d089541b62c5c878a6b01f1694299c91b Mon Sep 17 00:00:00 2001 From: liboz Date: Fri, 14 Oct 2016 20:13:25 -0400 Subject: [PATCH 177/327] 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 83a33dcc56a..e1894c87af1 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) @@ -1497,19 +1521,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 0ac206aa1b4062b23cc6933dd7483cc1be20e751 Mon Sep 17 00:00:00 2001 From: liboz Date: Fri, 14 Oct 2016 20:31:55 -0400 Subject: [PATCH 178/327] 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 e1894c87af1..592d0593c97 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1526,7 +1526,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 8400cd0f6b560702240203b233e81d0dc982c84a Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 15 Oct 2016 00:06:36 -0400 Subject: [PATCH 179/327] seq.tail and a fix to takewhile to use avoidtailcall --- src/fsharp/FSharp.Core/seq.fs | 51 +++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 592d0593c97..9f2082ce121 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,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) @@ -975,7 +997,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)) @@ -986,7 +1008,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 @@ -1088,7 +1110,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)) @@ -1098,7 +1120,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 @@ -1138,7 +1160,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)) @@ -1147,7 +1169,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 @@ -1188,7 +1210,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)) @@ -1197,7 +1219,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 @@ -1273,7 +1295,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)) @@ -1282,7 +1304,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 @@ -2248,12 +2270,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 60a379fa11b1b0a7dfec699945d808c56a728b27 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 16:57:55 +1100 Subject: [PATCH 180/327] 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 9f2082ce121..0d87a1e83ab 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 @@ -1739,7 +1714,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 e9d1593e4df7aaf0a632ddd1bf10f0cb3f59ee34 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 18:25:43 +1100 Subject: [PATCH 181/327] 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 0d87a1e83ab..748a14bd503 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1057,10 +1057,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 @@ -1076,19 +1085,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 @@ -1097,6 +1109,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 @@ -2285,10 +2298,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 75261c72c05c1b68fc4f862c1cf0eb86a8c41476 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 18:48:47 +1100 Subject: [PATCH 182/327] 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 748a14bd503..c9eb79ab082 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1092,7 +1092,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 692de1a4726ffc3ccbb061bd1b5766847d326e99 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 19:02:09 +1100 Subject: [PATCH 183/327] 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 c9eb79ab082..3ec9b65703d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2298,18 +2298,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 f3894883f310e14e6cb237107b52f57fd2d8fc26 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 19:07:03 +1100 Subject: [PATCH 184/327] 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 3ec9b65703d..ad609a1fc08 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -2002,26 +2002,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 6a96574edc13732bf4f43c5662bb215d25ea8b02 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 15 Oct 2016 19:24:50 +1100 Subject: [PATCH 185/327] 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 ad609a1fc08..af784af63a0 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1056,6 +1056,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) @@ -1091,9 +1094,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> () @@ -1118,6 +1118,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) @@ -1171,6 +1183,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) @@ -1510,9 +1525,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> = @@ -1727,7 +1742,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>) = @@ -2003,19 +2018,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 = @@ -2293,13 +2308,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 cb50fd1697ce2641b6194a0793d60cdcf484c49c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 05:10:24 +1100 Subject: [PATCH 186/327] 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 af784af63a0..d201984170f 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1060,7 +1060,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 @@ -1071,7 +1071,7 @@ namespace Microsoft.FSharp.Collections initMoveNext <- fun () -> result.SeqState <- SeqProcessNextStates.InProcess - array <- lazyArray.Value + array <- delayedArray () initMoveNext <- ignore let rec moveNext () = @@ -1091,16 +1091,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 @@ -1109,7 +1109,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 @@ -1118,14 +1118,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 ()) @@ -2017,20 +2017,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 = @@ -2307,14 +2316,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 4ca8f14a92c2a62694f818d04fc0cb4eba71b1b8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 05:15:23 +1100 Subject: [PATCH 187/327] 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 d201984170f..46caa751dcc 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) = @@ -972,7 +973,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)) @@ -983,7 +984,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 @@ -1097,7 +1098,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)) @@ -1107,7 +1108,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 @@ -1160,7 +1161,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)) @@ -1169,7 +1170,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 @@ -1213,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,'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)) @@ -1222,7 +1223,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 @@ -1298,7 +1299,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)) @@ -1307,7 +1308,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 8a4e1cc1eb086226928499b57368ef6d9961cb70 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 06:11:37 +1100 Subject: [PATCH 188/327] 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 46caa751dcc..65f6f762ffc 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -926,9 +926,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]) @@ -978,6 +979,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 @@ -1045,6 +1056,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 @@ -1103,6 +1121,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 @@ -1166,6 +1195,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 @@ -1219,6 +1265,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 @@ -1304,6 +1367,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 @@ -1390,6 +1471,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 ac6edc34c8cbfaa0d864f22798bbb225266b8c72 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 06:16:48 +1100 Subject: [PATCH 189/327] 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 65f6f762ffc..d01a8c3297c 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1521,9 +1521,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>) = @@ -2193,12 +2197,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 b0d980981c9e16e8afb761499a19f99555859e49 Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 15 Oct 2016 11:34:13 -0400 Subject: [PATCH 190/327] 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 d01a8c3297c..b7d63f0a8dc 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 37c0487c2c1a4a1be49977a99e8e1deb052a61c5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 10:09:42 +1100 Subject: [PATCH 191/327] 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 87b5b0670b0c84a406bcce3a9baf378919ff06c7 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 16 Oct 2016 18:11:25 +1100 Subject: [PATCH 192/327] 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 b7d63f0a8dc..9210cd8b854 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -995,6 +995,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 @@ -1007,6 +1010,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 @@ -1138,6 +1143,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 @@ -1152,6 +1160,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>) = @@ -1208,7 +1218,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 @@ -1227,7 +1237,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 @@ -1278,7 +1290,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 @@ -1297,7 +1309,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 @@ -1391,6 +1405,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 @@ -1411,6 +1427,8 @@ namespace Microsoft.FSharp.Collections state <- folder'.Invoke (state, result.Current) idx <- idx + 1 + + (Helpers.upcastISeqComponent components).OnComplete () state From b81417d4d06b4870b685e1b0e9d150626d645da7 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 17 Oct 2016 20:17:23 +1100 Subject: [PATCH 193/327] 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 9210cd8b854..60241df2f1e 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 Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State @@ -948,7 +981,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 () = @@ -985,6 +1019,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> () @@ -1067,6 +1103,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 () @@ -1090,7 +1128,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 @@ -1132,6 +1170,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> () @@ -1177,7 +1234,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 @@ -1211,6 +1268,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) @@ -1252,7 +1311,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 @@ -1283,6 +1342,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) @@ -1340,9 +1401,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 @@ -1356,7 +1425,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 () @@ -1387,18 +1456,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 @@ -1416,12 +1490,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) @@ -1495,6 +1572,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 () @@ -2203,12 +2282,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 3dd57da03f67e8977db54d647fd4ba175b06dfc5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 18:25:12 +1100 Subject: [PATCH 194/327] 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 60241df2f1e..5a5f202cfb3 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>() = @@ -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 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 9c3fda0ab20a1415cfc2c8024694172bd82b38ad Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 19:50:47 +1100 Subject: [PATCH 195/327] 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 5a5f202cfb3..72db32f1133 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 = @@ -1014,7 +1015,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 () @@ -1098,7 +1113,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) @@ -1263,7 +1294,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> () @@ -1337,7 +1386,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> () @@ -1451,7 +1518,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> () @@ -1567,7 +1661,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 f46148fc166274dd56f92cab7e5ec8a4a0a286bf Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 19:56:59 +1100 Subject: [PATCH 196/327] Removed Fold --- src/fsharp/FSharp.Core/seq.fs | 139 +++------------------------------- 1 file changed, 9 insertions(+), 130 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 72db32f1133..80bf1a07999 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 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]) @@ -1043,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 @@ -1138,18 +1119,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)) @@ -1228,25 +1197,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)) @@ -1331,26 +1281,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)) @@ -1423,26 +1353,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. @@ -1570,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" @@ -1684,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 @@ -1957,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 e6dd9322316a1086f81091e227440c47b38fb100 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 18 Oct 2016 20:01:20 +1100 Subject: [PATCH 197/327] 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 80bf1a07999..66d134891c7 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 @@ -1112,13 +1099,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)) @@ -1184,19 +1164,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)) @@ -1264,23 +1231,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)) @@ -1336,23 +1286,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 54cc0debb5680af88b93f97e9ec1114b3af43156 Mon Sep 17 00:00:00 2001 From: liboz Date: Tue, 18 Oct 2016 20:18:13 -0400 Subject: [PATCH 198/327] 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 66d134891c7..872e2e0ac09 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 d0612365c1d4b59201b74d6d3aede0a3749eec9a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 19 Oct 2016 18:20:55 +1100 Subject: [PATCH 199/327] 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 872e2e0ac09..2cea1544f3e 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 @@ -1087,7 +1085,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 099f9afe992b0fb6bcfdb23c4144cb5eaf244d8a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 19 Oct 2016 21:39:49 +1100 Subject: [PATCH 200/327] 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 e810f4efe4804495f72a161385c476a23b3ba486 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 18:27:37 -0400 Subject: [PATCH 201/327] 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 2cea1544f3e..3ebac351ff0 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 7853c1eed9fec076d815f9960e09e488d1bdcb26 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 18:48:31 -0400 Subject: [PATCH 202/327] 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 3ebac351ff0..bfc318e5fa2 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> = @@ -1169,10 +1171,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 0c354e5aecf0208d7469f75c1c18bf0f25d5a1e0 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 18:54:59 -0400 Subject: [PATCH 203/327] 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 bfc318e5fa2..ade84d84894 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 8b05b7d558c79eed81d13a873b5f2d17e8a31c0a Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 19:58:41 -0400 Subject: [PATCH 204/327] 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 ade84d84894..6091968d6e9 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 308a3cb19d0873d2e00b044ebe22cbfcf214c1f3 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 19 Oct 2016 21:32:50 -0400 Subject: [PATCH 205/327] 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 6091968d6e9..f16fb6ac3cb 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 69fa20293e379caee7cac5c11dc50ce202a0e903 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 16:55:58 +1100 Subject: [PATCH 206/327] 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 f16fb6ac3cb..54a9070c2ac 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 () @@ -1082,9 +1085,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 @@ -1092,7 +1093,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 () @@ -1147,16 +1148,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 @@ -1212,15 +1210,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 -> @@ -1267,15 +1263,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 addce476c0277e8dd9ba071f22daebebc35f3eb8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 17:56:26 +1100 Subject: [PATCH 207/327] 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 54a9070c2ac..39c9bbb9f06 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 79d6e71fcd87334e3e49deb5d752bb154bc5cbd9 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 18:24:25 +1100 Subject: [PATCH 208/327] 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 39c9bbb9f06..3b3c99e4685 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 519d528f0724c88b10cf55b381908d4e16c22b60 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 19:25:47 +1100 Subject: [PATCH 209/327] 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 3b3c99e4685..bc62d21fb59 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 d08afb3a8767ef80849630bbb48ee0586ea5989f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 20 Oct 2016 20:08:10 +1100 Subject: [PATCH 210/327] 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 bc62d21fb59..4b9d10ab674 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 @@ -1072,6 +1074,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)) @@ -1084,19 +1090,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)) @@ -1136,6 +1139,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> () @@ -1145,20 +1154,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)) @@ -1196,6 +1200,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>() @@ -1209,21 +1223,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)) @@ -1252,6 +1259,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> () @@ -1262,21 +1280,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 0bb4d329b73d2e0b9a1226bd4b5ed8a96159526f Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 20 Oct 2016 07:24:44 -0400 Subject: [PATCH 211/327] 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 4b9d10ab674..b5ca622008d 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 d0f68a14eadf85af7260c8db595d3aca484be2f6 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 20 Oct 2016 14:03:04 -0400 Subject: [PATCH 212/327] 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 b5ca622008d..cf054c3618e 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 1524c683b13c49ad1bca11f5b99b85c6da68b913 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 20 Oct 2016 16:29:50 -0400 Subject: [PATCH 213/327] 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 cf054c3618e..36a2a2b51b8 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1242,9 +1242,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 1f0a8e08359c07c8c0fa714734189159512a9004 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 13:36:33 +1100 Subject: [PATCH 214/327] 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 36a2a2b51b8..c882e888626 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 cba0be9429db88660fa36425915e6ddf094a3443 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 13:53:33 +1100 Subject: [PATCH 215/327] 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 c882e888626..7a1dec5f462 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 4ebe2dea829525fd3a365af130d39649aa82f430 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 14:02:20 +1100 Subject: [PATCH 216/327] 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 7a1dec5f462..a1e8a5dae95 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 ee1e12797ab1e9bf6e9dead24866c93ae4416532 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:31:38 +1100 Subject: [PATCH 217/327] 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 a1e8a5dae95..dc63e2195c1 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 f518f196a9831c0241430d4146f2fccee17b09c5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:49:17 +1100 Subject: [PATCH 218/327] 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 dc63e2195c1..b0999fa7e86 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 97a4552311bfe518ad09ed84bc069a545859c7ad Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:53:22 +1100 Subject: [PATCH 219/327] 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 b0999fa7e86..b2daae2f9e4 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 7516f7a9572e9b2d461a594e3a554edcbfd288f1 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 15:57:34 +1100 Subject: [PATCH 220/327] 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 b2daae2f9e4..68cd599a99c 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 0ce20c3e8bb2bc48c76332466ac309f176138441 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 16:44:03 +1100 Subject: [PATCH 221/327] 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 68cd599a99c..63b5dc88e76 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 519dedf1d5cead1fad62b57397d0ebb01a96b572 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Fri, 21 Oct 2016 19:37:46 +1100 Subject: [PATCH 222/327] 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 63b5dc88e76..513b108247e 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 10122b898b28fb58f04505160dbd0776b97634b8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 22 Oct 2016 12:38:03 +1100 Subject: [PATCH 223/327] 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 513b108247e..a8fbbfb983c 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 045b101a0afd17bc454c147918503f8b912493a2 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 22 Oct 2016 13:42:57 +1100 Subject: [PATCH 224/327] 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 a8fbbfb983c..0bb125c0be7 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 @@ -1086,10 +1135,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)) @@ -1101,17 +1146,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)) @@ -1151,12 +1187,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> () @@ -1166,15 +1196,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)) @@ -1212,16 +1234,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>() @@ -1234,15 +1246,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)) @@ -1272,17 +1276,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> () @@ -1292,15 +1285,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 fc9ff3eb392c554f81d780493595ae63ba4d65fc Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 22 Oct 2016 18:06:21 +1100 Subject: [PATCH 225/327] 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 0bb125c0be7..13caf1b6a42 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 = @@ -1130,6 +1146,7 @@ namespace Microsoft.FSharp.Collections interface IDisposable with member __.Dispose() = + main.Dispose () active.Dispose () and AppendEnumerable<'T> (sources:list>) = @@ -1137,7 +1154,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)) @@ -1146,8 +1163,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 8d652f6ea24a8c1e06f8b1f5c91d1c86c2710f17 Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 22 Oct 2016 07:29:55 -0400 Subject: [PATCH 226/327] 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 13caf1b6a42..b9b3475b1e2 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 0dbb721a8e87d4ecba701606a4424d98b00472d6 Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 22 Oct 2016 10:38:32 -0400 Subject: [PATCH 227/327] 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 b9b3475b1e2..bd7b8b055cb 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 48ab8e9d27517e0a899fdccfdd64b6f92d851343 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 23 Oct 2016 19:30:44 +1100 Subject: [PATCH 228/327] 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 bd7b8b055cb..034f04e3d6a 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)) @@ -1194,7 +1194,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 @@ -1202,7 +1202,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 @@ -1216,7 +1216,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)) @@ -1244,7 +1244,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 @@ -1252,7 +1252,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 @@ -1266,7 +1266,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)) @@ -1285,14 +1285,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 () = @@ -1305,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,'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 553617ff801fbcb3a9b21709cf0faa22ec4bb871 Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 22 Oct 2016 17:04:03 -0400 Subject: [PATCH 229/327] 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 034f04e3d6a..0b5400b3603 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 f24ddc41060a1349f64647b60d198ca554cf160f Mon Sep 17 00:00:00 2001 From: liboz Date: Sun, 23 Oct 2016 10:05:30 -0400 Subject: [PATCH 230/327] 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 0b5400b3603..6e2f4fa7e1a 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 9908b8b7cae00d7d25b355d220bd11f1e1b029ba Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 24 Oct 2016 20:17:12 +1100 Subject: [PATCH 231/327] 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 6e2f4fa7e1a..f8879349e65 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>) = @@ -1173,7 +1187,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>) = @@ -1186,7 +1200,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 = @@ -1230,12 +1244,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>) = @@ -1280,12 +1294,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 = @@ -1318,12 +1332,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 a8b4de9f86540e4a3a785171d575fdfea4635db3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 25 Oct 2016 19:21:05 +1100 Subject: [PATCH 232/327] 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 f8879349e65..ec6c9f302ef 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)) @@ -1222,7 +1217,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 @@ -1230,7 +1225,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 @@ -1244,7 +1239,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)) @@ -1271,7 +1266,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 @@ -1280,7 +1275,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 @@ -1294,7 +1289,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)) @@ -1312,7 +1307,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 @@ -1332,7 +1327,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 3443b7bbf02125d018dc19990870b32bab54940c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 26 Oct 2016 19:46:49 +1100 Subject: [PATCH 233/327] 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 ec6c9f302ef..dd12b35ea55 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 6b3fb07e976f23b3e309c862da8ae761dae0a949 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 26 Oct 2016 20:24:17 +1100 Subject: [PATCH 234/327] 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 dd12b35ea55..ec7792f5fa2 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>) = @@ -1165,7 +1170,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>) = @@ -1178,14 +1183,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 @@ -1227,7 +1232,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>) = @@ -1243,7 +1248,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 @@ -1277,14 +1282,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 @@ -1315,7 +1320,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 a908437ece4573b3c18d2e81f7ecd7aa101e9b77 Mon Sep 17 00:00:00 2001 From: liboz Date: Wed, 26 Oct 2016 22:09:06 -0400 Subject: [PATCH 235/327] 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 ec7792f5fa2..a19e6c5b2e8 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 140da9579192aff5cf442e037d22221e1a3e2765 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 27 Oct 2016 17:49:21 +1100 Subject: [PATCH 236/327] 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 a19e6c5b2e8..42480b4348a 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 343fcbaabe9c1817d80886a4385b176fa5b36bf9 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 27 Oct 2016 18:59:23 +1100 Subject: [PATCH 237/327] 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 42480b4348a..d1bbe0bc1f5 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 6ddb616d4bab3dfcc4dd0ba9d7e514d198c5eb52 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 13:17:25 +1100 Subject: [PATCH 238/327] 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 d1bbe0bc1f5..256f22807d8 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 @@ -1164,14 +1195,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>() @@ -1180,14 +1212,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>) = @@ -1221,7 +1254,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 @@ -1229,16 +1262,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>) = @@ -1271,7 +1305,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 @@ -1279,14 +1313,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>) = @@ -1309,7 +1344,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 @@ -1317,11 +1352,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 11c89f68925553a2045ad35884e080754dd04131 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 13:36:13 +1100 Subject: [PATCH 239/327] 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 256f22807d8..bec35aae7f9 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>() @@ -1246,7 +1246,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 @@ -1297,7 +1297,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 @@ -1324,13 +1324,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 @@ -1341,7 +1341,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 e2864d3cb00d81690a1d9ade4581c269b7178df4 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 13:40:36 +1100 Subject: [PATCH 240/327] 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 bec35aae7f9..f789407f631 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 e94cda005a97fd0b8f1b450285164734db2c1e31 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 29 Oct 2016 19:58:10 +1100 Subject: [PATCH 241/327] 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 f789407f631..a78556a259d 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> () @@ -1203,7 +1204,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>() @@ -1217,11 +1218,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) @@ -1276,10 +1299,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 d997daacb12a69b23d17a0f7bfe937e646142b08 Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 29 Oct 2016 22:26:16 -0400 Subject: [PATCH 242/327] Seq.item/iter2/iteri2/fold2/forall2/exists2 --- src/fsharp/FSharp.Core/seq.fs | 118 +++++++++++++++++++++++++--------- 1 file changed, 89 insertions(+), 29 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index a78556a259d..dae7f47422b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1728,10 +1728,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 +1774,41 @@ 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())) @@ -1926,16 +1958,20 @@ namespace Microsoft.FSharp.Collections 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>) = @@ -1960,7 +1996,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>) = @@ -2528,25 +2570,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 d2fa4d5b092577ca7aeee7f5b6856cae8bdcf9a1 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 30 Oct 2016 14:56:56 +1100 Subject: [PATCH 243/327] 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 dae7f47422b..94c74402ab5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -542,6 +542,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) @@ -557,7 +559,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> () @@ -695,7 +697,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>) = @@ -705,7 +707,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 @@ -716,7 +718,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 @@ -727,7 +729,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 @@ -738,7 +740,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 @@ -747,7 +749,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 @@ -757,7 +759,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) @@ -767,7 +769,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 @@ -783,7 +785,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 @@ -800,7 +802,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 @@ -815,7 +817,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 @@ -827,7 +829,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) @@ -839,7 +841,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 @@ -861,7 +863,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) @@ -871,7 +873,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) @@ -890,7 +892,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 @@ -909,9 +911,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) @@ -927,7 +929,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 @@ -942,7 +944,7 @@ namespace Microsoft.FSharp.Collections first <- false false else - Helpers.avoidTailCall (next.ProcessNext input) + avoidTailCall (next.ProcessNext input) override this.OnComplete _ = if first then @@ -960,7 +962,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 @@ -1048,10 +1050,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>() = @@ -1076,7 +1078,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 () @@ -1095,13 +1097,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 () @@ -1121,7 +1123,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 @@ -1134,7 +1136,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>() @@ -1142,11 +1144,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) @@ -1178,7 +1180,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 () @@ -1194,14 +1196,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) @@ -1211,17 +1213,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> () = @@ -1234,11 +1236,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) @@ -1269,7 +1271,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 @@ -1283,17 +1285,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 @@ -1320,7 +1322,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 @@ -1334,17 +1336,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>) = @@ -1373,11 +1375,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) @@ -1433,7 +1435,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 @@ -1447,11 +1449,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 @@ -1519,10 +1521,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 @@ -1531,9 +1533,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 @@ -1546,17 +1548,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 0c37f809269f8dfb3e1147826fe564a6322c73aa Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 30 Oct 2016 18:58:55 +1100 Subject: [PATCH 244/327] 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 518558993feb28f15b331d6285d5980dd3afdb03 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 30 Oct 2016 19:08:45 +1100 Subject: [PATCH 245/327] 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 94c74402ab5..74f904074fa 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -549,7 +549,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 63123164928c20c25c0636496359267a1478a678 Mon Sep 17 00:00:00 2001 From: liboz Date: Mon, 31 Oct 2016 19:40:51 -0400 Subject: [PATCH 246/327] 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 74f904074fa..f9440d25586 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -668,6 +668,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>() @@ -967,6 +972,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 @@ -2173,27 +2206,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 0457b1597a77d0098b150d4d67e1c3e7dff1e288 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 1 Nov 2016 18:25:18 +1100 Subject: [PATCH 247/327] 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 f9440d25586..67f39584744 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -975,30 +975,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 ffe74933b662690a73bce2fc5480deb09f198671 Mon Sep 17 00:00:00 2001 From: liboz Date: Thu, 3 Nov 2016 22:50:07 -0400 Subject: [PATCH 248/327] 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 | 1839 +-------------------- 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(+), 1931 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 1909f2ddfb6..861202ebf44 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.fsproj +++ b/src/fsharp/FSharp.Core/FSharp.Core.fsproj @@ -86,6 +86,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 67f39584744..fa03ad9f703 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1,424 +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 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 @@ -433,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>) = @@ -448,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 = - 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 - 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 [] @@ -1749,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 @@ -1786,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<_>) = @@ -1816,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) @@ -1835,7 +144,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) @@ -1855,14 +164,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 [] @@ -1870,40 +179,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 [] @@ -1921,7 +230,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 = @@ -1931,7 +240,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 = @@ -1944,7 +253,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>) = @@ -1960,7 +269,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>) = @@ -1982,7 +291,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 *) }) @@ -1994,12 +303,11 @@ namespace Microsoft.FSharp.Collections checkNonNull "source2" source2 use e2 = source2.GetEnumerator() - let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f) 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) @@ -2014,7 +322,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 @@ -2044,8 +352,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])) [] @@ -2060,7 +368,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 @@ -2089,7 +397,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>) = @@ -2143,17 +451,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>) = @@ -2177,7 +485,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) @@ -2208,7 +516,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>) = @@ -2312,7 +620,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>) = @@ -2326,11 +634,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 = @@ -2339,7 +647,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 = @@ -2348,7 +656,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 = @@ -2357,7 +665,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 = @@ -2390,7 +698,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>) = @@ -2408,7 +716,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 *) }) @@ -2418,7 +726,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 *) }) @@ -2428,7 +736,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 @@ -2443,7 +751,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 @@ -2458,7 +766,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 @@ -2477,7 +785,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 -> @@ -2516,7 +824,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 @@ -2535,7 +843,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 -> @@ -2573,19 +881,18 @@ 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<_>) = - checkNonNull "source1" source1 checkNonNull "source2" source2 use e2 = source2.GetEnumerator() @@ -2593,7 +900,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 @@ -2614,7 +921,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 @@ -2629,7 +936,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 () @@ -2644,13 +951,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 @@ -2672,7 +979,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 @@ -2696,7 +1003,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<_>) = @@ -2705,7 +1012,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 = @@ -2723,7 +1030,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 f1f4cf35819c06f5d6cc232f452fab6a7703dcff Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 5 Nov 2016 10:59:20 +1100 Subject: [PATCH 249/327] 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 fa03ad9f703..cabe5b11e5d 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>) = @@ -164,15 +168,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 @@ -180,12 +184,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 = @@ -196,7 +200,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)) [] @@ -208,12 +212,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 = @@ -353,7 +357,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])) [] @@ -397,7 +401,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>) = @@ -647,7 +651,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 = @@ -656,7 +660,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 = @@ -665,7 +669,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 = @@ -1003,7 +1007,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<_>) = @@ -1012,7 +1016,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 1ca38b56879482afb896e9a0c69baaeacb0a5368 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 5 Nov 2016 11:02:40 +1100 Subject: [PATCH 250/327] 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 b7e58244bea680927293a50b6daddc6ee464d402 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 5 Nov 2016 15:37:03 +1100 Subject: [PATCH 251/327] 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 cabe5b11e5d..50eb6169c1d 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>) = @@ -165,14 +170,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) @@ -887,10 +884,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) @@ -936,17 +929,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 fb170554f17189205ae31c5eaf4b1e90cb032a7e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 6 Nov 2016 08:56:59 +1100 Subject: [PATCH 252/327] 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 10c4389cb95..932a849aa54 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.coreclr.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 @@ -404,6 +461,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 c452c3f31c4..46020db9e40 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 8e5337ef4a8..0464eb1580f 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 531eebf0e8f..15ceb66e7d8 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 7d320ad8483..8e71c1daaee 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 f731fcdbcc0..c5601ff12ef 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 fe881fef96a9ab1471e5d2c62f0783a0e5469c27 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 13 Nov 2016 19:23:54 +1100 Subject: [PATCH 253/327] 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 50eb6169c1d..2b413787dd6 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 2e03f64a50e132ab77a3757bd5f1d570e6fd97a3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 16 Nov 2016 19:54:50 +1100 Subject: [PATCH 254/327] 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 0d40418cb24db5efaa0978921d33ba2df2fdb9da Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 17 Nov 2016 19:50:07 +1100 Subject: [PATCH 255/327] 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 980059d6c4519628d9c1163d2b8f69f65a92af6d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 21 Nov 2016 19:50:23 +1100 Subject: [PATCH 256/327] 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 2b413787dd6..2485f67d4fa 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -184,8 +184,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 4c56f6216a6d619a8b4f2f36a669d35d707b7625 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 6 Dec 2016 21:55:38 -0500 Subject: [PATCH 257/327] 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 b585a8d308af4849561efe6135ca65e959b5e46a Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 6 Dec 2016 23:09:58 -0500 Subject: [PATCH 258/327] 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 31a60648ee3..cc4504f6379 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 @@ -331,7 +334,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 }) @@ -379,7 +382,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 @@ -516,7 +519,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>) = @@ -634,7 +637,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 = @@ -711,7 +720,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 @@ -742,7 +751,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 @@ -757,7 +766,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 @@ -775,7 +784,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 }) @@ -798,7 +807,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 }) @@ -833,7 +842,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 }) @@ -856,7 +865,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 }) @@ -926,7 +935,7 @@ namespace Microsoft.FSharp.Collections halt() Unchecked.defaultof<_> (* return value unsed in ForEach context *) }) |> fun exists -> exists.Value - + [] let head (source : seq<_>) = match tryHead source with @@ -936,7 +945,7 @@ namespace Microsoft.FSharp.Collections [] let tail (source: seq<'T>) = source |> seqFactory (Composer.Seq.TailFactory ()) - + [] let tryLast (source : seq<_>) = source @@ -947,7 +956,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 @@ -971,9 +980,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 @@ -983,8 +992,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 4e8984c40ea76f7e2004277074c89a64e5468a7f Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 7 Dec 2016 21:48:01 -0500 Subject: [PATCH 259/327] 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 cc4504f6379..eb23e063df2 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) @@ -637,13 +637,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 5d8fa5ee03c27d727dc4fd6621525062cccff0f3 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 7 Dec 2016 22:07:54 -0500 Subject: [PATCH 260/327] 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 017da1162eca391362f83de301826210425358cb Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 7 Dec 2016 22:37:28 -0500 Subject: [PATCH 261/327] 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 eb23e063df2..6b7e2dbc561 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -641,7 +641,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 72852de98504d39927531620a889a4d6b2fe5801 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 7 Dec 2016 23:13:24 -0500 Subject: [PATCH 262/327] 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 6b7e2dbc561..815a015c803 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -883,12 +883,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 dc18d818daac40ecee5d110f658582fe90d8e9b5 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 7 Dec 2016 23:33:46 -0500 Subject: [PATCH 263/327] 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 815a015c803..02ffe8de879 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -882,11 +882,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 732e3d88c781957c19e5355636203db629dab733 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 00:07:53 -0500 Subject: [PATCH 264/327] 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 02ffe8de879..ef8940fdd39 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 02a9c2d252bacd7e33f155508ce3b7604569caf6 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 01:50:20 -0500 Subject: [PATCH 265/327] 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 ef8940fdd39..4bc07fe8d6e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -460,11 +460,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 2747dde75738d25dde87b8d040a66c2a3a32b086 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 02:34:20 -0500 Subject: [PATCH 266/327] 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 4bc07fe8d6e..6284361d422 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>) = @@ -451,10 +451,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 07e61e32c21532f77eebc3a15432daa306c1cf91 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 03:24:34 -0500 Subject: [PATCH 267/327] 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 6284361d422..e482b6d4f2a 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -517,7 +517,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 231a6df2fd3036eb7a4c451cb5eda47e8636ca70 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 03:39:30 -0500 Subject: [PATCH 268/327] 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 e482b6d4f2a..acb407acc5e 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -934,9 +934,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 e02bc005804d19f8c78552247544d3b162a5a080 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 04:16:18 -0500 Subject: [PATCH 269/327] 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 acb407acc5e..aa0d6615702 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 a1f1980d576c0fe6d14cd257ac9da5bca576f2a3 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 04:42:50 -0500 Subject: [PATCH 270/327] 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 6a03bc10069f617290bf3ec081bc098c2ee0084d Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 05:04:32 -0500 Subject: [PATCH 271/327] 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 aa0d6615702..c0f20336d4c 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1007,10 +1007,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 0fc259d6241d6637fd9f75701b9d435b9f2b60c5 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Thu, 8 Dec 2016 05:27:40 -0500 Subject: [PATCH 272/327] 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 c0f20336d4c..3615059c5ba 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -451,9 +451,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 f8ecd55b8a46fef3ccbb5cd1ea7730350e6549e3 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 10 Dec 2016 20:04:23 +1100 Subject: [PATCH 273/327] 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 3615059c5ba..8bd192f71ba 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -320,7 +320,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 @@ -366,7 +366,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 @@ -732,7 +732,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 @@ -747,7 +747,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 @@ -762,7 +762,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 @@ -781,7 +781,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 -> @@ -820,7 +820,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 @@ -839,7 +839,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 -> @@ -959,7 +959,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 0481aa8e0e8569c43970357dd9040f8b97e154e1 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Mon, 12 Dec 2016 22:25:47 -0500 Subject: [PATCH 274/327] 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 df90d3452d31bc21fefa3ce6e46c7f1177324135 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Mon, 12 Dec 2016 22:48:13 -0500 Subject: [PATCH 275/327] 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 8bd192f71ba..d230b17073f 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 [] let fold2<'T1,'T2,'State> f (state:'State) (source1: seq<'T1>) (source2: seq<'T2>) = 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 b410467468101f3c8f0b4d24585cc62e6f8cec91 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Mon, 12 Dec 2016 23:37:12 -0500 Subject: [PATCH 276/327] 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 d230b17073f..df74dd1b325 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -703,15 +703,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 8ea28545266739ac7c4361dfb21faa36df6539af Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Mon, 12 Dec 2016 23:52:20 -0500 Subject: [PATCH 277/327] 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 df74dd1b325..ab71a5c5ed0 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -704,33 +704,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 bd9334abf55b73fc8a2bea2c4c69e51f02bc7f32 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Mon, 12 Dec 2016 23:57:39 -0500 Subject: [PATCH 278/327] 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 ab71a5c5ed0..ff65f29bb3d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -704,31 +704,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 [] let inline min (source: seq<_>) = 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 877eb23be8de8410f991b918ab6481a4fd3cf837 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 13 Dec 2016 00:22:38 -0500 Subject: [PATCH 279/327] inline min & inline minBy --- src/fsharp/FSharp.Core/seq.fs | 46 ++++---------------------- src/fsharp/FSharp.Core/seqcomposer.fs | 43 ++++++++++++++++++++++++ src/fsharp/FSharp.Core/seqcomposer.fsi | 6 ++++ 3 files changed, 55 insertions(+), 40 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ff65f29bb3d..60c5e07ed0b 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -719,47 +719,13 @@ namespace Microsoft.FSharp.Collections let inline averageBy (f : 'T -> ^U) (source: seq< 'T >) : ^U = source |> toComposer |> Composer.Seq.averageBy f - [] - 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 *) + [] + let inline min (source: seq<'T>): 'T when 'T : comparison = + source |> toComposer |> Composer.Seq.min - 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 2f0d63286ad23c0161aebbeeba68b53be9bd6686 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 13 Dec 2016 00:32:12 -0500 Subject: [PATCH 280/327] 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 60c5e07ed0b..efb8fa5a1e6 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -743,47 +743,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 46ed3ef6857c1ab5e4243eebd91a9e9a27ce9aac Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 13 Dec 2016 00:43:41 -0500 Subject: [PATCH 281/327] 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 efb8fa5a1e6..46ac3bbdf2d 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -309,26 +309,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 5726d64be037c30c0b180717b1a639ed384cce13 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 13 Dec 2016 00:51:57 -0500 Subject: [PATCH 282/327] 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 46ac3bbdf2d..fff071c8ad5 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -456,19 +456,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 25f352dbcf09d4ae8ec259c2b0a4b66c5aacfa96 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 13 Dec 2016 01:02:53 -0500 Subject: [PATCH 283/327] 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 fff071c8ad5..9cb5e6f61e6 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -800,21 +800,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 6641d323e167ab5aad4c11fa2e7d2f70f182e4d4 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 13 Dec 2016 01:08:27 -0500 Subject: [PATCH 284/327] 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 9cb5e6f61e6..5ce84c13669 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -810,26 +810,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 [] let rev source = 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 1b7ae5a0a965f4a0d5f59f9fcd7687e6bcc5d4ca Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Tue, 13 Dec 2016 01:13:55 -0500 Subject: [PATCH 285/327] 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 5ce84c13669..249f26e4206 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 ef4ed52b93eddf2e1cf058ed97e10b7f0021732e Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 15:38:41 -0500 Subject: [PATCH 286/327] 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 249f26e4206..ef1856046a9 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 8671ebdb61e16f761bacad03d087618143051cef Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 18:20:01 -0500 Subject: [PATCH 287/327] 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 ef1856046a9..cc04cf759ae 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 a7e20184193bbc974a4085fad1043090d3c31d9a Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 18:47:18 -0500 Subject: [PATCH 288/327] inline forall2 & inline exists2 --- src/fsharp/FSharp.Core/seq.fs | 56 ++++++++------------------ src/fsharp/FSharp.Core/seqcomposer.fs | 35 +++++++++++++++- src/fsharp/FSharp.Core/seqcomposer.fsi | 6 +++ 3 files changed, 55 insertions(+), 42 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index cc04cf759ae..9af940dba41 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 @@ -735,47 +735,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 - - [] + [] 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 9bafcf31ddb170e28d261d3dbdf615557bd1a61f Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 19:27:58 -0500 Subject: [PATCH 289/327] inline fold2 --- src/fsharp/FSharp.Core/seq.fs | 21 ++++++--------------- src/fsharp/FSharp.Core/seqcomposer.fs | 18 ++++++++++++++---- src/fsharp/FSharp.Core/seqcomposer.fsi | 3 +++ 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index 9af940dba41..08634bc991e 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,23 +277,13 @@ namespace Microsoft.FSharp.Collections |> Composer.Seq.fold<'T,'State>(fun (a:'State) (b:'T) -> f.Invoke(a,b)) x - [] + [] 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 eae4f1adc1a8eb757cfe09002de2c8291dd260cf Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 19:37:46 -0500 Subject: [PATCH 290/327] 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 30c3b53148c3914595706037c31200463c96e7b8 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 19:38:40 -0500 Subject: [PATCH 291/327] 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 331c2231defd207f52e668ae81fe872806982d51 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 19:51:22 -0500 Subject: [PATCH 292/327] 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 08634bc991e..fff51490409 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 6c4b1aecccff0f1eb9640887d23793452f4a2de0 Mon Sep 17 00:00:00 2001 From: Jared Hester Date: Wed, 14 Dec 2016 20:28:25 -0500 Subject: [PATCH 293/327] 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 fff51490409..c2c3160e5e8 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)) [] let rev source = @@ -757,7 +757,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<_>) = @@ -766,7 +766,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 = @@ -785,7 +785,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 2232f4489f0db856248522419a44b1b828465bac Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 15 Dec 2016 19:17:42 +1100 Subject: [PATCH 294/327] 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 40dcf46393990c9c772a3e9aba5b685bfdb61e89 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 15 Dec 2016 19:26:22 +1100 Subject: [PATCH 295/327] 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 db456c65d38654c14da4f3bf24235551bcb82dfc Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 15 Dec 2016 19:56:06 +1100 Subject: [PATCH 296/327] 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 6c944174abeef6e41818bba9ad92ed057fecfb92 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 18 Dec 2016 08:10:18 +1100 Subject: [PATCH 297/327] 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 ab0fe0e5d5ab0dd7e97c7a12e6fe1f483df6c82e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 18 Dec 2016 09:13:07 +1100 Subject: [PATCH 298/327] 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 d3d8a373a447bb2412b3a46933ea364e68de67b5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 18 Dec 2016 14:08:50 +1100 Subject: [PATCH 299/327] 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 8649971d58f76f9dd73c74f31a51ed6792795b35 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 18 Dec 2016 14:13:56 +1100 Subject: [PATCH 300/327] 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 92253a6cfe31ef380ed7e038d1b0d8ef88fb651f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 18 Dec 2016 14:45:40 +1100 Subject: [PATCH 301/327] 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 9f91606294e81f46ca07a4967054fa1dba58349d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 18 Dec 2016 19:22:34 +1100 Subject: [PATCH 302/327] 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 7443790ef847caf96a0b434794d9893ef5580979 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sun, 18 Dec 2016 19:49:02 +1100 Subject: [PATCH 303/327] "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 98e2945b1e30ea2381e2861f84d321cc29d2980f Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 20 Dec 2016 16:31:52 +1100 Subject: [PATCH 304/327] 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 c2c3160e5e8..314e49a91de 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 5c3205f252d65abe8d2e0932ac9cd9b08419391c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 20 Dec 2016 16:43:15 +1100 Subject: [PATCH 305/327] 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 314e49a91de..f47d54e076b 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 48c6cab98dbd165edb924a3725dc0b73f838d09d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 20 Dec 2016 16:44:41 +1100 Subject: [PATCH 306/327] 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 a32ca3b6307deed25f8b1c5c23630b32c855c4ea Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 20 Dec 2016 19:36:38 +1100 Subject: [PATCH 307/327] 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 fcb845e82e76bc2223e15df11741aadbe2d73d83 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 20 Dec 2016 19:49:05 +1100 Subject: [PATCH 308/327] 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 1454a26ab130d662165e57ef053219ba65314d9a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 24 Dec 2016 14:04:13 +1100 Subject: [PATCH 309/327] 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 2269c45ffc58ecca3378a11a91453b92646c6945 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 24 Dec 2016 14:55:18 +1100 Subject: [PATCH 310/327] 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 f47d54e076b..a68172034ab 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 d2077ff23905e879a233cf419fae77909494874d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 24 Dec 2016 15:00:35 +1100 Subject: [PATCH 311/327] 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 a68172034ab..87647ef1ec9 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 [] let rev source = 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 e20ebace4c31363ac052a1e77411444491948ea0 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 24 Dec 2016 19:40:44 +1100 Subject: [PATCH 312/327] 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 9170469c1721bd9f013620c91a4a8a71ba995e6c Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Sat, 24 Dec 2016 19:45:35 +1100 Subject: [PATCH 313/327] 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 376492ed775913d4f4dac0c74249a25e9dbccd86 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 26 Dec 2016 15:42:48 +1100 Subject: [PATCH 314/327] 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 f3c2204c4ac7ec7a1a88cf9918b452f5434b339d Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Mon, 26 Dec 2016 19:26:46 +1100 Subject: [PATCH 315/327] 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 47d49cf2edafa73fdc03895e9042fadcc09b6034 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 27 Dec 2016 10:49:57 +1100 Subject: [PATCH 316/327] 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 fcfcec16f066590032880b90888c93b3ebdeba71 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 27 Dec 2016 11:09:22 +1100 Subject: [PATCH 317/327] 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 6061e30673237b81c30ccc860c512f9e0d29fae5 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 27 Dec 2016 13:34:48 +1100 Subject: [PATCH 318/327] 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 6a2fda4af605c775cec9d717dfd1a776ea0786df Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Tue, 27 Dec 2016 19:36:29 +1100 Subject: [PATCH 319/327] 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 87647ef1ec9..9555f7335e3 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 36ad648c18a0b84d565391909c19618d0d871f2e Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 28 Dec 2016 14:04:10 +1100 Subject: [PATCH 320/327] 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 84a107c4cbcd2a435107660c2b71ca0ce1ae3e0a Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 28 Dec 2016 17:05:21 +1100 Subject: [PATCH 321/327] 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 9555f7335e3..97736981ed3 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 0b193403f4cea8e7d507a8904abf18b798622605 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Wed, 28 Dec 2016 19:15:06 +1100 Subject: [PATCH 322/327] 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 97736981ed3..15bb759a058 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 = @@ -708,21 +682,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 f5461ea4fa9c4f2c9180fb011a4542421c35b36b Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Dec 2016 15:27:17 +1100 Subject: [PATCH 323/327] 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 9d35c9573cfe36bd2c8b7619668b8656525ec548 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Dec 2016 15:39:25 +1100 Subject: [PATCH 324/327] 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 15bb759a058..32b59dd2996 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)) [] @@ -703,7 +683,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 8e5ce241d568929cfd5f592c5868b232b8d431fb Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Dec 2016 16:10:11 +1100 Subject: [PATCH 325/327] 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 32b59dd2996..6c9764c81ca 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 4b8c858571123806191e0e59b985193f0ce2dabe Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Dec 2016 19:27:04 +1100 Subject: [PATCH 326/327] 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 6c9764c81ca..1204984292f 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 7831325d3de1783689c430104664c800293e6dd8 Mon Sep 17 00:00:00 2001 From: Paul Westcott Date: Thu, 29 Dec 2016 19:40:55 +1100 Subject: [PATCH 327/327] 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 1204984292f..8aba11bd9ac 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