From 16b1ac4c2a488cf10fbdd28e12fe0f7ac59b4ace Mon Sep 17 00:00:00 2001 From: liboz Date: Sat, 15 Oct 2016 00:06:36 -0400 Subject: [PATCH] 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<_>) =