From 5ec5c9658ab899eae86483439a83dda52507cbc6 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Wed, 28 Sep 2016 19:42:15 +1000
Subject: [PATCH 001/286] Basis of SeqComposer
- Removed all dynamic casting
- Split enumerable/enumerator
- Implementations of map, filter, skip, pairwise
---
src/fsharp/FSharp.Core/seq.fs | 266 ++++++++++++++++++++++++++++------
1 file changed, 223 insertions(+), 43 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index ca062b62d2a..45f7817a3ad 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -22,6 +22,215 @@ namespace Microsoft.FSharp.Collections
let check started = if not started then notStarted()
let dispose (r : System.IDisposable) = r.Dispose()
+ module SeqComposer =
+ module Helpers =
+ // used for performance reasons; these are not recursive calls, so should be safe
+ let inline avoidTailCall x =
+ match x with
+ | true -> true
+ | false -> false
+
+ type Factory =
+ static member Filter f g = Filter (fun x -> f x && g x)
+ static member Map f g = Map (f >> g)
+
+ and [] SeqComponent<'T,'U> () =
+ abstract ProcessNext : 'T * byref<'U> -> bool
+
+ abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
+
+ abstract ComposeMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeFilter : Filter<'T> -> SeqComponent<'T,'U>
+ abstract ComposeFilterMap<'S> : FilterMap<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeMapFilter<'S> : MapFilter<'S,'T> -> SeqComponent<'S,'U>
+
+ override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second)
+
+ default second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
+ default second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+
+ and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'T,'V>()
+
+ override __.ProcessNext (input:'T, output:byref<'V>) :bool =
+ let mutable temp = Unchecked.defaultof<'U>
+ if first.ProcessNext (input, &temp) then
+ Helpers.avoidTailCall (second.ProcessNext (temp, &output))
+ else
+ false
+
+ override __.Composer (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> =
+ upcast Composed (first, second.Composer next)
+
+ member __.First = first
+ member __.Second = second
+
+ and Map<'T,'U> (map:'T->'U) =
+ inherit SeqComponent<'T,'U>()
+
+ override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> =
+ second.ComposeMap first
+
+ override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> =
+ upcast Factory.Map first.Map second.Map
+
+ override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> =
+ upcast FilterMap (first, second)
+
+ override second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> =
+ upcast FilterMap (first.Filter, Factory.Map first.Map.Map second.Map)
+
+ override __.ProcessNext (input:'T, output:byref<'U>) : bool =
+ output <- map input
+ true
+
+ member __.Map :'T->'U = map
+
+ and Filter<'T> (filter:'T->bool) =
+ inherit SeqComponent<'T,'T>()
+
+ override this.Composer (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
+ next.ComposeFilter this
+
+ override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> =
+ upcast MapFilter (first, second)
+
+ override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'T> =
+ upcast Factory.Filter first.Filter second.Filter
+
+ override second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'T> =
+ upcast MapFilter(first.Map, Factory.Filter first.Filter.Filter second.Filter)
+
+ override __.ProcessNext (input:'T, output:byref<'T>) : bool =
+ if filter input then
+ output <- input
+ true
+ else
+ false
+
+ member __.Filter :'T->bool = filter
+
+ and MapFilter<'T,'U> (map:Map<'T,'U>, filter:Filter<'U>) =
+ inherit SeqComponent<'T,'U>()
+
+ override __.ProcessNext (input:'T, output:byref<'U>) :bool =
+ output <- map.Map input
+ Helpers.avoidTailCall (filter.Filter output)
+
+ override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> =
+ second.ComposeMapFilter first
+
+ member __.Map : Map<'T,'U> = map
+ member __.Filter : Filter<'U> = filter
+
+ and FilterMap<'T,'U> (filter:Filter<'T>, map:Map<'T,'U>) =
+ inherit SeqComponent<'T,'U>()
+
+ override __.ProcessNext (input:'T, output:byref<'U>) : bool =
+ if filter.Filter input then
+ output <- map.Map input
+ true
+ else
+ false
+
+ override this.Composer (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.ComposeFilterMap this
+
+ member __.Filter : Filter<'T> = filter
+ member __.Map : Map<'T,'U> = map
+
+ and Pairwise<'T> () =
+ inherit SeqComponent<'T,'T*'T>()
+
+ let mutable isFirst = true
+ let mutable lastValue = Unchecked.defaultof<'T>
+
+ override __.ProcessNext (input:'T, output:byref<'T*'T>) : bool =
+ if isFirst then
+ lastValue <- input
+ isFirst <- false
+ false
+ else
+ output <- lastValue, input
+ lastValue <- input
+ true
+
+ and Skip<'T> (skipCount:int) =
+ inherit SeqComponent<'T,'T>()
+
+ let mutable count = 0
+
+ override __.ProcessNext (input:'T, output:byref<'T>) : bool =
+ if count < skipCount then
+ count <- count + 1
+ false
+ else
+ output <- input
+ true
+
+ type SeqProcessNextStates =
+ | NotStarted = 1
+ | Finished = 2
+ | InProcess = 3
+
+ type SeqEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) =
+ let mutable source = enumerator
+ let mutable state = SeqProcessNextStates.NotStarted
+ let mutable current = Unchecked.defaultof<_>
+
+ let rec moveNext () =
+ if source.MoveNext () then
+ if t2u.ProcessNext (source.Current, ¤t) then
+ true
+ else
+ moveNext ()
+ else
+ state <- SeqProcessNextStates.Finished
+ false
+
+ interface IDisposable with
+ member x.Dispose():unit =
+ match source with
+ | null -> ()
+ | _ ->
+ source.Dispose ()
+ source <- Unchecked.defaultof<_>
+
+ interface IEnumerator with
+ member this.Current : obj = box (this:>IEnumerator<'U>).Current
+ member __.MoveNext () =
+ state <- SeqProcessNextStates.InProcess
+ moveNext ()
+ member __.Reset () : unit = noReset ()
+
+ interface IEnumerator<'U> with
+ member x.Current =
+ match state with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> ()
+ current
+
+ []
+ type SeqEnumerableBase<'T> () =
+ abstract member Compose<'U> : SeqComponent<'T,'U> -> IEnumerable<'U>
+
+ type SeqEnumerable<'T,'U>(generator:IEnumerable<'T>, t2u:SeqComponent<'T,'U>) =
+ inherit SeqEnumerableBase<'U>()
+
+ let getEnumerator () : IEnumerator<'U> =
+ upcast (new SeqEnumerator<'T,'U>(generator.GetEnumerator(), t2u))
+
+ interface IEnumerable with
+ member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
+
+ override __.Compose (u2v:SeqComponent<'U,'V>) =
+ new SeqEnumerable<'T,'V>(generator, t2u.Composer u2v) :> IEnumerable<'V>
+
let cast (e : IEnumerator) : IEnumerator<'T> =
{ new IEnumerator<'T> with
member x.Current = unbox<'T> e.Current
@@ -109,18 +318,6 @@ namespace Microsoft.FSharp.Collections
interface System.IDisposable with
member this.Dispose() = this.Dispose()
- let map f (e : IEnumerator<_>) : IEnumerator<_>=
- upcast
- { new MapEnumerator<_>() with
- member this.DoMoveNext (curr : byref<_>) =
- if e.MoveNext() then
- curr <- (f e.Current)
- true
- else
- false
- member this.Dispose() = e.Dispose()
- }
-
let mapi f (e : IEnumerator<_>) : IEnumerator<_> =
let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
let i = ref (-1)
@@ -216,23 +413,6 @@ namespace Microsoft.FSharp.Collections
interface System.IDisposable with
member x.Dispose() = e.Dispose() }
- let filter f (e : IEnumerator<'T>) =
- let started = ref false
- let this =
- { new IEnumerator<'T> with
- member x.Current = check !started; e.Current
- interface IEnumerator with
- member x.Current = check !started; box e.Current
- member x.MoveNext() =
- let rec next() =
- if not !started then started := true
- e.MoveNext() && (f e.Current || next())
- next()
- member x.Reset() = noReset()
- interface System.IDisposable with
- member x.Dispose() = e.Dispose() }
- this
-
let unfold f x : IEnumerator<_> =
let state = ref x
upcast
@@ -964,17 +1144,21 @@ namespace Microsoft.FSharp.Collections
mkSeq (fun () -> f (ie1.GetEnumerator()) (source2.GetEnumerator()) (source3.GetEnumerator()))
[]
- let filter f source =
+ let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> =
checkNonNull "source" source
- revamp (IEnumerator.filter f) source
+ match source with
+ | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Filter f)
+ | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Filter f))
[]
- let where f source = filter f source
+ let where f source = filter f source
[]
- let map f source =
+ let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> =
checkNonNull "source" source
- revamp (IEnumerator.map f) source
+ match source with
+ | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Map f)
+ | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Map f))
[]
let mapi f source =
@@ -1252,15 +1436,11 @@ namespace Microsoft.FSharp.Collections
yield ie.Current }
[]
- let pairwise (source: seq<'T>) =
- checkNonNull "source" source
- seq { use ie = source.GetEnumerator()
- if ie.MoveNext() then
- let iref = ref ie.Current
- while ie.MoveNext() do
- let j = ie.Current
- yield (!iref, j)
- iref := j }
+ let pairwise<'T> (source:seq<'T>) : seq<'T*'T> =
+ checkNonNull "source" source
+ match source with
+ | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Pairwise ())
+ | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Pairwise ()))
[]
let scan<'T,'State> f (z:'State) (source : seq<'T>) =
From c74e97f0e1647c2567651729dde6636e33c2110d Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Thu, 29 Sep 2016 16:05:23 +1000
Subject: [PATCH 002/286] Fixed output due to change in Seq.map
---
.../analyses/tailcalls.NoNeedToTailcall.output.test.bsl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl
index 5f4e677efc6..785a337a2f4 100644
--- a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl
+++ b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl
@@ -38,7 +38,7 @@ value simpleLibraryCall6 at line 60 does not make a critical tailcall
value simpleLibraryCall7 at line 61 does not make a critical tailcall
value simpleLibraryCall8 at line 62 does not make a critical tailcall
value simpleLibraryCall9 at line 63 does not make a critical tailcall
-value simpleLibraryCall10 at line 65 does not make a critical tailcall
+value simpleLibraryCall10 at line 65 may make a critical tailcall
value simpleLibraryCall11 at line 66 does not make a critical tailcall
value simpleLibraryCall12 at line 67 does not make a critical tailcall
value simpleLibraryCall13 at line 68 does not make a critical tailcall
From 515231df18a5c17f878ae92d0b0e6c02d1c3d317 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Thu, 29 Sep 2016 18:05:20 +1000
Subject: [PATCH 003/286] delayed component creation to respect mutability
- Added take, mapi
- Added same exceptions for skip & take
- Added composable skip & take
- Added array source
- Added source specific folding for functions like sum (required growing
of surface area, so currently not exposed)
---
src/fsharp/FSharp.Core/seq.fs | 644 +++++++++++++++++++++-------------
1 file changed, 405 insertions(+), 239 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 45f7817a3ad..ba17f59305e 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -15,222 +15,12 @@ namespace Microsoft.FSharp.Collections
module IEnumerator =
-
let noReset() = raise (new System.NotSupportedException(SR.GetString(SR.resetNotSupported)))
let notStarted() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationNotStarted)))
let alreadyFinished() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationAlreadyFinished)))
let check started = if not started then notStarted()
let dispose (r : System.IDisposable) = r.Dispose()
- module SeqComposer =
- module Helpers =
- // used for performance reasons; these are not recursive calls, so should be safe
- let inline avoidTailCall x =
- match x with
- | true -> true
- | false -> false
-
- type Factory =
- static member Filter f g = Filter (fun x -> f x && g x)
- static member Map f g = Map (f >> g)
-
- and [] SeqComponent<'T,'U> () =
- abstract ProcessNext : 'T * byref<'U> -> bool
-
- abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
-
- abstract ComposeMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeFilter : Filter<'T> -> SeqComponent<'T,'U>
- abstract ComposeFilterMap<'S> : FilterMap<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeMapFilter<'S> : MapFilter<'S,'T> -> SeqComponent<'S,'U>
-
- override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second)
-
- default second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
- default second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
-
- and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
-
- override __.ProcessNext (input:'T, output:byref<'V>) :bool =
- let mutable temp = Unchecked.defaultof<'U>
- if first.ProcessNext (input, &temp) then
- Helpers.avoidTailCall (second.ProcessNext (temp, &output))
- else
- false
-
- override __.Composer (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> =
- upcast Composed (first, second.Composer next)
-
- member __.First = first
- member __.Second = second
-
- and Map<'T,'U> (map:'T->'U) =
- inherit SeqComponent<'T,'U>()
-
- override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> =
- second.ComposeMap first
-
- override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> =
- upcast Factory.Map first.Map second.Map
-
- override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> =
- upcast FilterMap (first, second)
-
- override second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> =
- upcast FilterMap (first.Filter, Factory.Map first.Map.Map second.Map)
-
- override __.ProcessNext (input:'T, output:byref<'U>) : bool =
- output <- map input
- true
-
- member __.Map :'T->'U = map
-
- and Filter<'T> (filter:'T->bool) =
- inherit SeqComponent<'T,'T>()
-
- override this.Composer (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
- next.ComposeFilter this
-
- override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> =
- upcast MapFilter (first, second)
-
- override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'T> =
- upcast Factory.Filter first.Filter second.Filter
-
- override second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'T> =
- upcast MapFilter(first.Map, Factory.Filter first.Filter.Filter second.Filter)
-
- override __.ProcessNext (input:'T, output:byref<'T>) : bool =
- if filter input then
- output <- input
- true
- else
- false
-
- member __.Filter :'T->bool = filter
-
- and MapFilter<'T,'U> (map:Map<'T,'U>, filter:Filter<'U>) =
- inherit SeqComponent<'T,'U>()
-
- override __.ProcessNext (input:'T, output:byref<'U>) :bool =
- output <- map.Map input
- Helpers.avoidTailCall (filter.Filter output)
-
- override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> =
- second.ComposeMapFilter first
-
- member __.Map : Map<'T,'U> = map
- member __.Filter : Filter<'U> = filter
-
- and FilterMap<'T,'U> (filter:Filter<'T>, map:Map<'T,'U>) =
- inherit SeqComponent<'T,'U>()
-
- override __.ProcessNext (input:'T, output:byref<'U>) : bool =
- if filter.Filter input then
- output <- map.Map input
- true
- else
- false
-
- override this.Composer (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.ComposeFilterMap this
-
- member __.Filter : Filter<'T> = filter
- member __.Map : Map<'T,'U> = map
-
- and Pairwise<'T> () =
- inherit SeqComponent<'T,'T*'T>()
-
- let mutable isFirst = true
- let mutable lastValue = Unchecked.defaultof<'T>
-
- override __.ProcessNext (input:'T, output:byref<'T*'T>) : bool =
- if isFirst then
- lastValue <- input
- isFirst <- false
- false
- else
- output <- lastValue, input
- lastValue <- input
- true
-
- and Skip<'T> (skipCount:int) =
- inherit SeqComponent<'T,'T>()
-
- let mutable count = 0
-
- override __.ProcessNext (input:'T, output:byref<'T>) : bool =
- if count < skipCount then
- count <- count + 1
- false
- else
- output <- input
- true
-
- type SeqProcessNextStates =
- | NotStarted = 1
- | Finished = 2
- | InProcess = 3
-
- type SeqEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) =
- let mutable source = enumerator
- let mutable state = SeqProcessNextStates.NotStarted
- let mutable current = Unchecked.defaultof<_>
-
- let rec moveNext () =
- if source.MoveNext () then
- if t2u.ProcessNext (source.Current, ¤t) then
- true
- else
- moveNext ()
- else
- state <- SeqProcessNextStates.Finished
- false
-
- interface IDisposable with
- member x.Dispose():unit =
- match source with
- | null -> ()
- | _ ->
- source.Dispose ()
- source <- Unchecked.defaultof<_>
-
- interface IEnumerator with
- member this.Current : obj = box (this:>IEnumerator<'U>).Current
- member __.MoveNext () =
- state <- SeqProcessNextStates.InProcess
- moveNext ()
- member __.Reset () : unit = noReset ()
-
- interface IEnumerator<'U> with
- member x.Current =
- match state with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> ()
- current
-
- []
- type SeqEnumerableBase<'T> () =
- abstract member Compose<'U> : SeqComponent<'T,'U> -> IEnumerable<'U>
-
- type SeqEnumerable<'T,'U>(generator:IEnumerable<'T>, t2u:SeqComponent<'T,'U>) =
- inherit SeqEnumerableBase<'U>()
-
- let getEnumerator () : IEnumerator<'U> =
- upcast (new SeqEnumerator<'T,'U>(generator.GetEnumerator(), t2u))
-
- interface IEnumerable with
- member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
-
- interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
-
- override __.Compose (u2v:SeqComponent<'U,'V>) =
- new SeqEnumerable<'T,'V>(generator, t2u.Composer u2v) :> IEnumerable<'V>
-
let cast (e : IEnumerator) : IEnumerator<'T> =
{ new IEnumerator<'T> with
member x.Current = unbox<'T> e.Current
@@ -1023,6 +813,395 @@ namespace Microsoft.FSharp.Collections
[]
[]
module Seq =
+ type ISeqEnumerable<'T> =
+ abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State
+
+ module SeqComposer =
+ open IEnumerator
+
+ module Helpers =
+ // used for performance reasons; these are not recursive calls, so should be safe
+ let inline avoidTailCall x =
+ match x with
+ | true -> true
+ | false -> false
+
+ let inline ComposeFilter f g x = f x && g x
+
+ type [] SeqComponent<'T,'U> () =
+ abstract ProcessNext : input:'T * halt:byref * output:byref<'U> -> bool
+ abstract OnComplete : unit -> unit
+
+ abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
+
+ abstract ComposeMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeFilter : Filter<'T> -> SeqComponent<'T,'U>
+ abstract ComposeFilterMap<'S> : FilterMap<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeMapFilter<'S> : MapFilter<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeSkip : Skip<'T> -> SeqComponent<'T,'U>
+
+ default __.OnComplete () = ()
+
+ default first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second)
+
+ default second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
+ default second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
+
+ and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'T,'V>()
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) :bool =
+ let mutable temp = Unchecked.defaultof<'U>
+ if first.ProcessNext (input, &halted, &temp) && not halted then
+ second.ProcessNext (temp, &halted, &output)
+ else
+ false
+
+ override __.Composer (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> =
+ upcast Composed (first, second.Composer next)
+
+ override __.OnComplete () =
+ first.OnComplete ()
+ second.OnComplete ()
+
+ and Map<'T,'U> (map:'T->'U) =
+ inherit SeqComponent<'T,'U>()
+
+ override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> =
+ second.ComposeMap first
+
+ override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> =
+ upcast Map (first.Map >> second.Map)
+
+ override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> =
+ upcast FilterMap (first.Filter, second.Map)
+
+ override second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> =
+ upcast FilterMap (first.Filter, first.Map >> second.Map)
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
+ output <- map input
+ true
+
+ member __.Map : 'T->'U = map
+
+ and Mapi<'T,'U> (mapi:int->'T->'U) =
+ inherit SeqComponent<'T,'U>()
+
+ let mutable idx = 0
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
+ output <- mapi idx input
+ idx <- idx + 1
+ true
+
+ member __.Mapi : int->'T->'U = mapi
+
+ and Filter<'T> (filter:'T->bool) =
+ inherit SeqComponent<'T,'T>()
+
+ override this.Composer (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
+ next.ComposeFilter this
+
+ override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> =
+ upcast MapFilter (first.Map, second.Filter)
+
+ override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'T> =
+ upcast Filter (Helpers.ComposeFilter first.Filter second.Filter)
+
+ override second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'T> =
+ upcast MapFilter (first.Map, Helpers.ComposeFilter first.Filter second.Filter)
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ if filter input then
+ output <- input
+ true
+ else
+ false
+
+ member __.Filter :'T->bool = filter
+
+ and MapFilter<'T,'U> (map:'T->'U, filter:'U->bool) =
+ inherit SeqComponent<'T,'U>()
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) :bool =
+ output <- map input
+ Helpers.avoidTailCall (filter output)
+
+ override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> =
+ second.ComposeMapFilter first
+
+ member __.Map : 'T->'U = map
+ member __.Filter : 'U->bool = filter
+
+ and FilterMap<'T,'U> (filter:'T->bool, map:'T->'U) =
+ inherit SeqComponent<'T,'U>()
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
+ if filter input then
+ output <- map input
+ true
+ else
+ false
+
+ override this.Composer (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.ComposeFilterMap this
+
+ member __.Filter : 'T->bool = filter
+ member __.Map : 'T->'U = map
+
+ and Pairwise<'T> () =
+ inherit SeqComponent<'T,'T*'T>()
+
+ let mutable isFirst = true
+ let mutable lastValue = Unchecked.defaultof<'T>
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T*'T>) : bool =
+ if isFirst then
+ lastValue <- input
+ isFirst <- false
+ false
+ else
+ output <- lastValue, input
+ lastValue <- input
+ true
+
+ and Skip<'T> (skipCount:int) =
+ inherit SeqComponent<'T,'T>()
+
+ let mutable count = 0
+
+ override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
+ second.ComposeSkip first
+
+ override second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
+ if System.Int32.MaxValue - second.SkipCount > first.SkipCount then
+ upcast Skip (first.SkipCount + second.SkipCount)
+ else
+ upcast Composed (first, second)
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ if count < skipCount then
+ count <- count + 1
+ false
+ else
+ output <- input
+ true
+
+ override __.OnComplete () =
+ if count < skipCount then
+ let x = skipCount - count
+ invalidOpFmt "tried to skip {0} {1} past the end of the seq"
+ [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+
+ member __.SkipCount = skipCount
+
+ and Take<'T> (takeCount:int) =
+ inherit SeqComponent<'T,'T>()
+
+ let mutable count = 0
+
+ override second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
+ if System.Int32.MaxValue - second.TakeCount > first.SkipCount then
+ upcast SkipTake (first.SkipCount, first.SkipCount+second.TakeCount)
+ else
+ upcast Composed (first, second)
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ if count < takeCount then
+ count <- count + 1
+ output <- input
+ true
+ else
+ halted <- true
+ false
+
+ override __.OnComplete () =
+ if count < takeCount then
+ let x = takeCount - count
+ invalidOpFmt "tried to take {0} {1} past the end of the seq"
+ [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+
+ member __.TakeCount = takeCount
+
+ and SkipTake<'T> (startIdx:int, endIdx:int) =
+ inherit SeqComponent<'T,'T>()
+
+ let mutable count = 0
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ if count < startIdx then
+ count <- count + 1
+ false
+ elif count < endIdx then
+ count <- count + 1
+ output <- input
+ true
+ else
+ halted <- true
+ false
+
+ override __.OnComplete () =
+ if count < startIdx then
+ let x = startIdx - count
+ invalidOpFmt "tried to skip {0} {1} past the end of the seq"
+ [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+ elif count < endIdx then
+ let x = endIdx - count
+ invalidOpFmt "tried to take {0} {1} past the end of the seq"
+ [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+
+ type SeqProcessNextStates =
+ | NotStarted = 1
+ | Finished = 2
+ | InProcess = 3
+
+ type SeqEnumeratorEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) =
+ let mutable state = SeqProcessNextStates.NotStarted
+ let mutable current = Unchecked.defaultof<'U>
+ let mutable halted = false
+
+ let mutable source = enumerator
+
+ let rec moveNext () =
+ if (not halted) && source.MoveNext () then
+ if t2u.ProcessNext (source.Current, &halted, ¤t) then
+ true
+ else
+ moveNext ()
+ else
+ state <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IDisposable with
+ member x.Dispose():unit =
+ match source with
+ | null -> ()
+ | _ -> source.Dispose (); source <- Unchecked.defaultof<_>
+
+ interface IEnumerator with
+ member this.Current : obj = box (this:>IEnumerator<'U>).Current
+ member __.MoveNext () =
+ state <- SeqProcessNextStates.InProcess
+ moveNext ()
+ member __.Reset () : unit = noReset ()
+
+ interface IEnumerator<'U> with
+ member x.Current =
+ match state with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> ()
+ current
+
+ type SeqArrayEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) =
+ let mutable state = SeqProcessNextStates.NotStarted
+ let mutable current = Unchecked.defaultof<'U>
+ let mutable halted = false
+
+ let mutable idx = 0
+
+ let rec moveNext () =
+ if (not halted) && idx < array.Length then
+ idx <- idx+1
+ if t2u.ProcessNext (array.[idx-1], &halted, ¤t) then
+ true
+ else
+ moveNext ()
+ else
+ state <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IDisposable with
+ member x.Dispose() : unit = ()
+
+ interface IEnumerator with
+ member this.Current : obj = box (this:>IEnumerator<'U>).Current
+ member __.MoveNext () =
+ state <- SeqProcessNextStates.InProcess
+ moveNext ()
+ member __.Reset () : unit = noReset ()
+
+ interface IEnumerator<'U> with
+ member x.Current =
+ match state with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> ()
+ current
+
+ []
+ type ComposableEnumerable<'T> () =
+ abstract member Compose<'U> : (unit -> SeqComponent<'T,'U>) -> IEnumerable<'U>
+
+ type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:unit->SeqComponent<'T,'U>) =
+ inherit ComposableEnumerable<'U>()
+
+ let getEnumerator () : IEnumerator<'U> =
+ upcast (new SeqEnumeratorEnumerator<'T,'U>(enumerable.GetEnumerator(), current ()))
+
+ interface IEnumerable with
+ member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
+
+ override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
+ upcast new SeqEnumerable<'T,'V>(enumerable, fun () -> (current ()).Composer (next ()))
+
+ interface ISeqEnumerable<'U> with
+ member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let enumerator = enumerable.GetEnumerator ()
+ let components = current ()
+ let mutable output = Unchecked.defaultof<'U>
+ let mutable halt = false
+
+ let mutable state = initialState
+ while (not halt) && enumerator.MoveNext () do
+ if components.ProcessNext (enumerator.Current, &halt, &output) then
+ state <- folder'.Invoke (state, output)
+
+ state
+
+ type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:unit->SeqComponent<'T,'U>) =
+ inherit ComposableEnumerable<'U>()
+
+ let getEnumerator () : IEnumerator<'U> =
+ upcast (new SeqArrayEnumerator<'T,'U>(array, current ()))
+
+ interface IEnumerable with
+ member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
+
+ override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
+ upcast new SeqArrayEnumerable<'T,'V>(array, fun () -> (current ()).Composer (next ()))
+
+ interface ISeqEnumerable<'U> with
+ member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let mutable idx = 0
+ let components = current ()
+ let mutable current = Unchecked.defaultof<'U>
+ let mutable halt = false
+
+ let mutable state = initialState
+ while (not halt) && idx < array.Length do
+ if components.ProcessNext (array.[idx], &halt, ¤t) then
+ state <- folder'.Invoke(state, current)
+ idx <- idx + 1
+
+ state
+
+
#if FX_NO_ICLONEABLE
open Microsoft.FSharp.Core.ICloneableExtensions
@@ -1143,27 +1322,30 @@ namespace Microsoft.FSharp.Collections
let revamp3 f (ie1 : seq<_>) (source2 : seq<_>) (source3 : seq<_>) =
mkSeq (fun () -> f (ie1.GetEnumerator()) (source2.GetEnumerator()) (source3.GetEnumerator()))
- []
- let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> =
+ let private seqFactory createSeqComponent (source:seq<'T>) =
checkNonNull "source" source
match source with
- | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Filter f)
- | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Filter f))
+ | :? SeqComposer.ComposableEnumerable<'T> as s -> s.Compose createSeqComponent
+ | :? array<'T> as a -> upcast (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent))
+ | _ -> upcast (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent))
+
+ let private seqFactoryForImmutable seqComponent (source:seq<'T>) =
+ source |> seqFactory (fun () -> seqComponent)
+
+ []
+ let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> =
+ source |> seqFactoryForImmutable (SeqComposer.Filter f)
[]
let where f source = filter f source
[]
let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> =
- checkNonNull "source" source
- match source with
- | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Map f)
- | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Map f))
+ source |> seqFactoryForImmutable (SeqComposer.Map f)
[]
let mapi f source =
- checkNonNull "source" source
- revamp (IEnumerator.mapi f) source
+ source |> seqFactory (fun () -> upcast SeqComposer.Mapi f)
[]
let mapi2 f source1 source2 =
@@ -1247,16 +1429,10 @@ namespace Microsoft.FSharp.Collections
[]
let take count (source : seq<'T>) =
- checkNonNull "source" source
if count < 0 then invalidArgInputMustBeNonNegative "count" count
(* Note: don't create or dispose any IEnumerable if n = 0 *)
if count = 0 then empty else
- seq { use e = source.GetEnumerator()
- for x in 0 .. count - 1 do
- if not (e.MoveNext()) then
- invalidOpFmt "tried to take {0} {1} past the end of the seq"
- [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- yield e.Current }
+ source |> seqFactory (fun () -> upcast SeqComposer.Take count)
[]
let isEmpty (source : seq<'T>) =
@@ -1437,10 +1613,7 @@ namespace Microsoft.FSharp.Collections
[]
let pairwise<'T> (source:seq<'T>) : seq<'T*'T> =
- checkNonNull "source" source
- match source with
- | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Pairwise ())
- | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Pairwise ()))
+ source |> seqFactory (fun () -> upcast SeqComposer.Pairwise ())
[]
let scan<'T,'State> f (z:'State) (source : seq<'T>) =
@@ -1878,14 +2051,7 @@ namespace Microsoft.FSharp.Collections
[]
let skip count (source: seq<_>) =
- checkNonNull "source" source
- seq { use e = source.GetEnumerator()
- for x in 1 .. count do
- if not (e.MoveNext()) then
- invalidOpFmt "tried to skip {0} {1} past the end of the seq"
- [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- while e.MoveNext() do
- yield e.Current }
+ source |> seqFactory (fun () -> upcast SeqComposer.Skip count)
[]
let skipWhile p (source: seq<_>) =
From ce6b12621fc2b2fa831b8542f47b7d8db87284ba Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Thu, 29 Sep 2016 18:49:22 +1000
Subject: [PATCH 004/286] Temporarily remove the ISeqEnumerable interface
It was causing build issues as it was currently unused.
---
src/fsharp/FSharp.Core/seq.fs | 66 +++++++++++++++++------------------
1 file changed, 33 insertions(+), 33 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index ba17f59305e..1c1d7a089a2 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -813,8 +813,8 @@ namespace Microsoft.FSharp.Collections
[]
[]
module Seq =
- type ISeqEnumerable<'T> =
- abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State
+// type ISeqEnumerable<'T> =
+// abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State
module SeqComposer =
open IEnumerator
@@ -1153,21 +1153,21 @@ namespace Microsoft.FSharp.Collections
override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
upcast new SeqEnumerable<'T,'V>(enumerable, fun () -> (current ()).Composer (next ()))
- interface ISeqEnumerable<'U> with
- member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
- let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
-
- let enumerator = enumerable.GetEnumerator ()
- let components = current ()
- let mutable output = Unchecked.defaultof<'U>
- let mutable halt = false
-
- let mutable state = initialState
- while (not halt) && enumerator.MoveNext () do
- if components.ProcessNext (enumerator.Current, &halt, &output) then
- state <- folder'.Invoke (state, output)
-
- state
+// interface ISeqEnumerable<'U> with
+// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+//
+// let enumerator = enumerable.GetEnumerator ()
+// let components = current ()
+// let mutable output = Unchecked.defaultof<'U>
+// let mutable halt = false
+//
+// let mutable state = initialState
+// while (not halt) && enumerator.MoveNext () do
+// if components.ProcessNext (enumerator.Current, &halt, &output) then
+// state <- folder'.Invoke (state, output)
+//
+// state
type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:unit->SeqComponent<'T,'U>) =
inherit ComposableEnumerable<'U>()
@@ -1184,22 +1184,22 @@ namespace Microsoft.FSharp.Collections
override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
upcast new SeqArrayEnumerable<'T,'V>(array, fun () -> (current ()).Composer (next ()))
- interface ISeqEnumerable<'U> with
- member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
- let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
-
- let mutable idx = 0
- let components = current ()
- let mutable current = Unchecked.defaultof<'U>
- let mutable halt = false
-
- let mutable state = initialState
- while (not halt) && idx < array.Length do
- if components.ProcessNext (array.[idx], &halt, ¤t) then
- state <- folder'.Invoke(state, current)
- idx <- idx + 1
-
- state
+// interface ISeqEnumerable<'U> with
+// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+//
+// let mutable idx = 0
+// let components = current ()
+// let mutable current = Unchecked.defaultof<'U>
+// let mutable halt = false
+//
+// let mutable state = initialState
+// while (not halt) && idx < array.Length do
+// if components.ProcessNext (array.[idx], &halt, ¤t) then
+// state <- folder'.Invoke(state, current)
+// idx <- idx + 1
+//
+// state
From 118ca3d19b2465addff0c7cab30b60c0fec5bccc Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Thu, 29 Sep 2016 19:59:49 +1000
Subject: [PATCH 005/286] Fixing halting on take
---
src/fsharp/FSharp.Core/seq.fs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 1c1d7a089a2..5f4b34ceb26 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -855,7 +855,7 @@ namespace Microsoft.FSharp.Collections
override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) :bool =
let mutable temp = Unchecked.defaultof<'U>
- if first.ProcessNext (input, &halted, &temp) && not halted then
+ if first.ProcessNext (input, &halted, &temp) then
second.ProcessNext (temp, &halted, &output)
else
false
@@ -1013,6 +1013,7 @@ namespace Microsoft.FSharp.Collections
if count < takeCount then
count <- count + 1
output <- input
+ halted <- count = takeCount
true
else
halted <- true
@@ -1038,6 +1039,7 @@ namespace Microsoft.FSharp.Collections
elif count < endIdx then
count <- count + 1
output <- input
+ halted <- count = endIdx
true
else
halted <- true
From e2a5ae4d619a90bd097c21324a8c327dd3148c29 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 2 Oct 2016 18:26:16 +1100
Subject: [PATCH 006/286] Return current as match of match statement for perf
*slight* performance improvement
---
src/fsharp/FSharp.Core/seq.fs | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 5f4b34ceb26..afff06239bb 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1096,8 +1096,7 @@ namespace Microsoft.FSharp.Collections
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> ()
- current
+ | _ -> current
type SeqArrayEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) =
let mutable state = SeqProcessNextStates.NotStarted
@@ -1133,8 +1132,7 @@ namespace Microsoft.FSharp.Collections
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> ()
- current
+ | _ -> current
[]
type ComposableEnumerable<'T> () =
From 7fce803a777823d48ef634622e101dc18127c525 Mon Sep 17 00:00:00 2001
From: liboz
Date: Mon, 3 Oct 2016 16:34:00 -0400
Subject: [PATCH 007/286] renaming cleanup. Adding ListEnumerable. Adding
Choose
---
src/fsharp/FSharp.Core/seq.fs | 149 ++++++++++++++++++++++++----------
1 file changed, 104 insertions(+), 45 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index afff06239bb..58f034d1914 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -834,21 +834,21 @@ namespace Microsoft.FSharp.Collections
abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
- abstract ComposeMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeFilter : Filter<'T> -> SeqComponent<'T,'U>
- abstract ComposeFilterMap<'S> : FilterMap<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeMapFilter<'S> : MapFilter<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeSkip : Skip<'T> -> SeqComponent<'T,'U>
+ abstract ComposeWithMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeWithFilter : Filter<'T> -> SeqComponent<'T,'U>
+ abstract ComposeWithFilterThenMap<'S> : FilterThenMap<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeWithMapThenFilter<'S> : MapThenFilter<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeWithSkip : Skip<'T> -> SeqComponent<'T,'U>
default __.OnComplete () = ()
- default first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second)
+ default first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second)
- default second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
- default second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
+ default second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
+ default second.ComposeWithFilterThenMap<'S> (first:FilterThenMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeWithMapThenFilter<'S> (first:MapThenFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>()
@@ -871,16 +871,16 @@ namespace Microsoft.FSharp.Collections
inherit SeqComponent<'T,'U>()
override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> =
- second.ComposeMap first
+ second.ComposeWithMap first
- override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> =
+ override second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> =
upcast Map (first.Map >> second.Map)
- override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> =
- upcast FilterMap (first.Filter, second.Map)
+ override second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'U> =
+ upcast FilterThenMap (first.Filter, second.Map)
- override second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> =
- upcast FilterMap (first.Filter, first.Map >> second.Map)
+ override second.ComposeWithFilterThenMap<'S> (first:FilterThenMap<'S,'T>) : SeqComponent<'S,'U> =
+ upcast FilterThenMap (first.Filter, first.Map >> second.Map)
override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
output <- map input
@@ -903,17 +903,17 @@ namespace Microsoft.FSharp.Collections
and Filter<'T> (filter:'T->bool) =
inherit SeqComponent<'T,'T>()
- override this.Composer (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
- next.ComposeFilter this
+ override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
+ second.ComposeWithFilter first
- override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> =
- upcast MapFilter (first.Map, second.Filter)
+ override second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> =
+ upcast MapThenFilter (first.Map, second.Filter)
- override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'T> =
+ override second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'T> =
upcast Filter (Helpers.ComposeFilter first.Filter second.Filter)
- override second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'T> =
- upcast MapFilter (first.Map, Helpers.ComposeFilter first.Filter second.Filter)
+ override second.ComposeWithMapThenFilter<'S> (first:MapThenFilter<'S,'T>) : SeqComponent<'S,'T> =
+ upcast MapThenFilter (first.Map, Helpers.ComposeFilter first.Filter second.Filter)
override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
if filter input then
@@ -924,7 +924,7 @@ namespace Microsoft.FSharp.Collections
member __.Filter :'T->bool = filter
- and MapFilter<'T,'U> (map:'T->'U, filter:'U->bool) =
+ and MapThenFilter<'T,'U> (map:'T->'U, filter:'U->bool) =
inherit SeqComponent<'T,'U>()
override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) :bool =
@@ -932,12 +932,12 @@ namespace Microsoft.FSharp.Collections
Helpers.avoidTailCall (filter output)
override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> =
- second.ComposeMapFilter first
+ second.ComposeWithMapThenFilter first
member __.Map : 'T->'U = map
member __.Filter : 'U->bool = filter
- and FilterMap<'T,'U> (filter:'T->bool, map:'T->'U) =
+ and FilterThenMap<'T,'U> (filter:'T->bool, map:'T->'U) =
inherit SeqComponent<'T,'U>()
override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
@@ -947,7 +947,7 @@ namespace Microsoft.FSharp.Collections
else
false
- override this.Composer (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.ComposeFilterMap this
+ override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = second.ComposeWithFilterThenMap first
member __.Filter : 'T->bool = filter
member __.Map : 'T->'U = map
@@ -974,10 +974,10 @@ namespace Microsoft.FSharp.Collections
let mutable count = 0
override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
- second.ComposeSkip first
+ second.ComposeWithSkip first
- override second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
- if System.Int32.MaxValue - second.SkipCount > first.SkipCount then
+ override second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
+ if Int32.MaxValue - first.SkipCount - second.SkipCount > 0 then
upcast Skip (first.SkipCount + second.SkipCount)
else
upcast Composed (first, second)
@@ -1003,9 +1003,9 @@ namespace Microsoft.FSharp.Collections
let mutable count = 0
- override second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
- if System.Int32.MaxValue - second.TakeCount > first.SkipCount then
- upcast SkipTake (first.SkipCount, first.SkipCount+second.TakeCount)
+ override second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
+ if Int32.MaxValue - first.SkipCount - second.TakeCount > 0 then
+ upcast SkipThenTake (first.SkipCount, first.SkipCount+second.TakeCount)
else
upcast Composed (first, second)
@@ -1027,7 +1027,7 @@ namespace Microsoft.FSharp.Collections
member __.TakeCount = takeCount
- and SkipTake<'T> (startIdx:int, endIdx:int) =
+ and SkipThenTake<'T> (startIdx:int, endIdx:int) =
inherit SeqComponent<'T,'T>()
let mutable count = 0
@@ -1054,13 +1054,22 @@ namespace Microsoft.FSharp.Collections
let x = endIdx - count
invalidOpFmt "tried to take {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+
+ and Choose<'T, 'U> (choose:'T->'U option) =
+ inherit SeqComponent<'T,'U>()
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
+ match choose input with
+ | Some value -> output <- value
+ true
+ | None -> false
type SeqProcessNextStates =
| NotStarted = 1
| Finished = 2
| InProcess = 3
- type SeqEnumeratorEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) =
+ type SeqComposedEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) =
let mutable state = SeqProcessNextStates.NotStarted
let mutable current = Unchecked.defaultof<'U>
let mutable halted = false
@@ -1079,7 +1088,7 @@ namespace Microsoft.FSharp.Collections
false
interface IDisposable with
- member x.Dispose():unit =
+ member __.Dispose():unit =
match source with
| null -> ()
| _ -> source.Dispose (); source <- Unchecked.defaultof<_>
@@ -1092,13 +1101,13 @@ namespace Microsoft.FSharp.Collections
member __.Reset () : unit = noReset ()
interface IEnumerator<'U> with
- member x.Current =
+ member __.Current =
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
| _ -> current
- type SeqArrayEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) =
+ type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) =
let mutable state = SeqProcessNextStates.NotStarted
let mutable current = Unchecked.defaultof<'U>
let mutable halted = false
@@ -1118,7 +1127,7 @@ namespace Microsoft.FSharp.Collections
false
interface IDisposable with
- member x.Dispose() : unit = ()
+ member __.Dispose() : unit = ()
interface IEnumerator with
member this.Current : obj = box (this:>IEnumerator<'U>).Current
@@ -1128,7 +1137,43 @@ namespace Microsoft.FSharp.Collections
member __.Reset () : unit = noReset ()
interface IEnumerator<'U> with
- member x.Current =
+ member __.Current =
+ match state with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> current
+
+ type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>) =
+ let mutable state = SeqProcessNextStates.NotStarted
+ let mutable current = Unchecked.defaultof<'U>
+ let mutable halted = false
+
+ let mutable list = alist
+
+ let rec moveNext () =
+ match halted, list with
+ | false, head::tail ->
+ list <- tail
+ if t2u.ProcessNext (head, &halted, ¤t) then
+ true
+ else
+ moveNext ()
+ | _ -> state <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IDisposable with
+ member __.Dispose() : unit = ()
+
+ interface IEnumerator with
+ member this.Current : obj = box (this:>IEnumerator<'U>).Current
+ member __.MoveNext () =
+ state <- SeqProcessNextStates.InProcess
+ moveNext ()
+ member __.Reset () : unit = noReset ()
+
+ interface IEnumerator<'U> with
+ member __.Current =
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
@@ -1142,7 +1187,7 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- upcast (new SeqEnumeratorEnumerator<'T,'U>(enumerable.GetEnumerator(), current ()))
+ upcast (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current ()))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
@@ -1173,7 +1218,7 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- upcast (new SeqArrayEnumerator<'T,'U>(array, current ()))
+ upcast (new ArrayComposedEnumerator<'T,'U>(array, current ()))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
@@ -1201,6 +1246,20 @@ namespace Microsoft.FSharp.Collections
//
// state
+ type SeqListEnumerable<'T,'U>(alist:list<'T>, current:unit->SeqComponent<'T,'U>) =
+ inherit ComposableEnumerable<'U>()
+
+ let getEnumerator () : IEnumerator<'U> =
+ upcast (new ListComposedEnumerator<'T,'U>(alist, current ()))
+
+ interface IEnumerable with
+ member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
+
+ override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
+ upcast new SeqListEnumerable<'T,'V>(alist, fun () -> (current ()).Composer (next ()))
#if FX_NO_ICLONEABLE
@@ -1327,6 +1386,7 @@ namespace Microsoft.FSharp.Collections
match source with
| :? SeqComposer.ComposableEnumerable<'T> as s -> s.Compose createSeqComponent
| :? array<'T> as a -> upcast (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent))
+ | :? list<'T> as a -> upcast (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent))
| _ -> upcast (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent))
let private seqFactoryForImmutable seqComponent (source:seq<'T>) =
@@ -1368,8 +1428,7 @@ namespace Microsoft.FSharp.Collections
[]
let choose f source =
- checkNonNull "source" source
- revamp (IEnumerator.choose f) source
+ source |> seqFactoryForImmutable (SeqComposer.Choose f)
[]
let indexed source =
From e5bf10a3f37e5abd401f4fd69202ff30a86ca0dc Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Tue, 4 Oct 2016 20:00:31 +1100
Subject: [PATCH 008/286] Remove unbox.any when upcasting to IEnumer(able|ator)
Thanks to @liboz for reminding me of the performance hit here. This is
noticeable when you have small collections to be iterated.
---
src/fsharp/FSharp.Core/seq.fs | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 58f034d1914..6895051cda0 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -828,6 +828,10 @@ namespace Microsoft.FSharp.Collections
let inline ComposeFilter f g x = f x && g x
+ let inline UpcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #)
+ let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #)
+ let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #)
+
type [] SeqComponent<'T,'U> () =
abstract ProcessNext : input:'T * halt:byref * output:byref<'U> -> bool
abstract OnComplete : unit -> unit
@@ -1094,7 +1098,7 @@ namespace Microsoft.FSharp.Collections
| _ -> source.Dispose (); source <- Unchecked.defaultof<_>
interface IEnumerator with
- member this.Current : obj = box (this:>IEnumerator<'U>).Current
+ member this.Current : obj = box (Helpers.UpcastEnumerator this).Current
member __.MoveNext () =
state <- SeqProcessNextStates.InProcess
moveNext ()
@@ -1130,7 +1134,7 @@ namespace Microsoft.FSharp.Collections
member __.Dispose() : unit = ()
interface IEnumerator with
- member this.Current : obj = box (this:>IEnumerator<'U>).Current
+ member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current
member __.MoveNext () =
state <- SeqProcessNextStates.InProcess
moveNext ()
@@ -1187,16 +1191,16 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- upcast (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current ()))
+ Helpers.UpcastEnumerator (new SeqEnumeratorEnumerator<'T,'U>(enumerable.GetEnumerator(), current ()))
interface IEnumerable with
- member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
+ member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
- upcast new SeqEnumerable<'T,'V>(enumerable, fun () -> (current ()).Composer (next ()))
+ Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, fun () -> (current ()).Composer (next ())))
// interface ISeqEnumerable<'U> with
// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
@@ -1218,16 +1222,16 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- upcast (new ArrayComposedEnumerator<'T,'U>(array, current ()))
+ Helpers.UpcastEnumerator (new SeqArrayEnumerator<'T,'U>(array, current ()))
interface IEnumerable with
- member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
+ member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
- upcast new SeqArrayEnumerable<'T,'V>(array, fun () -> (current ()).Composer (next ()))
+ Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, fun () -> (current ()).Composer (next ())))
// interface ISeqEnumerable<'U> with
// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
@@ -1385,9 +1389,9 @@ namespace Microsoft.FSharp.Collections
checkNonNull "source" source
match source with
| :? SeqComposer.ComposableEnumerable<'T> as s -> s.Compose createSeqComponent
- | :? array<'T> as a -> upcast (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent))
- | :? list<'T> as a -> upcast (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent))
- | _ -> upcast (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent))
+ | :? array<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent))
+ | :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent))
+ | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent))
let private seqFactoryForImmutable seqComponent (source:seq<'T>) =
source |> seqFactory (fun () -> seqComponent)
From 113c5903396066d121f353de09f906799a504574 Mon Sep 17 00:00:00 2001
From: liboz
Date: Tue, 4 Oct 2016 22:13:24 -0400
Subject: [PATCH 009/286] remove old mapi function
---
src/fsharp/FSharp.Core/seq.fs | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 6895051cda0..5ca6b376d72 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -108,21 +108,6 @@ namespace Microsoft.FSharp.Collections
interface System.IDisposable with
member this.Dispose() = this.Dispose()
- let mapi f (e : IEnumerator<_>) : IEnumerator<_> =
- let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
- let i = ref (-1)
- upcast
- { new MapEnumerator<_>() with
- member this.DoMoveNext curr =
- i := !i + 1
- if e.MoveNext() then
- curr <- f.Invoke(!i, e.Current)
- true
- else
- false
- member this.Dispose() = e.Dispose()
- }
-
let map2 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) : IEnumerator<_>=
let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
upcast
From dd80725e539142567428d2f001a7697496970562 Mon Sep 17 00:00:00 2001
From: liboz
Date: Wed, 5 Oct 2016 10:09:17 -0400
Subject: [PATCH 010/286] skipwhile/takewhile
---
src/fsharp/FSharp.Core/seq.fs | 46 +++++++++++++++++++++++------------
1 file changed, 31 insertions(+), 15 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 5ca6b376d72..12533201ea2 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1043,7 +1043,35 @@ namespace Microsoft.FSharp.Collections
let x = endIdx - count
invalidOpFmt "tried to take {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
-
+
+ and SkipWhile<'T> (predicate: 'T -> bool) =
+ inherit SeqComponent<'T,'T>()
+
+ let mutable skip = true
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ if skip then
+ skip <- predicate input
+ if skip then
+ false
+ else
+ output <- input
+ true
+ else
+ output <- input
+ true
+
+ and TakeWhile<'T> (predicate: 'T -> bool) =
+ inherit SeqComponent<'T,'T>()
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ if predicate input then
+ output <- input
+ true
+ else
+ halted <- true
+ false
+
and Choose<'T, 'U> (choose:'T->'U option) =
inherit SeqComponent<'T,'U>()
@@ -2091,11 +2119,7 @@ namespace Microsoft.FSharp.Collections
*)
[]
let takeWhile p (source: seq<_>) =
- checkNonNull "source" source
- seq { use e = source.GetEnumerator()
- let latest = ref Unchecked.defaultof<_>
- while e.MoveNext() && (latest := e.Current; p !latest) do
- yield !latest }
+ source |> seqFactory (fun () -> upcast SeqComposer.TakeWhile p)
[]
let skip count (source: seq<_>) =
@@ -2103,15 +2127,7 @@ namespace Microsoft.FSharp.Collections
[]
let skipWhile p (source: seq<_>) =
- checkNonNull "source" source
- seq { use e = source.GetEnumerator()
- let latest = ref (Unchecked.defaultof<_>)
- let ok = ref false
- while e.MoveNext() do
- if (latest := e.Current; (!ok || not (p !latest))) then
- ok := true
- yield !latest }
-
+ source |> seqFactory (fun () -> upcast SeqComposer.SkipWhile p)
[]
let forall2 p (source1: seq<_>) (source2: seq<_>) =
From 01675fe6688b65593ec78f5a4685194a3489de2a Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Fri, 7 Oct 2016 20:18:45 +1100
Subject: [PATCH 011/286] Changes SeqComposer to build bottom-up
A more direct calling process. Slows things down *slightly* when only a
single item is being processed, but is a better model to build from
going forward.
---
src/fsharp/FSharp.Core/seq.fs | 319 +++++++++++++---------------------
1 file changed, 125 insertions(+), 194 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 12533201ea2..655ff4fb830 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -817,167 +817,137 @@ namespace Microsoft.FSharp.Collections
let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #)
let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #)
- type [] SeqComponent<'T,'U> () =
- abstract ProcessNext : input:'T * halt:byref * output:byref<'U> -> bool
- abstract OnComplete : unit -> unit
+ type [] SeqComponentFactory<'T,'U> () =
+ abstract Create<'V> : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
+
+ member __.Compose<'V> (next:SeqComponent<'U,'V>) = Unchecked.defaultof<_>
- abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
+ and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) =
+ inherit SeqComponentFactory<'T,'V> ()
+ override __.Create<'W> (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create (second.Create next)
- abstract ComposeWithMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeWithFilter : Filter<'T> -> SeqComponent<'T,'U>
- abstract ComposeWithFilterThenMap<'S> : FilterThenMap<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeWithMapThenFilter<'S> : MapThenFilter<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeWithSkip : Skip<'T> -> SeqComponent<'T,'U>
+ and MapFactory<'T,'U> (map:'T->'U) =
+ inherit SeqComponentFactory<'T,'U> ()
+ override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
- default __.OnComplete () = ()
+ and MapiFactory<'T,'U> (mapi:int->'T->'U) =
+ inherit SeqComponentFactory<'T,'U> ()
+ override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
- default first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second)
+ and FilterFactory<'T> (filter:'T->bool) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Filter (filter, next)
- default second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
- default second.ComposeWithFilterThenMap<'S> (first:FilterThenMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeWithMapThenFilter<'S> (first:MapThenFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
+ and PairwiseFactory<'T> () =
+ inherit SeqComponentFactory<'T,'T*'T> ()
+ override __.Create<'V> (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next
- and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
+ and SkipFactory<'T> (count:int) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) :bool =
- let mutable temp = Unchecked.defaultof<'U>
- if first.ProcessNext (input, &halted, &temp) then
- second.ProcessNext (temp, &halted, &output)
- else
- false
+ and SkipWhileFactory<'T> (perdicate:'T->bool) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
- override __.Composer (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> =
- upcast Composed (first, second.Composer next)
+ and TakeWhileFactory<'T> (perdicate:'T->bool) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, next)
- override __.OnComplete () =
- first.OnComplete ()
- second.OnComplete ()
+ and TakeFactory<'T> (count:int) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, next)
- and Map<'T,'U> (map:'T->'U) =
- inherit SeqComponent<'T,'U>()
+ and ChooseFactory<'T,'U> (filter:'T->option<'U>) =
+ inherit SeqComponentFactory<'T,'U> ()
+ override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
- override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> =
- second.ComposeWithMap first
+ and [] SeqComponent<'T,'U> () =
+ abstract ProcessNext : input:'T * halt:byref * output:byref<'U> -> bool
+ abstract OnComplete : unit -> unit
- override second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> =
- upcast Map (first.Map >> second.Map)
-
- override second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'U> =
- upcast FilterThenMap (first.Filter, second.Map)
+ abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U>
+ abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U>
- override second.ComposeWithFilterThenMap<'S> (first:FilterThenMap<'S,'T>) : SeqComponent<'S,'U> =
- upcast FilterThenMap (first.Filter, first.Map >> second.Map)
+ default __.OnComplete () = ()
- override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
- output <- map input
- true
+ default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this)
+ default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this)
- member __.Map : 'T->'U = map
+ and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'T,'V>()
- and Mapi<'T,'U> (mapi:int->'T->'U) =
- inherit SeqComponent<'T,'U>()
+ default this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next)
- let mutable idx = 0
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
+ next.ProcessNext (map input, &halted, &output)
- override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
- output <- mapi idx input
- idx <- idx + 1
- true
+ and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'T,'V>()
- member __.Mapi : int->'T->'U = mapi
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
+ let u = map input
+ if filter u then
+ next.ProcessNext (u, &halted, &output)
+ else
+ false
- and Filter<'T> (filter:'T->bool) =
- inherit SeqComponent<'T,'T>()
+ and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'T,'V>()
- override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
- second.ComposeWithFilter first
+ let mutable idx = 0
- override second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> =
- upcast MapThenFilter (first.Map, second.Filter)
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
+ idx <- idx + 1
+ next.ProcessNext(mapi (idx-1) input, &halted, &output)
- override second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'T> =
- upcast Filter (Helpers.ComposeFilter first.Filter second.Filter)
+ and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>()
- override second.ComposeWithMapThenFilter<'S> (first:MapThenFilter<'S,'T>) : SeqComponent<'S,'T> =
- upcast MapThenFilter (first.Map, Helpers.ComposeFilter first.Filter second.Filter)
+ default this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next)
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
if filter input then
- output <- input
- true
+ next.ProcessNext (input, &halted, &output)
else
false
- member __.Filter :'T->bool = filter
-
- and MapThenFilter<'T,'U> (map:'T->'U, filter:'U->bool) =
- inherit SeqComponent<'T,'U>()
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) :bool =
- output <- map input
- Helpers.avoidTailCall (filter output)
-
- override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> =
- second.ComposeWithMapThenFilter first
-
- member __.Map : 'T->'U = map
- member __.Filter : 'U->bool = filter
-
- and FilterThenMap<'T,'U> (filter:'T->bool, map:'T->'U) =
- inherit SeqComponent<'T,'U>()
+ and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'T,'V>()
- override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
if filter input then
- output <- map input
- true
+ next.ProcessNext (map input, &halted, &output)
else
false
- override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = second.ComposeWithFilterThenMap first
-
- member __.Filter : 'T->bool = filter
- member __.Map : 'T->'U = map
-
- and Pairwise<'T> () =
- inherit SeqComponent<'T,'T*'T>()
+ and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) =
+ inherit SeqComponent<'T,'V>()
let mutable isFirst = true
let mutable lastValue = Unchecked.defaultof<'T>
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T*'T>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
if isFirst then
lastValue <- input
isFirst <- false
false
else
- output <- lastValue, input
+ let currentPair = lastValue, input
lastValue <- input
- true
+ next.ProcessNext(currentPair, &halted, &output)
- and Skip<'T> (skipCount:int) =
- inherit SeqComponent<'T,'T>()
+ and Skip<'T,'V> (skipCount:int, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>()
let mutable count = 0
- override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
- second.ComposeWithSkip first
-
- override second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
- if Int32.MaxValue - first.SkipCount - second.SkipCount > 0 then
- upcast Skip (first.SkipCount + second.SkipCount)
- else
- upcast Composed (first, second)
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
if count < skipCount then
count <- count + 1
false
else
- output <- input
- true
+ next.ProcessNext (input, &halted, &output)
override __.OnComplete () =
if count < skipCount then
@@ -985,25 +955,16 @@ namespace Microsoft.FSharp.Collections
invalidOpFmt "tried to skip {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- member __.SkipCount = skipCount
-
- and Take<'T> (takeCount:int) =
- inherit SeqComponent<'T,'T>()
+ and Take<'T,'V> (takeCount:int, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>()
let mutable count = 0
- override second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
- if Int32.MaxValue - first.SkipCount - second.TakeCount > 0 then
- upcast SkipThenTake (first.SkipCount, first.SkipCount+second.TakeCount)
- else
- upcast Composed (first, second)
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
if count < takeCount then
count <- count + 1
- output <- input
halted <- count = takeCount
- true
+ next.ProcessNext (input, &halted, &output)
else
halted <- true
false
@@ -1014,73 +975,46 @@ namespace Microsoft.FSharp.Collections
invalidOpFmt "tried to take {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- member __.TakeCount = takeCount
-
- and SkipThenTake<'T> (startIdx:int, endIdx:int) =
- inherit SeqComponent<'T,'T>()
-
- let mutable count = 0
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
- if count < startIdx then
- count <- count + 1
- false
- elif count < endIdx then
- count <- count + 1
- output <- input
- halted <- count = endIdx
- true
- else
- halted <- true
- false
-
- override __.OnComplete () =
- if count < startIdx then
- let x = startIdx - count
- invalidOpFmt "tried to skip {0} {1} past the end of the seq"
- [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- elif count < endIdx then
- let x = endIdx - count
- invalidOpFmt "tried to take {0} {1} past the end of the seq"
- [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
-
- and SkipWhile<'T> (predicate: 'T -> bool) =
- inherit SeqComponent<'T,'T>()
+ and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>()
let mutable skip = true
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
if skip then
skip <- predicate input
if skip then
false
else
- output <- input
- true
+ next.ProcessNext (input, &halted, &output)
else
- output <- input
- true
+ next.ProcessNext (input, &halted, &output)
- and TakeWhile<'T> (predicate: 'T -> bool) =
- inherit SeqComponent<'T,'T>()
+ and TakeWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>()
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
if predicate input then
- output <- input
- true
+ next.ProcessNext(input, &halted, &output)
else
halted <- true
false
- and Choose<'T, 'U> (choose:'T->'U option) =
- inherit SeqComponent<'T,'U>()
+ and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'T,'V>()
- override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
match choose input with
- | Some value -> output <- value
- true
+ | Some value -> next.ProcessNext (value, &halted, &output)
| None -> false
+ and Tail<'T> () =
+ inherit SeqComponent<'T,'T>()
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ output <- input
+ true
+
type SeqProcessNextStates =
| NotStarted = 1
| Finished = 2
@@ -1198,13 +1132,13 @@ namespace Microsoft.FSharp.Collections
[]
type ComposableEnumerable<'T> () =
- abstract member Compose<'U> : (unit -> SeqComponent<'T,'U>) -> IEnumerable<'U>
+ abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
- type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:unit->SeqComponent<'T,'U>) =
+ type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- Helpers.UpcastEnumerator (new SeqEnumeratorEnumerator<'T,'U>(enumerable.GetEnumerator(), current ()))
+ Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create (Tail ())))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
@@ -1212,8 +1146,8 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
- override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, fun () -> (current ()).Composer (next ())))
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, ComposedFactory (current, next)))
// interface ISeqEnumerable<'U> with
// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
@@ -1231,11 +1165,11 @@ namespace Microsoft.FSharp.Collections
//
// state
- type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:unit->SeqComponent<'T,'U>) =
+ type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- Helpers.UpcastEnumerator (new SeqArrayEnumerator<'T,'U>(array, current ()))
+ Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create (Tail ())))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
@@ -1243,8 +1177,8 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
- override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, fun () -> (current ()).Composer (next ())))
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, ComposedFactory (current, next)))
// interface ISeqEnumerable<'U> with
// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
@@ -1263,11 +1197,11 @@ namespace Microsoft.FSharp.Collections
//
// state
- type SeqListEnumerable<'T,'U>(alist:list<'T>, current:unit->SeqComponent<'T,'U>) =
+ type SeqListEnumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- upcast (new ListComposedEnumerator<'T,'U>(alist, current ()))
+ Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create (Tail ())))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
@@ -1275,8 +1209,8 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
- override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
- upcast new SeqListEnumerable<'T,'V>(alist, fun () -> (current ()).Composer (next ()))
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next)))
#if FX_NO_ICLONEABLE
@@ -1406,23 +1340,20 @@ namespace Microsoft.FSharp.Collections
| :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent))
| _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent))
- let private seqFactoryForImmutable seqComponent (source:seq<'T>) =
- source |> seqFactory (fun () -> seqComponent)
-
[]
let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> =
- source |> seqFactoryForImmutable (SeqComposer.Filter f)
+ source |> seqFactory (SeqComposer.FilterFactory f)
[]
let where f source = filter f source
[]
let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> =
- source |> seqFactoryForImmutable (SeqComposer.Map f)
+ source |> seqFactory (SeqComposer.MapFactory f)
[]
let mapi f source =
- source |> seqFactory (fun () -> upcast SeqComposer.Mapi f)
+ source |> seqFactory (SeqComposer.MapiFactory f)
[]
let mapi2 f source1 source2 =
@@ -1445,7 +1376,7 @@ namespace Microsoft.FSharp.Collections
[]
let choose f source =
- source |> seqFactoryForImmutable (SeqComposer.Choose f)
+ source |> seqFactory (SeqComposer.ChooseFactory f)
[]
let indexed source =
@@ -1508,7 +1439,7 @@ namespace Microsoft.FSharp.Collections
if count < 0 then invalidArgInputMustBeNonNegative "count" count
(* Note: don't create or dispose any IEnumerable if n = 0 *)
if count = 0 then empty else
- source |> seqFactory (fun () -> upcast SeqComposer.Take count)
+ source |> seqFactory (SeqComposer.TakeFactory count)
[]
let isEmpty (source : seq<'T>) =
@@ -1689,7 +1620,7 @@ namespace Microsoft.FSharp.Collections
[]
let pairwise<'T> (source:seq<'T>) : seq<'T*'T> =
- source |> seqFactory (fun () -> upcast SeqComposer.Pairwise ())
+ source |> seqFactory (SeqComposer.PairwiseFactory ())
[]
let scan<'T,'State> f (z:'State) (source : seq<'T>) =
@@ -2119,15 +2050,15 @@ namespace Microsoft.FSharp.Collections
*)
[]
let takeWhile p (source: seq<_>) =
- source |> seqFactory (fun () -> upcast SeqComposer.TakeWhile p)
+ source |> seqFactory (SeqComposer.TakeWhileFactory p)
[]
let skip count (source: seq<_>) =
- source |> seqFactory (fun () -> upcast SeqComposer.Skip count)
+ source |> seqFactory (SeqComposer.SkipFactory count)
[]
let skipWhile p (source: seq<_>) =
- source |> seqFactory (fun () -> upcast SeqComposer.SkipWhile p)
+ source |> seqFactory (SeqComposer.SkipWhileFactory p)
[]
let forall2 p (source1: seq<_>) (source2: seq<_>) =
From 751d54ca820171ca32f1d8e070a5b8eb03d447f4 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Fri, 7 Oct 2016 20:30:18 +1100
Subject: [PATCH 012/286] Remove unused member
---
src/fsharp/FSharp.Core/seq.fs | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 655ff4fb830..f39da6f8bc6 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -819,8 +819,6 @@ namespace Microsoft.FSharp.Collections
type [] SeqComponentFactory<'T,'U> () =
abstract Create<'V> : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
-
- member __.Compose<'V> (next:SeqComponent<'U,'V>) = Unchecked.defaultof<_>
and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) =
inherit SeqComponentFactory<'T,'V> ()
From 441a9b19642761a743d5728f9a11575808fe2c88 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sat, 8 Oct 2016 06:55:59 +1100
Subject: [PATCH 013/286] Simplified ProcessNext call by creating Result object
Due to the bottom-up build process I now have a consistent output
signature, which allowed it to be wrapped in an single object rather
than being passed up and down the chain of ProcessNext calls.
---
src/fsharp/FSharp.Core/seq.fs | 222 +++++++++++++++++-----------------
1 file changed, 114 insertions(+), 108 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index f39da6f8bc6..299b493a181 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -817,107 +817,123 @@ namespace Microsoft.FSharp.Collections
let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #)
let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #)
+ type Result<'T>() =
+ let mutable halted = false
+
+ member __.StopFurtherProcessing () = halted <- true
+ member __.Halted = halted
+
+ member val Current = Unchecked.defaultof<'T> with get, set
+
type [] SeqComponentFactory<'T,'U> () =
- abstract Create<'V> : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
+ abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V>
and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) =
inherit SeqComponentFactory<'T,'V> ()
- override __.Create<'W> (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create (second.Create next)
+ override __.Create<'W> (result:Result<'W>) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create result (second.Create result next)
+
+ and ChooseFactory<'T,'U> (filter:'T->option<'U>) =
+ inherit SeqComponentFactory<'T,'U> ()
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
+
+ and FilterFactory<'T> (filter:'T->bool) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter
and MapFactory<'T,'U> (map:'T->'U) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
and MapiFactory<'T,'U> (mapi:int->'T->'U) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
-
- and FilterFactory<'T> (filter:'T->bool) =
- inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Filter (filter, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
and PairwiseFactory<'T> () =
inherit SeqComponentFactory<'T,'T*'T> ()
- override __.Create<'V> (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next
and SkipFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
and SkipWhileFactory<'T> (perdicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
and TakeWhileFactory<'T> (perdicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, next)
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, result, next)
and TakeFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, next)
-
- and ChooseFactory<'T,'U> (filter:'T->option<'U>) =
- inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next)
and [] SeqComponent<'T,'U> () =
- abstract ProcessNext : input:'T * halt:byref * output:byref<'U> -> bool
+ abstract ProcessNext : input:'T -> bool
abstract OnComplete : unit -> unit
- abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U>
- abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U>
+ abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U>
+ abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U>
default __.OnComplete () = ()
- default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this)
- default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this)
+ default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this)
+ default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this)
- and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) =
+ and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>()
- default this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next)
+ override __.ProcessNext (input:'T) : bool =
+ match choose input with
+ | Some value -> Helpers.avoidTailCall (next.ProcessNext value)
+ | None -> false
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
- next.ProcessNext (map input, &halted, &output)
+ and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>()
- and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) =
+ default this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next)
+
+ override __.ProcessNext (input:'T) : bool =
+ if filter input then
+ Helpers.avoidTailCall (next.ProcessNext input)
+ else
+ false
+
+ and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>()
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
- let u = map input
- if filter u then
- next.ProcessNext (u, &halted, &output)
+ override __.ProcessNext (input:'T) : bool =
+ if filter input then
+ Helpers.avoidTailCall (next.ProcessNext (map input))
else
false
- and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqComponent<'U,'V>) =
+ and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>()
- let mutable idx = 0
+ override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next)
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
- idx <- idx + 1
- next.ProcessNext(mapi (idx-1) input, &halted, &output)
+ override __.ProcessNext (input:'T) : bool =
+ Helpers.avoidTailCall (next.ProcessNext (map input))
- and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) =
+ and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>()
- default this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next)
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
- if filter input then
- next.ProcessNext (input, &halted, &output)
+ override __.ProcessNext (input:'T) : bool =
+ let u = map input
+ if filter u then
+ Helpers.avoidTailCall (next.ProcessNext u)
else
false
- and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqComponent<'U,'V>) =
+ and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>()
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
- if filter input then
- next.ProcessNext (map input, &halted, &output)
- else
- false
+ let mutable idx = 0
+
+ override __.ProcessNext (input:'T) : bool =
+ idx <- idx + 1
+ Helpers.avoidTailCall (next.ProcessNext (mapi (idx-1) input))
and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) =
inherit SeqComponent<'T,'V>()
@@ -925,7 +941,7 @@ namespace Microsoft.FSharp.Collections
let mutable isFirst = true
let mutable lastValue = Unchecked.defaultof<'T>
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
+ override __.ProcessNext (input:'T) : bool =
if isFirst then
lastValue <- input
isFirst <- false
@@ -933,19 +949,19 @@ namespace Microsoft.FSharp.Collections
else
let currentPair = lastValue, input
lastValue <- input
- next.ProcessNext(currentPair, &halted, &output)
+ Helpers.avoidTailCall (next.ProcessNext currentPair)
and Skip<'T,'V> (skipCount:int, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
let mutable count = 0
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
+ override __.ProcessNext (input:'T) : bool =
if count < skipCount then
count <- count + 1
false
else
- next.ProcessNext (input, &halted, &output)
+ Helpers.avoidTailCall (next.ProcessNext input)
override __.OnComplete () =
if count < skipCount then
@@ -953,18 +969,34 @@ namespace Microsoft.FSharp.Collections
invalidOpFmt "tried to skip {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- and Take<'T,'V> (takeCount:int, next:SeqComponent<'T,'V>) =
+ and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>()
+
+ let mutable skip = true
+
+ override __.ProcessNext (input:'T) : bool =
+ if skip then
+ skip <- predicate input
+ if skip then
+ false
+ else
+ Helpers.avoidTailCall (next.ProcessNext input)
+ else
+ Helpers.avoidTailCall (next.ProcessNext input)
+
+ and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
let mutable count = 0
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
+ override __.ProcessNext (input:'T) : bool =
if count < takeCount then
count <- count + 1
- halted <- count = takeCount
- next.ProcessNext (input, &halted, &output)
+ if count = takeCount then
+ result.StopFurtherProcessing ()
+ next.ProcessNext input
else
- halted <- true
+ result.StopFurtherProcessing ()
false
override __.OnComplete () =
@@ -973,44 +1005,21 @@ namespace Microsoft.FSharp.Collections
invalidOpFmt "tried to take {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) =
+ and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
- let mutable skip = true
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
- if skip then
- skip <- predicate input
- if skip then
- false
- else
- next.ProcessNext (input, &halted, &output)
- else
- next.ProcessNext (input, &halted, &output)
-
- and TakeWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) =
- inherit SeqComponent<'T,'V>()
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
+ override __.ProcessNext (input:'T) : bool =
if predicate input then
- next.ProcessNext(input, &halted, &output)
+ next.ProcessNext input
else
- halted <- true
+ result.StopFurtherProcessing ()
false
- and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
- match choose input with
- | Some value -> next.ProcessNext (value, &halted, &output)
- | None -> false
-
- and Tail<'T> () =
+ and Tail<'T> (result:Result<'T>) =
inherit SeqComponent<'T,'T>()
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
- output <- input
+ override __.ProcessNext (input:'T) : bool =
+ result.Current <- input
true
type SeqProcessNextStates =
@@ -1018,16 +1027,14 @@ namespace Microsoft.FSharp.Collections
| Finished = 2
| InProcess = 3
- type SeqComposedEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) =
+ type SeqComposedEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
let mutable state = SeqProcessNextStates.NotStarted
- let mutable current = Unchecked.defaultof<'U>
- let mutable halted = false
let mutable source = enumerator
let rec moveNext () =
- if (not halted) && source.MoveNext () then
- if t2u.ProcessNext (source.Current, &halted, ¤t) then
+ if (not result.Halted) && source.MoveNext () then
+ if t2u.ProcessNext source.Current then
true
else
moveNext ()
@@ -1054,19 +1061,17 @@ namespace Microsoft.FSharp.Collections
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> current
+ | _ -> result.Current
- type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) =
+ type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
let mutable state = SeqProcessNextStates.NotStarted
- let mutable current = Unchecked.defaultof<'U>
- let mutable halted = false
let mutable idx = 0
let rec moveNext () =
- if (not halted) && idx < array.Length then
+ if (not result.Halted) && idx < array.Length then
idx <- idx+1
- if t2u.ProcessNext (array.[idx-1], &halted, ¤t) then
+ if t2u.ProcessNext array.[idx-1] then
true
else
moveNext ()
@@ -1090,20 +1095,18 @@ namespace Microsoft.FSharp.Collections
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> current
+ | _ -> result.Current
- type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>) =
+ type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
let mutable state = SeqProcessNextStates.NotStarted
- let mutable current = Unchecked.defaultof<'U>
- let mutable halted = false
let mutable list = alist
let rec moveNext () =
- match halted, list with
+ match result.Halted, list with
| false, head::tail ->
list <- tail
- if t2u.ProcessNext (head, &halted, ¤t) then
+ if t2u.ProcessNext head then
true
else
moveNext ()
@@ -1126,7 +1129,7 @@ namespace Microsoft.FSharp.Collections
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> current
+ | _ -> result.Current
[]
type ComposableEnumerable<'T> () =
@@ -1136,7 +1139,8 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create (Tail ())))
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
@@ -1167,7 +1171,8 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create (Tail ())))
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
@@ -1199,7 +1204,8 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create (Tail ())))
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
From 16461ea2045674ca4429e82544e5a4b953688e90 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sat, 8 Oct 2016 10:36:05 +1100
Subject: [PATCH 014/286] default -> override
---
src/fsharp/FSharp.Core/seq.fs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 299b493a181..bd93cfdd017 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -891,7 +891,7 @@ namespace Microsoft.FSharp.Collections
and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
- default this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next)
+ override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next)
override __.ProcessNext (input:'T) : bool =
if filter input then
From 9c2e7d4a03dae014167ee0f5c8e40a08997b1310 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sat, 8 Oct 2016 19:35:08 +1100
Subject: [PATCH 015/286] OptimizedClosure for mapi
---
src/fsharp/FSharp.Core/seq.fs | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index bd93cfdd017..62711b6c7d4 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -930,10 +930,11 @@ namespace Microsoft.FSharp.Collections
inherit SeqComponent<'T,'V>()
let mutable idx = 0
+ let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi
override __.ProcessNext (input:'T) : bool =
idx <- idx + 1
- Helpers.avoidTailCall (next.ProcessNext (mapi (idx-1) input))
+ Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input)))
and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) =
inherit SeqComponent<'T,'V>()
@@ -1156,14 +1157,14 @@ namespace Microsoft.FSharp.Collections
// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
//
// let enumerator = enumerable.GetEnumerator ()
-// let components = current ()
-// let mutable output = Unchecked.defaultof<'U>
-// let mutable halt = false
+// let result = Result<'U> ()
+//
+// let components = current.Create result (Tail result)
//
// let mutable state = initialState
-// while (not halt) && enumerator.MoveNext () do
-// if components.ProcessNext (enumerator.Current, &halt, &output) then
-// state <- folder'.Invoke (state, output)
+// while (not result.Halted) && enumerator.MoveNext () do
+// if components.ProcessNext (enumerator.Current) then
+// state <- folder'.Invoke (state, result.Current)
//
// state
@@ -1188,14 +1189,13 @@ namespace Microsoft.FSharp.Collections
// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
//
// let mutable idx = 0
-// let components = current ()
-// let mutable current = Unchecked.defaultof<'U>
-// let mutable halt = false
+// let result = Result<'U> ()
+// let components = current.Create result (Tail result)
//
// let mutable state = initialState
-// while (not halt) && idx < array.Length do
-// if components.ProcessNext (array.[idx], &halt, ¤t) then
-// state <- folder'.Invoke(state, current)
+// while (not result.Halted) && idx < array.Length do
+// if components.ProcessNext array.[idx] then
+// state <- folder'.Invoke(state, result.Current)
// idx <- idx + 1
//
// state
From 86d8781037360e5cc9bfec9eff7223c3d3a43f6d Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sat, 8 Oct 2016 20:19:46 +1100
Subject: [PATCH 016/286] Consolidated code in base class ensuring performance
Retained MoveNext in derived class to ensure we didn't add an extra
virtual call into the call stack.
---
src/fsharp/FSharp.Core/seq.fs | 144 ++++++++++++++--------------------
1 file changed, 60 insertions(+), 84 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 62711b6c7d4..89b18b6f2db 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -817,9 +817,16 @@ namespace Microsoft.FSharp.Collections
let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #)
let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #)
+ type SeqProcessNextStates =
+ | NotStarted = 1
+ | Finished = 2
+ | InProcess = 3
+
type Result<'T>() =
let mutable halted = false
+ member val SeqState = SeqProcessNextStates.NotStarted with get, set
+
member __.StopFurtherProcessing () = halted <- true
member __.Halted = halted
@@ -1023,15 +1030,25 @@ namespace Microsoft.FSharp.Collections
result.Current <- input
true
- type SeqProcessNextStates =
- | NotStarted = 1
- | Finished = 2
- | InProcess = 3
+ []
+ type ComposedEnumerator<'T>(result:Result<'T>) =
+ interface IDisposable with
+ member __.Dispose() : unit = ()
- type SeqComposedEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- let mutable state = SeqProcessNextStates.NotStarted
+ interface IEnumerator with
+ member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current
+ member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)"
+ member __.Reset () : unit = noReset ()
- let mutable source = enumerator
+ interface IEnumerator<'T> with
+ member __.Current =
+ match result.SeqState with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> result.Current
+
+ type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit ComposedEnumerator<'U>(result)
let rec moveNext () =
if (not result.Halted) && source.MoveNext () then
@@ -1040,32 +1057,20 @@ namespace Microsoft.FSharp.Collections
else
moveNext ()
else
- state <- SeqProcessNextStates.Finished
+ result.SeqState <- SeqProcessNextStates.Finished
t2u.OnComplete ()
false
- interface IDisposable with
- member __.Dispose():unit =
- match source with
- | null -> ()
- | _ -> source.Dispose (); source <- Unchecked.defaultof<_>
-
interface IEnumerator with
- member this.Current : obj = box (Helpers.UpcastEnumerator this).Current
member __.MoveNext () =
- state <- SeqProcessNextStates.InProcess
+ result.SeqState <- SeqProcessNextStates.InProcess
moveNext ()
- member __.Reset () : unit = noReset ()
- interface IEnumerator<'U> with
- member __.Current =
- match state with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> result.Current
+ interface IDisposable with
+ member __.Dispose() = source.Dispose ()
type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- let mutable state = SeqProcessNextStates.NotStarted
+ inherit ComposedEnumerator<'U>(result)
let mutable idx = 0
@@ -1077,77 +1082,58 @@ namespace Microsoft.FSharp.Collections
else
moveNext ()
else
- state <- SeqProcessNextStates.Finished
+ result.SeqState <- SeqProcessNextStates.Finished
t2u.OnComplete ()
false
- interface IDisposable with
- member __.Dispose() : unit = ()
-
interface IEnumerator with
- member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current
member __.MoveNext () =
- state <- SeqProcessNextStates.InProcess
+ result.SeqState <- SeqProcessNextStates.InProcess
moveNext ()
- member __.Reset () : unit = noReset ()
-
- interface IEnumerator<'U> with
- member __.Current =
- match state with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> result.Current
type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- let mutable state = SeqProcessNextStates.NotStarted
+ inherit ComposedEnumerator<'U>(result)
let mutable list = alist
- let rec moveNext () =
- match result.Halted, list with
+ let rec moveNext current =
+ match result.Halted, current with
| false, head::tail ->
- list <- tail
if t2u.ProcessNext head then
+ list <- tail
true
else
- moveNext ()
- | _ -> state <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
- false
-
- interface IDisposable with
- member __.Dispose() : unit = ()
+ moveNext tail
+ | _ ->
+ result.SeqState <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
interface IEnumerator with
- member this.Current : obj = box (this:>IEnumerator<'U>).Current
member __.MoveNext () =
- state <- SeqProcessNextStates.InProcess
- moveNext ()
- member __.Reset () : unit = noReset ()
-
- interface IEnumerator<'U> with
- member __.Current =
- match state with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> result.Current
+ result.SeqState <- SeqProcessNextStates.InProcess
+ moveNext list
[]
type ComposableEnumerable<'T> () =
abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
+ interface IEnumerable with
+ member this.GetEnumerator () : IEnumerator =
+ let genericEnumerable = Helpers.UpcastEnumerable this
+ let genericEnumerator = genericEnumerable.GetEnumerator ()
+ Helpers.UpcastEnumeratorNonGeneric genericEnumerator
+
+ interface IEnumerable<'T> with
+ member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
+
type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerable<'U>()
- let getEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result))
-
- interface IEnumerable with
- member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
-
interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result))
override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, ComposedFactory (current, next)))
@@ -1171,15 +1157,10 @@ namespace Microsoft.FSharp.Collections
type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerable<'U>()
- let getEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result))
-
- interface IEnumerable with
- member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
-
interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result))
override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, ComposedFactory (current, next)))
@@ -1203,15 +1184,10 @@ namespace Microsoft.FSharp.Collections
type SeqListEnumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerable<'U>()
- let getEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result))
-
- interface IEnumerable with
- member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
-
interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result))
override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next)))
From 3a3fd6fc9b90b4c1c97a3250b10e626ab40797fb Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sat, 8 Oct 2016 20:38:54 +1100
Subject: [PATCH 017/286] Added ComposableEnumerableFactoryHelper
Sweeping up common functionality
---
src/fsharp/FSharp.Core/seq.fs | 46 ++++++++++++++++++++++-------------
1 file changed, 29 insertions(+), 17 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 89b18b6f2db..5c88f61a6cc 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1127,16 +1127,28 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'T> with
member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
- type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
+ []
+ type ComposableEnumerableFactoryHelper<'T,'U> (seqComponentFactory:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerable<'U>()
+ member __.FactoryCompose next =
+ ComposedFactory (seqComponentFactory, next)
+
+ member __.CreateSeqComponent () =
+ let result = Result<'U> ()
+ let seqComponent = seqComponentFactory.Create result (Tail result)
+ result, seqComponent
+
+ type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
+
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result))
+ let result, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), seqComponent, result))
- override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, ComposedFactory (current, next)))
+ override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, this.FactoryCompose next))
// interface ISeqEnumerable<'U> with
// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
@@ -1154,16 +1166,16 @@ namespace Microsoft.FSharp.Collections
//
// state
- type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerable<'U>()
+ type SeqArrayEnumerable<'T,'U>(array:array<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result))
+ let result, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, seqComponent, result))
- override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, ComposedFactory (current, next)))
+ override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, this.FactoryCompose next))
// interface ISeqEnumerable<'U> with
// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
@@ -1181,16 +1193,16 @@ namespace Microsoft.FSharp.Collections
//
// state
- type SeqListEnumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerable<'U>()
+ type SeqListEnumerable<'T,'U>(alist:list<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result))
+ let result, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, seqComponent, result))
- override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next)))
+ override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, this.FactoryCompose next))
#if FX_NO_ICLONEABLE
From 7ff0fb091d99d85ae60441f2c6ed6968784bacfc Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 05:36:56 +1100
Subject: [PATCH 018/286] init(Infinite)? implementations
Not as simple as it should be due to the original implementation
deciding to evaluate Current in a lazy fashion. Comments have been
splattered around hopefully describing the situation in enough detail.
---
src/fsharp/FSharp.Core/seq.fs | 92 ++++++++++++++++++++++++++++++++++-
1 file changed, 90 insertions(+), 2 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 5c88f61a6cc..2c74e6f63ad 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -878,12 +878,18 @@ namespace Microsoft.FSharp.Collections
and [] SeqComponent<'T,'U> () =
abstract ProcessNext : input:'T -> bool
abstract OnComplete : unit -> unit
+
+ // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip
+ // and it can only do it at the start of a sequence
+ abstract Skipping : unit -> bool
abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U>
abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U>
default __.OnComplete () = ()
+ default __.Skipping () = false
+
default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this)
default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this)
@@ -964,6 +970,13 @@ namespace Microsoft.FSharp.Collections
let mutable count = 0
+ override __.Skipping () =
+ if count < skipCount then
+ count <- count + 1
+ true
+ else
+ false
+
override __.ProcessNext (input:'T) : bool =
if count < skipCount then
count <- count + 1
@@ -1204,6 +1217,79 @@ namespace Microsoft.FSharp.Collections
override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, this.FactoryCompose next))
+ // The original implementation of "init" delayed the calculation of Current, and so it was possible
+ // to do MoveNext without it's value being calculated.
+ // I can imagine only two scenerios where that is possibly sane, although a simple solution is readily
+ // at hand in both cases. The first is that of an expensive generator function, where you skip the
+ // first n elements. The simple solution would have just been to have a map ((+) n) as the first operation
+ // instead. The second case would be counting elements, but that is only of use if you're not filtering
+ // or mapping or doing anything else (as that would cause Current to be evaluated!) and
+ // so you already know what the count is!! Anyway, someone thought it was a good idea, so
+ // I have had to add an extra function that is used in Skip to determine if we are touching
+ // Current or not.
+ type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit ComposedEnumerator<'U>(result)
+
+ // we are offset by 1 to allow for values going up to System.Int32.MaxValue
+ // System.Int32.MaxValue is an illegal value for the "infinite" sequence
+ let terminatingIdx =
+ if count.HasValue then
+ count.Value - 1
+ else
+ System.Int32.MaxValue
+
+ let mutable maybeSkipping = true
+ let mutable idx = -1
+
+ let rec moveNext () =
+ if (not result.Halted) && idx < terminatingIdx then
+ idx <- idx + 1
+
+ if maybeSkipping then
+ // Skip can only is only checked at the start of the sequence, so once
+ // triggered, we stay triggered.
+ maybeSkipping <- t2u.Skipping ()
+
+ if maybeSkipping || t2u.ProcessNext (f idx) then
+ true
+ else
+ moveNext ()
+ elif (not result.Halted) && idx = System.Int32.MaxValue then
+ raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue))
+ else
+ result.SeqState <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ result.SeqState <- SeqProcessNextStates.InProcess
+ moveNext ()
+
+ type InitComposingEnumerable<'T,'U>(count:Nullable, f:int->'T, seqComponentFactory:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, seqComponent, result))
+
+ override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new InitComposingEnumerable<'T,'V>(count, f, this.FactoryCompose next))
+
+ type InitEnumerable<'T>(count:Nullable, f:int->'T) =
+ inherit ComposableEnumerable<'T>()
+
+ interface IEnumerable<'T> with
+ member this.GetEnumerator () : IEnumerator<'T> =
+ // we defer back to the original implementation as, as it's quite idiomatic in it's decision
+ // to calculate Current in a lazy fashion. I doubt anyone is really using this functionality
+ // in the way presented, but it's possible.
+ upto (if count.HasValue then Some count.Value else None) f
+
+ override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
+ Helpers.UpcastEnumerable (InitComposingEnumerable<'T,'V>(count, f, next))
+
#if FX_NO_ICLONEABLE
open Microsoft.FSharp.Core.ICloneableExtensions
@@ -1226,12 +1312,14 @@ namespace Microsoft.FSharp.Collections
let empty<'T> = (EmptyEnumerable :> seq<'T>)
[]
- let initInfinite f = mkSeq (fun () -> IEnumerator.upto None f)
+ let initInfinite<'T> (f:int->'T) : IEnumerable<'T> =
+ SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable (), f))
[]
let init count f =
if count < 0 then invalidArgInputMustBeNonNegative "count" count
- mkSeq (fun () -> IEnumerator.upto (Some (count-1)) f)
+ elif count = 0 then empty else
+ SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable count, f))
[]
let iter f (source : seq<'T>) =
From aa25d0cffe6b4934267180be33dec33a6973ccdd Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 06:00:07 +1100
Subject: [PATCH 019/286] Split Result object in multi-leveled Signal
The plan is to then implement fold like functionality in a Tail like
object that we can expose out in a public interface, so I'm trying to
minimize what would be needed to be visible externally.
---
src/fsharp/FSharp.Core/seq.fs | 131 +++++++++++++++++-----------------
1 file changed, 67 insertions(+), 64 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 2c74e6f63ad..9d2342a35ac 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -817,63 +817,57 @@ namespace Microsoft.FSharp.Collections
let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #)
let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #)
- type SeqProcessNextStates =
- | NotStarted = 1
- | Finished = 2
- | InProcess = 3
-
- type Result<'T>() =
+ type SeqSignal () =
let mutable halted = false
-
- member val SeqState = SeqProcessNextStates.NotStarted with get, set
-
member __.StopFurtherProcessing () = halted <- true
member __.Halted = halted
+ type TailSignal<'T> () =
+ inherit SeqSignal ()
member val Current = Unchecked.defaultof<'T> with get, set
type [] SeqComponentFactory<'T,'U> () =
- abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V>
+ abstract Create<'V> : SeqSignal -> SeqComponent<'U,'V> -> SeqComponent<'T,'V>
and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) =
inherit SeqComponentFactory<'T,'V> ()
- override __.Create<'W> (result:Result<'W>) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create result (second.Create result next)
+ override __.Create<'W> (signal:SeqSignal) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create signal (second.Create signal next)
and ChooseFactory<'T,'U> (filter:'T->option<'U>) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
+ override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
and FilterFactory<'T> (filter:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter
+ override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter
and MapFactory<'T,'U> (map:'T->'U) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
+ override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
and MapiFactory<'T,'U> (mapi:int->'T->'U) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
+ override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
and PairwiseFactory<'T> () =
inherit SeqComponentFactory<'T,'T*'T> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next
+ override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next
and SkipFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
+ override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
and SkipWhileFactory<'T> (perdicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
+ override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
and TakeWhileFactory<'T> (perdicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, result, next)
+ override __.Create<'V> (signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, signal, next)
and TakeFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next)
+ override __.Create<'V> (signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, signal, next)
and [] SeqComponent<'T,'U> () =
abstract ProcessNext : input:'T -> bool
@@ -1005,7 +999,7 @@ namespace Microsoft.FSharp.Collections
else
Helpers.avoidTailCall (next.ProcessNext input)
- and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
+ and Take<'T,'V> (takeCount:int, signal:SeqSignal, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
let mutable count = 0
@@ -1014,10 +1008,10 @@ namespace Microsoft.FSharp.Collections
if count < takeCount then
count <- count + 1
if count = takeCount then
- result.StopFurtherProcessing ()
+ signal.StopFurtherProcessing ()
next.ProcessNext input
else
- result.StopFurtherProcessing ()
+ signal.StopFurtherProcessing ()
false
override __.OnComplete () =
@@ -1026,25 +1020,34 @@ namespace Microsoft.FSharp.Collections
invalidOpFmt "tried to take {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) =
+ and TakeWhile<'T,'V> (predicate:'T->bool, signal:SeqSignal, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
override __.ProcessNext (input:'T) : bool =
if predicate input then
next.ProcessNext input
else
- result.StopFurtherProcessing ()
+ signal.StopFurtherProcessing ()
false
- and Tail<'T> (result:Result<'T>) =
+ and Tail<'T> (signal:TailSignal<'T>) =
inherit SeqComponent<'T,'T>()
override __.ProcessNext (input:'T) : bool =
- result.Current <- input
+ signal.Current <- input
true
+ type SeqEnumeratorState =
+ | NotStarted = 1
+ | Finished = 2
+ | InProcess = 3
+
+ type EnumeratorSignal<'T>() =
+ inherit TailSignal<'T>()
+ member val EnumeratorState = SeqEnumeratorState.NotStarted with get, set
+
[]
- type ComposedEnumerator<'T>(result:Result<'T>) =
+ type ComposedEnumerator<'T>(signal:EnumeratorSignal<'T>) =
interface IDisposable with
member __.Dispose() : unit = ()
@@ -1055,62 +1058,62 @@ namespace Microsoft.FSharp.Collections
interface IEnumerator<'T> with
member __.Current =
- match result.SeqState with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> result.Current
+ match signal.EnumeratorState with
+ | SeqEnumeratorState.NotStarted -> notStarted()
+ | SeqEnumeratorState.Finished -> alreadyFinished()
+ | _ -> signal.Current
- type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit ComposedEnumerator<'U>(result)
+ type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
let rec moveNext () =
- if (not result.Halted) && source.MoveNext () then
+ if (not signal.Halted) && source.MoveNext () then
if t2u.ProcessNext source.Current then
true
else
moveNext ()
else
- result.SeqState <- SeqProcessNextStates.Finished
+ signal.EnumeratorState <- SeqEnumeratorState.Finished
t2u.OnComplete ()
false
interface IEnumerator with
member __.MoveNext () =
- result.SeqState <- SeqProcessNextStates.InProcess
+ signal.EnumeratorState <- SeqEnumeratorState.InProcess
moveNext ()
interface IDisposable with
member __.Dispose() = source.Dispose ()
- type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit ComposedEnumerator<'U>(result)
+ type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
let mutable idx = 0
let rec moveNext () =
- if (not result.Halted) && idx < array.Length then
+ if (not signal.Halted) && idx < array.Length then
idx <- idx+1
if t2u.ProcessNext array.[idx-1] then
true
else
moveNext ()
else
- result.SeqState <- SeqProcessNextStates.Finished
+ signal.EnumeratorState <- SeqEnumeratorState.Finished
t2u.OnComplete ()
false
interface IEnumerator with
member __.MoveNext () =
- result.SeqState <- SeqProcessNextStates.InProcess
+ signal.EnumeratorState <- SeqEnumeratorState.InProcess
moveNext ()
- type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit ComposedEnumerator<'U>(result)
+ type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
let mutable list = alist
let rec moveNext current =
- match result.Halted, current with
+ match signal.Halted, current with
| false, head::tail ->
if t2u.ProcessNext head then
list <- tail
@@ -1118,13 +1121,13 @@ namespace Microsoft.FSharp.Collections
else
moveNext tail
| _ ->
- result.SeqState <- SeqProcessNextStates.Finished
+ signal.EnumeratorState <- SeqEnumeratorState.Finished
t2u.OnComplete ()
false
interface IEnumerator with
member __.MoveNext () =
- result.SeqState <- SeqProcessNextStates.InProcess
+ signal.EnumeratorState <- SeqEnumeratorState.InProcess
moveNext list
[]
@@ -1148,17 +1151,17 @@ namespace Microsoft.FSharp.Collections
ComposedFactory (seqComponentFactory, next)
member __.CreateSeqComponent () =
- let result = Result<'U> ()
- let seqComponent = seqComponentFactory.Create result (Tail result)
- result, seqComponent
+ let signal = EnumeratorSignal<'U> ()
+ let seqComponent = seqComponentFactory.Create signal (Tail signal)
+ signal, seqComponent
type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let result, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), seqComponent, result))
+ let signal, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), seqComponent, signal))
override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, this.FactoryCompose next))
@@ -1184,8 +1187,8 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let result, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, seqComponent, result))
+ let signal, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, seqComponent, signal))
override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, this.FactoryCompose next))
@@ -1211,8 +1214,8 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let result, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, seqComponent, result))
+ let signal, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, seqComponent, signal))
override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, this.FactoryCompose next))
@@ -1227,8 +1230,8 @@ namespace Microsoft.FSharp.Collections
// so you already know what the count is!! Anyway, someone thought it was a good idea, so
// I have had to add an extra function that is used in Skip to determine if we are touching
// Current or not.
- type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit ComposedEnumerator<'U>(result)
+ type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
// we are offset by 1 to allow for values going up to System.Int32.MaxValue
// System.Int32.MaxValue is an illegal value for the "infinite" sequence
@@ -1242,7 +1245,7 @@ namespace Microsoft.FSharp.Collections
let mutable idx = -1
let rec moveNext () =
- if (not result.Halted) && idx < terminatingIdx then
+ if (not signal.Halted) && idx < terminatingIdx then
idx <- idx + 1
if maybeSkipping then
@@ -1254,16 +1257,16 @@ namespace Microsoft.FSharp.Collections
true
else
moveNext ()
- elif (not result.Halted) && idx = System.Int32.MaxValue then
+ elif (not signal.Halted) && idx = System.Int32.MaxValue then
raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue))
else
- result.SeqState <- SeqProcessNextStates.Finished
+ signal.EnumeratorState <- SeqEnumeratorState.Finished
t2u.OnComplete ()
false
interface IEnumerator with
member __.MoveNext () =
- result.SeqState <- SeqProcessNextStates.InProcess
+ signal.EnumeratorState <- SeqEnumeratorState.InProcess
moveNext ()
type InitComposingEnumerable<'T,'U>(count:Nullable, f:int->'T, seqComponentFactory:SeqComponentFactory<'T,'U>) =
@@ -1271,8 +1274,8 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let result, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, seqComponent, result))
+ let signal, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, seqComponent, signal))
override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new InitComposingEnumerable<'T,'V>(count, f, this.FactoryCompose next))
From a9f76259cd2b0d1f4759344156d9301e0e82dcb4 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 06:12:42 +1100
Subject: [PATCH 020/286] Rearranged Enumerator/Enumerable pairs together
---
src/fsharp/FSharp.Core/seq.fs | 160 ++++++++++++++++++----------------
1 file changed, 85 insertions(+), 75 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 9d2342a35ac..d56d658996f 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1046,6 +1046,8 @@ namespace Microsoft.FSharp.Collections
inherit TailSignal<'T>()
member val EnumeratorState = SeqEnumeratorState.NotStarted with get, set
+ // ----- base classes for enumerator/enumerable -----
+
[]
type ComposedEnumerator<'T>(signal:EnumeratorSignal<'T>) =
interface IDisposable with
@@ -1063,73 +1065,6 @@ namespace Microsoft.FSharp.Collections
| SeqEnumeratorState.Finished -> alreadyFinished()
| _ -> signal.Current
- type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
- inherit ComposedEnumerator<'U>(signal)
-
- let rec moveNext () =
- if (not signal.Halted) && source.MoveNext () then
- if t2u.ProcessNext source.Current then
- true
- else
- moveNext ()
- else
- signal.EnumeratorState <- SeqEnumeratorState.Finished
- t2u.OnComplete ()
- false
-
- interface IEnumerator with
- member __.MoveNext () =
- signal.EnumeratorState <- SeqEnumeratorState.InProcess
- moveNext ()
-
- interface IDisposable with
- member __.Dispose() = source.Dispose ()
-
- type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
- inherit ComposedEnumerator<'U>(signal)
-
- let mutable idx = 0
-
- let rec moveNext () =
- if (not signal.Halted) && idx < array.Length then
- idx <- idx+1
- if t2u.ProcessNext array.[idx-1] then
- true
- else
- moveNext ()
- else
- signal.EnumeratorState <- SeqEnumeratorState.Finished
- t2u.OnComplete ()
- false
-
- interface IEnumerator with
- member __.MoveNext () =
- signal.EnumeratorState <- SeqEnumeratorState.InProcess
- moveNext ()
-
- type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
- inherit ComposedEnumerator<'U>(signal)
-
- let mutable list = alist
-
- let rec moveNext current =
- match signal.Halted, current with
- | false, head::tail ->
- if t2u.ProcessNext head then
- list <- tail
- true
- else
- moveNext tail
- | _ ->
- signal.EnumeratorState <- SeqEnumeratorState.Finished
- t2u.OnComplete ()
- false
-
- interface IEnumerator with
- member __.MoveNext () =
- signal.EnumeratorState <- SeqEnumeratorState.InProcess
- moveNext list
-
[]
type ComposableEnumerable<'T> () =
abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
@@ -1155,6 +1090,30 @@ namespace Microsoft.FSharp.Collections
let seqComponent = seqComponentFactory.Create signal (Tail signal)
signal, seqComponent
+ // ----- seq -----
+
+ type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
+
+ let rec moveNext () =
+ if (not signal.Halted) && source.MoveNext () then
+ if t2u.ProcessNext source.Current then
+ true
+ else
+ moveNext ()
+ else
+ signal.EnumeratorState <- SeqEnumeratorState.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ signal.EnumeratorState <- SeqEnumeratorState.InProcess
+ moveNext ()
+
+ interface IDisposable with
+ member __.Dispose() = source.Dispose ()
+
type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
@@ -1171,17 +1130,41 @@ namespace Microsoft.FSharp.Collections
// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
//
// let enumerator = enumerable.GetEnumerator ()
-// let result = Result<'U> ()
+// let signal = TailSignal<'U> ()
//
-// let components = current.Create result (Tail result)
+// let components = seqComponentFactory.Create signal (Tail signal)
//
// let mutable state = initialState
-// while (not result.Halted) && enumerator.MoveNext () do
+// while (not signal.Halted) && enumerator.MoveNext () do
// if components.ProcessNext (enumerator.Current) then
-// state <- folder'.Invoke (state, result.Current)
+// state <- folder'.Invoke (state, signal.Current)
//
// state
+ // ----- array -----
+
+ type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
+
+ let mutable idx = 0
+
+ let rec moveNext () =
+ if (not signal.Halted) && idx < array.Length then
+ idx <- idx+1
+ if t2u.ProcessNext array.[idx-1] then
+ true
+ else
+ moveNext ()
+ else
+ signal.EnumeratorState <- SeqEnumeratorState.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ signal.EnumeratorState <- SeqEnumeratorState.InProcess
+ moveNext ()
+
type SeqArrayEnumerable<'T,'U>(array:array<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
@@ -1198,17 +1181,42 @@ namespace Microsoft.FSharp.Collections
// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
//
// let mutable idx = 0
-// let result = Result<'U> ()
-// let components = current.Create result (Tail result)
+// let signal = TailSignal<'U> ()
+// let components = seqComponentFactory.Create signal (Tail signal)
//
// let mutable state = initialState
-// while (not result.Halted) && idx < array.Length do
+// while (not signal.Halted) && idx < array.Length do
// if components.ProcessNext array.[idx] then
-// state <- folder'.Invoke(state, result.Current)
+// state <- folder'.Invoke(state, signal.Current)
// idx <- idx + 1
//
// state
+ // ----- list -----
+
+ type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
+
+ let mutable list = alist
+
+ let rec moveNext current =
+ match signal.Halted, current with
+ | false, head::tail ->
+ if t2u.ProcessNext head then
+ list <- tail
+ true
+ else
+ moveNext tail
+ | _ ->
+ signal.EnumeratorState <- SeqEnumeratorState.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ signal.EnumeratorState <- SeqEnumeratorState.InProcess
+ moveNext list
+
type SeqListEnumerable<'T,'U>(alist:list<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
@@ -1220,6 +1228,8 @@ namespace Microsoft.FSharp.Collections
override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, this.FactoryCompose next))
+ // ----- init -----
+
// The original implementation of "init" delayed the calculation of Current, and so it was possible
// to do MoveNext without it's value being calculated.
// I can imagine only two scenerios where that is possibly sane, although a simple solution is readily
From 960fa27fbbee1db012b91d908d773a0d696fce69 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 06:32:14 +1100
Subject: [PATCH 021/286] Fix bug in skipping an init seq
---
src/fsharp/FSharp.Core/seq.fs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index d56d658996f..ee0f8728139 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1263,7 +1263,9 @@ namespace Microsoft.FSharp.Collections
// triggered, we stay triggered.
maybeSkipping <- t2u.Skipping ()
- if maybeSkipping || t2u.ProcessNext (f idx) then
+ if maybeSkipping then
+ moveNext ()
+ elif t2u.ProcessNext (f idx) then
true
else
moveNext ()
From 5088eeffeb246bc615c2c898125f0e140664ad12 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 08:19:24 +1100
Subject: [PATCH 022/286] Restoring to last successful build server build
I probably don't have any more time today to bug issues
---
src/fsharp/FSharp.Core/seq.fs | 341 +++++++++++-----------------------
1 file changed, 113 insertions(+), 228 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index ee0f8728139..89b18b6f2db 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -817,73 +817,73 @@ namespace Microsoft.FSharp.Collections
let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #)
let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #)
- type SeqSignal () =
+ type SeqProcessNextStates =
+ | NotStarted = 1
+ | Finished = 2
+ | InProcess = 3
+
+ type Result<'T>() =
let mutable halted = false
+
+ member val SeqState = SeqProcessNextStates.NotStarted with get, set
+
member __.StopFurtherProcessing () = halted <- true
member __.Halted = halted
- type TailSignal<'T> () =
- inherit SeqSignal ()
member val Current = Unchecked.defaultof<'T> with get, set
type [] SeqComponentFactory<'T,'U> () =
- abstract Create<'V> : SeqSignal -> SeqComponent<'U,'V> -> SeqComponent<'T,'V>
+ abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V>
and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) =
inherit SeqComponentFactory<'T,'V> ()
- override __.Create<'W> (signal:SeqSignal) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create signal (second.Create signal next)
+ override __.Create<'W> (result:Result<'W>) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create result (second.Create result next)
and ChooseFactory<'T,'U> (filter:'T->option<'U>) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
and FilterFactory<'T> (filter:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter
and MapFactory<'T,'U> (map:'T->'U) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
and MapiFactory<'T,'U> (mapi:int->'T->'U) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
and PairwiseFactory<'T> () =
inherit SeqComponentFactory<'T,'T*'T> ()
- override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next
and SkipFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
and SkipWhileFactory<'T> (perdicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
and TakeWhileFactory<'T> (perdicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, signal, next)
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, result, next)
and TakeFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, signal, next)
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next)
and [] SeqComponent<'T,'U> () =
abstract ProcessNext : input:'T -> bool
abstract OnComplete : unit -> unit
-
- // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip
- // and it can only do it at the start of a sequence
- abstract Skipping : unit -> bool
abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U>
abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U>
default __.OnComplete () = ()
- default __.Skipping () = false
-
default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this)
default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this)
@@ -964,13 +964,6 @@ namespace Microsoft.FSharp.Collections
let mutable count = 0
- override __.Skipping () =
- if count < skipCount then
- count <- count + 1
- true
- else
- false
-
override __.ProcessNext (input:'T) : bool =
if count < skipCount then
count <- count + 1
@@ -999,7 +992,7 @@ namespace Microsoft.FSharp.Collections
else
Helpers.avoidTailCall (next.ProcessNext input)
- and Take<'T,'V> (takeCount:int, signal:SeqSignal, next:SeqComponent<'T,'V>) =
+ and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
let mutable count = 0
@@ -1008,10 +1001,10 @@ namespace Microsoft.FSharp.Collections
if count < takeCount then
count <- count + 1
if count = takeCount then
- signal.StopFurtherProcessing ()
+ result.StopFurtherProcessing ()
next.ProcessNext input
else
- signal.StopFurtherProcessing ()
+ result.StopFurtherProcessing ()
false
override __.OnComplete () =
@@ -1020,36 +1013,25 @@ namespace Microsoft.FSharp.Collections
invalidOpFmt "tried to take {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- and TakeWhile<'T,'V> (predicate:'T->bool, signal:SeqSignal, next:SeqComponent<'T,'V>) =
+ and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
override __.ProcessNext (input:'T) : bool =
if predicate input then
next.ProcessNext input
else
- signal.StopFurtherProcessing ()
+ result.StopFurtherProcessing ()
false
- and Tail<'T> (signal:TailSignal<'T>) =
+ and Tail<'T> (result:Result<'T>) =
inherit SeqComponent<'T,'T>()
override __.ProcessNext (input:'T) : bool =
- signal.Current <- input
+ result.Current <- input
true
- type SeqEnumeratorState =
- | NotStarted = 1
- | Finished = 2
- | InProcess = 3
-
- type EnumeratorSignal<'T>() =
- inherit TailSignal<'T>()
- member val EnumeratorState = SeqEnumeratorState.NotStarted with get, set
-
- // ----- base classes for enumerator/enumerable -----
-
[]
- type ComposedEnumerator<'T>(signal:EnumeratorSignal<'T>) =
+ type ComposedEnumerator<'T>(result:Result<'T>) =
interface IDisposable with
member __.Dispose() : unit = ()
@@ -1060,147 +1042,62 @@ namespace Microsoft.FSharp.Collections
interface IEnumerator<'T> with
member __.Current =
- match signal.EnumeratorState with
- | SeqEnumeratorState.NotStarted -> notStarted()
- | SeqEnumeratorState.Finished -> alreadyFinished()
- | _ -> signal.Current
-
- []
- type ComposableEnumerable<'T> () =
- abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
-
- interface IEnumerable with
- member this.GetEnumerator () : IEnumerator =
- let genericEnumerable = Helpers.UpcastEnumerable this
- let genericEnumerator = genericEnumerable.GetEnumerator ()
- Helpers.UpcastEnumeratorNonGeneric genericEnumerator
+ match result.SeqState with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> result.Current
- interface IEnumerable<'T> with
- member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
-
- []
- type ComposableEnumerableFactoryHelper<'T,'U> (seqComponentFactory:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerable<'U>()
-
- member __.FactoryCompose next =
- ComposedFactory (seqComponentFactory, next)
-
- member __.CreateSeqComponent () =
- let signal = EnumeratorSignal<'U> ()
- let seqComponent = seqComponentFactory.Create signal (Tail signal)
- signal, seqComponent
-
- // ----- seq -----
-
- type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
- inherit ComposedEnumerator<'U>(signal)
+ type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit ComposedEnumerator<'U>(result)
let rec moveNext () =
- if (not signal.Halted) && source.MoveNext () then
+ if (not result.Halted) && source.MoveNext () then
if t2u.ProcessNext source.Current then
true
else
moveNext ()
else
- signal.EnumeratorState <- SeqEnumeratorState.Finished
+ result.SeqState <- SeqProcessNextStates.Finished
t2u.OnComplete ()
false
interface IEnumerator with
member __.MoveNext () =
- signal.EnumeratorState <- SeqEnumeratorState.InProcess
+ result.SeqState <- SeqProcessNextStates.InProcess
moveNext ()
interface IDisposable with
member __.Dispose() = source.Dispose ()
- type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
-
- interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> =
- let signal, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), seqComponent, signal))
-
- override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, this.FactoryCompose next))
-
-// interface ISeqEnumerable<'U> with
-// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
-// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
-//
-// let enumerator = enumerable.GetEnumerator ()
-// let signal = TailSignal<'U> ()
-//
-// let components = seqComponentFactory.Create signal (Tail signal)
-//
-// let mutable state = initialState
-// while (not signal.Halted) && enumerator.MoveNext () do
-// if components.ProcessNext (enumerator.Current) then
-// state <- folder'.Invoke (state, signal.Current)
-//
-// state
-
- // ----- array -----
-
- type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
- inherit ComposedEnumerator<'U>(signal)
+ type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit ComposedEnumerator<'U>(result)
let mutable idx = 0
let rec moveNext () =
- if (not signal.Halted) && idx < array.Length then
+ if (not result.Halted) && idx < array.Length then
idx <- idx+1
if t2u.ProcessNext array.[idx-1] then
true
else
moveNext ()
else
- signal.EnumeratorState <- SeqEnumeratorState.Finished
+ result.SeqState <- SeqProcessNextStates.Finished
t2u.OnComplete ()
false
interface IEnumerator with
member __.MoveNext () =
- signal.EnumeratorState <- SeqEnumeratorState.InProcess
+ result.SeqState <- SeqProcessNextStates.InProcess
moveNext ()
- type SeqArrayEnumerable<'T,'U>(array:array<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
-
- interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> =
- let signal, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, seqComponent, signal))
-
- override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, this.FactoryCompose next))
-
-// interface ISeqEnumerable<'U> with
-// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
-// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
-//
-// let mutable idx = 0
-// let signal = TailSignal<'U> ()
-// let components = seqComponentFactory.Create signal (Tail signal)
-//
-// let mutable state = initialState
-// while (not signal.Halted) && idx < array.Length do
-// if components.ProcessNext array.[idx] then
-// state <- folder'.Invoke(state, signal.Current)
-// idx <- idx + 1
-//
-// state
-
- // ----- list -----
-
- type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
- inherit ComposedEnumerator<'U>(signal)
+ type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit ComposedEnumerator<'U>(result)
let mutable list = alist
let rec moveNext current =
- match signal.Halted, current with
+ match result.Halted, current with
| false, head::tail ->
if t2u.ProcessNext head then
list <- tail
@@ -1208,102 +1105,92 @@ namespace Microsoft.FSharp.Collections
else
moveNext tail
| _ ->
- signal.EnumeratorState <- SeqEnumeratorState.Finished
+ result.SeqState <- SeqProcessNextStates.Finished
t2u.OnComplete ()
false
interface IEnumerator with
member __.MoveNext () =
- signal.EnumeratorState <- SeqEnumeratorState.InProcess
+ result.SeqState <- SeqProcessNextStates.InProcess
moveNext list
- type SeqListEnumerable<'T,'U>(alist:list<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
+ []
+ type ComposableEnumerable<'T> () =
+ abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
+
+ interface IEnumerable with
+ member this.GetEnumerator () : IEnumerator =
+ let genericEnumerable = Helpers.UpcastEnumerable this
+ let genericEnumerator = genericEnumerable.GetEnumerator ()
+ Helpers.UpcastEnumeratorNonGeneric genericEnumerator
+
+ interface IEnumerable<'T> with
+ member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
+
+ type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerable<'U>()
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let signal, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, seqComponent, signal))
-
- override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, this.FactoryCompose next))
-
- // ----- init -----
-
- // The original implementation of "init" delayed the calculation of Current, and so it was possible
- // to do MoveNext without it's value being calculated.
- // I can imagine only two scenerios where that is possibly sane, although a simple solution is readily
- // at hand in both cases. The first is that of an expensive generator function, where you skip the
- // first n elements. The simple solution would have just been to have a map ((+) n) as the first operation
- // instead. The second case would be counting elements, but that is only of use if you're not filtering
- // or mapping or doing anything else (as that would cause Current to be evaluated!) and
- // so you already know what the count is!! Anyway, someone thought it was a good idea, so
- // I have had to add an extra function that is used in Skip to determine if we are touching
- // Current or not.
- type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
- inherit ComposedEnumerator<'U>(signal)
-
- // we are offset by 1 to allow for values going up to System.Int32.MaxValue
- // System.Int32.MaxValue is an illegal value for the "infinite" sequence
- let terminatingIdx =
- if count.HasValue then
- count.Value - 1
- else
- System.Int32.MaxValue
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result))
- let mutable maybeSkipping = true
- let mutable idx = -1
-
- let rec moveNext () =
- if (not signal.Halted) && idx < terminatingIdx then
- idx <- idx + 1
-
- if maybeSkipping then
- // Skip can only is only checked at the start of the sequence, so once
- // triggered, we stay triggered.
- maybeSkipping <- t2u.Skipping ()
-
- if maybeSkipping then
- moveNext ()
- elif t2u.ProcessNext (f idx) then
- true
- else
- moveNext ()
- elif (not signal.Halted) && idx = System.Int32.MaxValue then
- raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue))
- else
- signal.EnumeratorState <- SeqEnumeratorState.Finished
- t2u.OnComplete ()
- false
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, ComposedFactory (current, next)))
- interface IEnumerator with
- member __.MoveNext () =
- signal.EnumeratorState <- SeqEnumeratorState.InProcess
- moveNext ()
+// interface ISeqEnumerable<'U> with
+// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+//
+// let enumerator = enumerable.GetEnumerator ()
+// let result = Result<'U> ()
+//
+// let components = current.Create result (Tail result)
+//
+// let mutable state = initialState
+// while (not result.Halted) && enumerator.MoveNext () do
+// if components.ProcessNext (enumerator.Current) then
+// state <- folder'.Invoke (state, result.Current)
+//
+// state
- type InitComposingEnumerable<'T,'U>(count:Nullable, f:int->'T, seqComponentFactory:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
+ type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerable<'U>()
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let signal, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, seqComponent, signal))
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result))
- override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new InitComposingEnumerable<'T,'V>(count, f, this.FactoryCompose next))
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, ComposedFactory (current, next)))
- type InitEnumerable<'T>(count:Nullable, f:int->'T) =
- inherit ComposableEnumerable<'T>()
+// interface ISeqEnumerable<'U> with
+// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+//
+// let mutable idx = 0
+// let result = Result<'U> ()
+// let components = current.Create result (Tail result)
+//
+// let mutable state = initialState
+// while (not result.Halted) && idx < array.Length do
+// if components.ProcessNext array.[idx] then
+// state <- folder'.Invoke(state, result.Current)
+// idx <- idx + 1
+//
+// state
- interface IEnumerable<'T> with
- member this.GetEnumerator () : IEnumerator<'T> =
- // we defer back to the original implementation as, as it's quite idiomatic in it's decision
- // to calculate Current in a lazy fashion. I doubt anyone is really using this functionality
- // in the way presented, but it's possible.
- upto (if count.HasValue then Some count.Value else None) f
+ type SeqListEnumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerable<'U>()
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result))
- override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
- Helpers.UpcastEnumerable (InitComposingEnumerable<'T,'V>(count, f, next))
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next)))
#if FX_NO_ICLONEABLE
@@ -1327,14 +1214,12 @@ namespace Microsoft.FSharp.Collections
let empty<'T> = (EmptyEnumerable :> seq<'T>)
[]
- let initInfinite<'T> (f:int->'T) : IEnumerable<'T> =
- SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable (), f))
+ let initInfinite f = mkSeq (fun () -> IEnumerator.upto None f)
[]
let init count f =
if count < 0 then invalidArgInputMustBeNonNegative "count" count
- elif count = 0 then empty else
- SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable count, f))
+ mkSeq (fun () -> IEnumerator.upto (Some (count-1)) f)
[]
let iter f (source : seq<'T>) =
From 60fc2a1f3a7b6d28e03a89c9ed568020153e71b3 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 13:32:57 +1100
Subject: [PATCH 023/286] init/initInfinite
Try again, without any other clutter
---
src/fsharp/FSharp.Core/seq.fs | 97 +++++++++++++++++++++++++++++++++--
1 file changed, 94 insertions(+), 3 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 89b18b6f2db..027cdbbd5bf 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -879,11 +879,17 @@ namespace Microsoft.FSharp.Collections
abstract ProcessNext : input:'T -> bool
abstract OnComplete : unit -> unit
+ // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip
+ // and it can only do it at the start of a sequence
+ abstract Skipping : unit -> bool
+
abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U>
abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U>
default __.OnComplete () = ()
+ default __.Skipping () = false
+
default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this)
default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this)
@@ -964,6 +970,13 @@ namespace Microsoft.FSharp.Collections
let mutable count = 0
+ override __.Skipping () =
+ if count < skipCount then
+ count <- count + 1
+ true
+ else
+ false
+
override __.ProcessNext (input:'T) : bool =
if count < skipCount then
count <- count + 1
@@ -1193,6 +1206,82 @@ namespace Microsoft.FSharp.Collections
Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next)))
+ // The original implementation of "init" delayed the calculation of Current, and so it was possible
+ // to do MoveNext without it's value being calculated.
+ // I can imagine only two scenerios where that is possibly sane, although a simple solution is readily
+ // at hand in both cases. The first is that of an expensive generator function, where you skip the
+ // first n elements. The simple solution would have just been to have a map ((+) n) as the first operation
+ // instead. The second case would be counting elements, but that is only of use if you're not filtering
+ // or mapping or doing anything else (as that would cause Current to be evaluated!) and
+ // so you already know what the count is!! Anyway, someone thought it was a good idea, so
+ // I have had to add an extra function that is used in Skip to determine if we are touching
+ // Current or not.
+ type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:Result<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
+
+ // we are offset by 1 to allow for values going up to System.Int32.MaxValue
+ // System.Int32.MaxValue is an illegal value for the "infinite" sequence
+ let terminatingIdx =
+ if count.HasValue then
+ count.Value - 1
+ else
+ System.Int32.MaxValue
+
+ let mutable maybeSkipping = true
+ let mutable idx = -1
+
+ let rec moveNext () =
+ if (not signal.Halted) && idx < terminatingIdx then
+ idx <- idx + 1
+
+ if maybeSkipping then
+ // Skip can only is only checked at the start of the sequence, so once
+ // triggered, we stay triggered.
+ maybeSkipping <- t2u.Skipping ()
+
+ if maybeSkipping then
+ moveNext ()
+ elif t2u.ProcessNext (f idx) then
+ true
+ else
+ moveNext ()
+ elif (not signal.Halted) && idx = System.Int32.MaxValue then
+ raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue))
+ else
+ signal.SeqState <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ signal.SeqState <- SeqProcessNextStates.InProcess
+ moveNext ()
+
+ type InitComposingEnumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerable<'U>()
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, current.Create result (Tail result), result))
+
+ override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new InitComposingEnumerable<'T,'V>(count, f, ComposedFactory (current, next)))
+
+
+ type InitEnumerable<'T>(count:Nullable, f:int->'T) =
+ inherit ComposableEnumerable<'T>()
+
+ interface IEnumerable<'T> with
+ member this.GetEnumerator () : IEnumerator<'T> =
+ // we defer back to the original implementation as, as it's quite idiomatic in it's decision
+ // to calculate Current in a lazy fashion. I doubt anyone is really using this functionality
+ // in the way presented, but it's possible.
+ upto (if count.HasValue then Some count.Value else None) f
+
+ override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
+ Helpers.UpcastEnumerable (InitComposingEnumerable<'T,'V>(count, f, next))
+
#if FX_NO_ICLONEABLE
open Microsoft.FSharp.Core.ICloneableExtensions
#else
@@ -1214,12 +1303,14 @@ namespace Microsoft.FSharp.Collections
let empty<'T> = (EmptyEnumerable :> seq<'T>)
[]
- let initInfinite f = mkSeq (fun () -> IEnumerator.upto None f)
+ let initInfinite<'T> (f:int->'T) : IEnumerable<'T> =
+ SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable (), f))
[]
- let init count f =
+ let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> =
if count < 0 then invalidArgInputMustBeNonNegative "count" count
- mkSeq (fun () -> IEnumerator.upto (Some (count-1)) f)
+ elif count = 0 then empty else
+ SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable count, f))
[]
let iter f (source : seq<'T>) =
From 848593f7e0083b2284a71c0bd4e3d380b375f548 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 14:12:59 +1100
Subject: [PATCH 024/286] Bug fix; off by 1...
---
src/fsharp/FSharp.Core/seq.fs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 027cdbbd5bf..c34a370e500 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1277,7 +1277,7 @@ namespace Microsoft.FSharp.Collections
// we defer back to the original implementation as, as it's quite idiomatic in it's decision
// to calculate Current in a lazy fashion. I doubt anyone is really using this functionality
// in the way presented, but it's possible.
- upto (if count.HasValue then Some count.Value else None) f
+ upto (if count.HasValue then Some (count.Value-1) else None) f
override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
Helpers.UpcastEnumerable (InitComposingEnumerable<'T,'V>(count, f, next))
From 78a13664c54bba25d1aa86e0cca41f843c384217 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 16:29:19 +1100
Subject: [PATCH 025/286] Moved Enumerable/Enumerator pairs into modules
---
src/fsharp/FSharp.Core/seq.fs | 441 +++++++++++++++++-----------------
1 file changed, 223 insertions(+), 218 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index c34a370e500..39c3a0fdbb5 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1043,244 +1043,249 @@ namespace Microsoft.FSharp.Collections
result.Current <- input
true
- []
- type ComposedEnumerator<'T>(result:Result<'T>) =
- interface IDisposable with
- member __.Dispose() : unit = ()
-
- interface IEnumerator with
- member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current
- member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)"
- member __.Reset () : unit = noReset ()
-
- interface IEnumerator<'T> with
- member __.Current =
- match result.SeqState with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> result.Current
-
- type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit ComposedEnumerator<'U>(result)
-
- let rec moveNext () =
- if (not result.Halted) && source.MoveNext () then
- if t2u.ProcessNext source.Current then
- true
+ module Base =
+ []
+ type Enumerator<'T>(result:Result<'T>) =
+ interface IDisposable with
+ member __.Dispose() : unit = ()
+
+ interface IEnumerator with
+ member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current
+ member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)"
+ member __.Reset () : unit = noReset ()
+
+ interface IEnumerator<'T> with
+ member __.Current =
+ match result.SeqState with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> result.Current
+
+
+ []
+ type Enumerable<'T> () =
+ abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
+
+ interface IEnumerable with
+ member this.GetEnumerator () : IEnumerator =
+ let genericEnumerable = Helpers.UpcastEnumerable this
+ let genericEnumerator = genericEnumerable.GetEnumerator ()
+ Helpers.UpcastEnumeratorNonGeneric genericEnumerator
+
+ interface IEnumerable<'T> with
+ member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
+
+ module Enumerable =
+ type Enumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit Base.Enumerator<'U>(result)
+
+ let rec moveNext () =
+ if (not result.Halted) && source.MoveNext () then
+ if t2u.ProcessNext source.Current then
+ true
+ else
+ moveNext ()
else
+ result.SeqState <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ result.SeqState <- SeqProcessNextStates.InProcess
moveNext ()
- else
- result.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
- false
- interface IEnumerator with
- member __.MoveNext () =
- result.SeqState <- SeqProcessNextStates.InProcess
- moveNext ()
+ interface IDisposable with
+ member __.Dispose() = source.Dispose ()
- interface IDisposable with
- member __.Dispose() = source.Dispose ()
- type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit ComposedEnumerator<'U>(result)
+ type Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
+ inherit Base.Enumerable<'U>()
- let mutable idx = 0
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result))
- let rec moveNext () =
- if (not result.Halted) && idx < array.Length then
- idx <- idx+1
- if t2u.ProcessNext array.[idx-1] then
- true
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory (current, next)))
+
+ // interface ISeqEnumerable<'U> with
+ // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+ //
+ // let enumerator = enumerable.GetEnumerator ()
+ // let result = Result<'U> ()
+ //
+ // let components = current.Create result (Tail result)
+ //
+ // let mutable state = initialState
+ // while (not result.Halted) && enumerator.MoveNext () do
+ // if components.ProcessNext (enumerator.Current) then
+ // state <- folder'.Invoke (state, result.Current)
+ //
+ // state
+
+ module Array =
+ type Enumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit Base.Enumerator<'U>(result)
+
+ let mutable idx = 0
+
+ let rec moveNext () =
+ if (not result.Halted) && idx < array.Length then
+ idx <- idx+1
+ if t2u.ProcessNext array.[idx-1] then
+ true
+ else
+ moveNext ()
else
+ result.SeqState <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ result.SeqState <- SeqProcessNextStates.InProcess
moveNext ()
- else
- result.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
- false
- interface IEnumerator with
- member __.MoveNext () =
- result.SeqState <- SeqProcessNextStates.InProcess
- moveNext ()
+ type Enumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) =
+ inherit Base.Enumerable<'U>()
- type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit ComposedEnumerator<'U>(result)
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail result), result))
- let mutable list = alist
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory (current, next)))
- let rec moveNext current =
- match result.Halted, current with
- | false, head::tail ->
- if t2u.ProcessNext head then
- list <- tail
- true
- else
- moveNext tail
- | _ ->
- result.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
- false
+ // interface ISeqEnumerable<'U> with
+ // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+ //
+ // let mutable idx = 0
+ // let result = Result<'U> ()
+ // let components = current.Create result (Tail result)
+ //
+ // let mutable state = initialState
+ // while (not result.Halted) && idx < array.Length do
+ // if components.ProcessNext array.[idx] then
+ // state <- folder'.Invoke(state, result.Current)
+ // idx <- idx + 1
+ //
+ // state
- interface IEnumerator with
- member __.MoveNext () =
- result.SeqState <- SeqProcessNextStates.InProcess
- moveNext list
-
- []
- type ComposableEnumerable<'T> () =
- abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
-
- interface IEnumerable with
- member this.GetEnumerator () : IEnumerator =
- let genericEnumerable = Helpers.UpcastEnumerable this
- let genericEnumerator = genericEnumerable.GetEnumerator ()
- Helpers.UpcastEnumeratorNonGeneric genericEnumerator
-
- interface IEnumerable<'T> with
- member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
-
- type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerable<'U>()
-
- interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result))
-
- override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, ComposedFactory (current, next)))
-
-// interface ISeqEnumerable<'U> with
-// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
-// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
-//
-// let enumerator = enumerable.GetEnumerator ()
-// let result = Result<'U> ()
-//
-// let components = current.Create result (Tail result)
-//
-// let mutable state = initialState
-// while (not result.Halted) && enumerator.MoveNext () do
-// if components.ProcessNext (enumerator.Current) then
-// state <- folder'.Invoke (state, result.Current)
-//
-// state
-
- type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerable<'U>()
-
- interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result))
-
- override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, ComposedFactory (current, next)))
-
-// interface ISeqEnumerable<'U> with
-// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
-// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
-//
-// let mutable idx = 0
-// let result = Result<'U> ()
-// let components = current.Create result (Tail result)
-//
-// let mutable state = initialState
-// while (not result.Halted) && idx < array.Length do
-// if components.ProcessNext array.[idx] then
-// state <- folder'.Invoke(state, result.Current)
-// idx <- idx + 1
-//
-// state
-
- type SeqListEnumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerable<'U>()
-
- interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result))
-
- override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next)))
-
-
- // The original implementation of "init" delayed the calculation of Current, and so it was possible
- // to do MoveNext without it's value being calculated.
- // I can imagine only two scenerios where that is possibly sane, although a simple solution is readily
- // at hand in both cases. The first is that of an expensive generator function, where you skip the
- // first n elements. The simple solution would have just been to have a map ((+) n) as the first operation
- // instead. The second case would be counting elements, but that is only of use if you're not filtering
- // or mapping or doing anything else (as that would cause Current to be evaluated!) and
- // so you already know what the count is!! Anyway, someone thought it was a good idea, so
- // I have had to add an extra function that is used in Skip to determine if we are touching
- // Current or not.
- type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:Result<'U>) =
- inherit ComposedEnumerator<'U>(signal)
-
- // we are offset by 1 to allow for values going up to System.Int32.MaxValue
- // System.Int32.MaxValue is an illegal value for the "infinite" sequence
- let terminatingIdx =
- if count.HasValue then
- count.Value - 1
- else
- System.Int32.MaxValue
+ module List =
+ type Enumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit Base.Enumerator<'U>(result)
- let mutable maybeSkipping = true
- let mutable idx = -1
+ let mutable list = alist
- let rec moveNext () =
- if (not signal.Halted) && idx < terminatingIdx then
- idx <- idx + 1
+ let rec moveNext current =
+ match result.Halted, current with
+ | false, head::tail ->
+ if t2u.ProcessNext head then
+ list <- tail
+ true
+ else
+ moveNext tail
+ | _ ->
+ result.SeqState <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
- if maybeSkipping then
- // Skip can only is only checked at the start of the sequence, so once
- // triggered, we stay triggered.
- maybeSkipping <- t2u.Skipping ()
-
- if maybeSkipping then
- moveNext ()
- elif t2u.ProcessNext (f idx) then
- true
+ interface IEnumerator with
+ member __.MoveNext () =
+ result.SeqState <- SeqProcessNextStates.InProcess
+ moveNext list
+
+ type Enumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) =
+ inherit Base.Enumerable<'U>()
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail result), result))
+
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory (current, next)))
+
+ module Init =
+ // The original implementation of "init" delayed the calculation of Current, and so it was possible
+ // to do MoveNext without it's value being calculated.
+ // I can imagine only two scenerios where that is possibly sane, although a simple solution is readily
+ // at hand in both cases. The first is that of an expensive generator function, where you skip the
+ // first n elements. The simple solution would have just been to have a map ((+) n) as the first operation
+ // instead. The second case would be counting elements, but that is only of use if you're not filtering
+ // or mapping or doing anything else (as that would cause Current to be evaluated!) and
+ // so you already know what the count is!! Anyway, someone thought it was a good idea, so
+ // I have had to add an extra function that is used in Skip to determine if we are touching
+ // Current or not.
+ type Enumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:Result<'U>) =
+ inherit Base.Enumerator<'U>(signal)
+
+ // we are offset by 1 to allow for values going up to System.Int32.MaxValue
+ // System.Int32.MaxValue is an illegal value for the "infinite" sequence
+ let terminatingIdx =
+ if count.HasValue then
+ count.Value - 1
else
- moveNext ()
- elif (not signal.Halted) && idx = System.Int32.MaxValue then
- raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue))
- else
- signal.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
- false
+ System.Int32.MaxValue
- interface IEnumerator with
- member __.MoveNext () =
- signal.SeqState <- SeqProcessNextStates.InProcess
- moveNext ()
+ let mutable maybeSkipping = true
+ let mutable idx = -1
+
+ let rec moveNext () =
+ if (not signal.Halted) && idx < terminatingIdx then
+ idx <- idx + 1
- type InitComposingEnumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerable<'U>()
+ if maybeSkipping then
+ // Skip can only is only checked at the start of the sequence, so once
+ // triggered, we stay triggered.
+ maybeSkipping <- t2u.Skipping ()
+
+ if maybeSkipping then
+ moveNext ()
+ elif t2u.ProcessNext (f idx) then
+ true
+ else
+ moveNext ()
+ elif (not signal.Halted) && idx = System.Int32.MaxValue then
+ raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue))
+ else
+ signal.SeqState <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ signal.SeqState <- SeqProcessNextStates.InProcess
+ moveNext ()
- interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, current.Create result (Tail result), result))
+ type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) =
+ inherit Base.Enumerable<'U>()
- override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new InitComposingEnumerable<'T,'V>(count, f, ComposedFactory (current, next)))
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail result), result))
+ override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next)))
- type InitEnumerable<'T>(count:Nullable, f:int->'T) =
- inherit ComposableEnumerable<'T>()
+ type EnumerableDecider<'T>(count:Nullable, f:int->'T) =
+ inherit Base.Enumerable<'T>()
- interface IEnumerable<'T> with
- member this.GetEnumerator () : IEnumerator<'T> =
- // we defer back to the original implementation as, as it's quite idiomatic in it's decision
- // to calculate Current in a lazy fashion. I doubt anyone is really using this functionality
- // in the way presented, but it's possible.
- upto (if count.HasValue then Some (count.Value-1) else None) f
+ interface IEnumerable<'T> with
+ member this.GetEnumerator () : IEnumerator<'T> =
+ // we defer back to the original implementation as, as it's quite idiomatic in it's decision
+ // to calculate Current in a lazy fashion. I doubt anyone is really using this functionality
+ // in the way presented, but it's possible.
+ upto (if count.HasValue then Some (count.Value-1) else None) f
- override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
- Helpers.UpcastEnumerable (InitComposingEnumerable<'T,'V>(count, f, next))
+ override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
+ Helpers.UpcastEnumerable (Enumerable<'T,'V>(count, f, next))
#if FX_NO_ICLONEABLE
open Microsoft.FSharp.Core.ICloneableExtensions
@@ -1304,13 +1309,13 @@ namespace Microsoft.FSharp.Collections
[]
let initInfinite<'T> (f:int->'T) : IEnumerable<'T> =
- SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable (), f))
+ SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable (), f))
[]
let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> =
if count < 0 then invalidArgInputMustBeNonNegative "count" count
elif count = 0 then empty else
- SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable count, f))
+ SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable count, f))
[]
let iter f (source : seq<'T>) =
@@ -1406,10 +1411,10 @@ namespace Microsoft.FSharp.Collections
let private seqFactory createSeqComponent (source:seq<'T>) =
checkNonNull "source" source
match source with
- | :? SeqComposer.ComposableEnumerable<'T> as s -> s.Compose createSeqComponent
- | :? array<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent))
- | :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent))
- | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent))
+ | :? SeqComposer.Base.Enumerable<'T> as s -> s.Compose createSeqComponent
+ | :? array<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Array.Enumerable<_,_>(a, createSeqComponent))
+ | :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.List.Enumerable<_,_>(a, createSeqComponent))
+ | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Enumerable.Enumerable<_,_>(source, createSeqComponent))
[]
let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> =
From b88dd4e5a4d3d56a5c7b8b247092d0393d06e989 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 19:09:42 +1100
Subject: [PATCH 026/286] map2
---
src/fsharp/FSharp.Core/seq.fs | 65 ++++++++++++++++++++++++-----------
1 file changed, 44 insertions(+), 21 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 39c3a0fdbb5..3fb1ed974af 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -108,25 +108,6 @@ namespace Microsoft.FSharp.Collections
interface System.IDisposable with
member this.Dispose() = this.Dispose()
- let map2 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) : IEnumerator<_>=
- let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
- upcast
- { new MapEnumerator<_>() with
- member this.DoMoveNext curr =
- let n1 = e1.MoveNext()
- let n2 = e2.MoveNext()
- if n1 && n2 then
- curr <- f.Invoke(e1.Current, e2.Current)
- true
- else
- false
- member this.Dispose() =
- try
- e1.Dispose()
- finally
- e2.Dispose()
- }
-
let mapi2 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) : IEnumerator<_> =
let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f)
let i = ref (-1)
@@ -851,6 +832,14 @@ namespace Microsoft.FSharp.Collections
inherit SeqComponentFactory<'T,'U> ()
override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
+ and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) =
+ inherit SeqComponentFactory<'First,'U> ()
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map2First (map, input2, result, next)
+
+ and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) =
+ inherit SeqComponentFactory<'Second,'U> ()
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'Second,'V> = upcast Map2Second (map, input1, result, next)
+
and MapiFactory<'T,'U> (mapi:int->'T->'U) =
inherit SeqComponentFactory<'T,'U> ()
override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
@@ -929,6 +918,38 @@ namespace Microsoft.FSharp.Collections
override __.ProcessNext (input:'T) : bool =
Helpers.avoidTailCall (next.ProcessNext (map input))
+ and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'First,'V>()
+
+ let input2 = enumerable2.GetEnumerator ()
+ let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map
+
+ override __.ProcessNext (input:'First) : bool =
+ if input2.MoveNext () then
+ Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current)))
+ else
+ result.StopFurtherProcessing ()
+ false
+
+ override __.OnComplete () =
+ input2.Dispose ()
+
+ and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'Second,'V>()
+
+ let input1 = enumerable1.GetEnumerator ()
+ let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map
+
+ override __.ProcessNext (input:'Second) : bool =
+ if input1.MoveNext () then
+ Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input)))
+ else
+ result.StopFurtherProcessing ()
+ false
+
+ override __.OnComplete () =
+ input1.Dispose ()
+
and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>()
@@ -1438,10 +1459,12 @@ namespace Microsoft.FSharp.Collections
revamp2 (IEnumerator.mapi2 f) source1 source2
[]
- let map2 f source1 source2 =
+ let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> =
checkNonNull "source1" source1
checkNonNull "source2" source2
- revamp2 (IEnumerator.map2 f) source1 source2
+ match source1 with
+ | :? SeqComposer.Base.Enumerable<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2))
+ | _ -> source2 |> seqFactory (SeqComposer.Map2SecondFactory (f, source1))
[]
let map3 f source1 source2 source3 =
From 2f91fb3997577628328221dc577fec52c9b90e84 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 19:29:55 +1100
Subject: [PATCH 027/286] Fix OnComplete/OnDispose
Hmmm... not 100% happy with this because it requires all links in the
chain to ensure that that follow the protocol, but it isn't too bad I
guess...
---
src/fsharp/FSharp.Core/seq.fs | 125 ++++++++++++++++++++--------------
1 file changed, 73 insertions(+), 52 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 3fb1ed974af..ce9cdd1dc04 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -785,6 +785,10 @@ namespace Microsoft.FSharp.Collections
module SeqComposer =
open IEnumerator
+ type ISeqComponent =
+ abstract OnComplete : unit -> unit
+ abstract OnDispose : unit -> unit
+
module Helpers =
// used for performance reasons; these are not recursive calls, so should be safe
let inline avoidTailCall x =
@@ -797,6 +801,7 @@ namespace Microsoft.FSharp.Collections
let inline UpcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #)
let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #)
let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #)
+ let inline UpcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #)
type SeqProcessNextStates =
| NotStarted = 1
@@ -813,6 +818,11 @@ namespace Microsoft.FSharp.Collections
member val Current = Unchecked.defaultof<'T> with get, set
+ let seqComponentTail =
+ { new ISeqComponent with
+ member __.OnComplete() = ()
+ member __.OnDispose() = () }
+
type [] SeqComponentFactory<'T,'U> () =
abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V>
@@ -864,9 +874,8 @@ namespace Microsoft.FSharp.Collections
inherit SeqComponentFactory<'T,'T> ()
override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next)
- and [] SeqComponent<'T,'U> () =
+ and [] SeqComponent<'T,'U> (next:ISeqComponent) =
abstract ProcessNext : input:'T -> bool
- abstract OnComplete : unit -> unit
// Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip
// and it can only do it at the start of a sequence
@@ -875,7 +884,9 @@ namespace Microsoft.FSharp.Collections
abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U>
abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U>
- default __.OnComplete () = ()
+ interface ISeqComponent with
+ member __.OnComplete () = next.OnComplete ()
+ member __.OnDispose () = next.OnDispose ()
default __.Skipping () = false
@@ -883,7 +894,7 @@ namespace Microsoft.FSharp.Collections
default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this)
and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
override __.ProcessNext (input:'T) : bool =
match choose input with
@@ -891,7 +902,7 @@ namespace Microsoft.FSharp.Collections
| None -> false
and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next)
@@ -902,7 +913,7 @@ namespace Microsoft.FSharp.Collections
false
and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
override __.ProcessNext (input:'T) : bool =
if filter input then
@@ -911,7 +922,7 @@ namespace Microsoft.FSharp.Collections
false
and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next)
@@ -919,7 +930,7 @@ namespace Microsoft.FSharp.Collections
Helpers.avoidTailCall (next.ProcessNext (map input))
and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'First,'V>()
+ inherit SeqComponent<'First,'V>(next)
let input2 = enumerable2.GetEnumerator ()
let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map
@@ -931,11 +942,13 @@ namespace Microsoft.FSharp.Collections
result.StopFurtherProcessing ()
false
- override __.OnComplete () =
- input2.Dispose ()
+ interface ISeqComponent with
+ override __.OnDispose () =
+ input2.Dispose ()
+ (Helpers.UpcastISeqComponent next).OnDispose ()
and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'Second,'V>()
+ inherit SeqComponent<'Second,'V>(next)
let input1 = enumerable1.GetEnumerator ()
let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map
@@ -947,11 +960,13 @@ namespace Microsoft.FSharp.Collections
result.StopFurtherProcessing ()
false
- override __.OnComplete () =
- input1.Dispose ()
+ interface ISeqComponent with
+ override __.OnDispose () =
+ input1.Dispose ()
+ (Helpers.UpcastISeqComponent next).OnDispose ()
and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
override __.ProcessNext (input:'T) : bool =
let u = map input
@@ -961,7 +976,7 @@ namespace Microsoft.FSharp.Collections
false
and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
let mutable idx = 0
let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi
@@ -971,7 +986,7 @@ namespace Microsoft.FSharp.Collections
Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input)))
and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
let mutable isFirst = true
let mutable lastValue = Unchecked.defaultof<'T>
@@ -987,7 +1002,7 @@ namespace Microsoft.FSharp.Collections
Helpers.avoidTailCall (next.ProcessNext currentPair)
and Skip<'T,'V> (skipCount:int, next:SeqComponent<'T,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
let mutable count = 0
@@ -1005,14 +1020,16 @@ namespace Microsoft.FSharp.Collections
else
Helpers.avoidTailCall (next.ProcessNext input)
- override __.OnComplete () =
- if count < skipCount then
- let x = skipCount - count
- invalidOpFmt "tried to skip {0} {1} past the end of the seq"
- [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+ interface ISeqComponent with
+ override __.OnComplete () =
+ if count < skipCount then
+ let x = skipCount - count
+ invalidOpFmt "tried to skip {0} {1} past the end of the seq"
+ [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+ (Helpers.UpcastISeqComponent next).OnComplete ()
and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
let mutable skip = true
@@ -1027,7 +1044,7 @@ namespace Microsoft.FSharp.Collections
Helpers.avoidTailCall (next.ProcessNext input)
and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
let mutable count = 0
@@ -1041,14 +1058,16 @@ namespace Microsoft.FSharp.Collections
result.StopFurtherProcessing ()
false
- override __.OnComplete () =
- if count < takeCount then
- let x = takeCount - count
- invalidOpFmt "tried to take {0} {1} past the end of the seq"
- [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+ interface ISeqComponent with
+ override __.OnComplete () =
+ if count < takeCount then
+ let x = takeCount - count
+ invalidOpFmt "tried to take {0} {1} past the end of the seq"
+ [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+ (Helpers.UpcastISeqComponent next).OnComplete ()
and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
override __.ProcessNext (input:'T) : bool =
if predicate input then
@@ -1058,7 +1077,7 @@ namespace Microsoft.FSharp.Collections
false
and Tail<'T> (result:Result<'T>) =
- inherit SeqComponent<'T,'T>()
+ inherit SeqComponent<'T,'T>(seqComponentTail)
override __.ProcessNext (input:'T) : bool =
result.Current <- input
@@ -1066,9 +1085,10 @@ namespace Microsoft.FSharp.Collections
module Base =
[]
- type Enumerator<'T>(result:Result<'T>) =
+ type Enumerator<'T>(result:Result<'T>, seqComponent:ISeqComponent) =
interface IDisposable with
- member __.Dispose() : unit = ()
+ member __.Dispose() : unit =
+ seqComponent.OnDispose ()
interface IEnumerator with
member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current
@@ -1097,18 +1117,18 @@ namespace Microsoft.FSharp.Collections
member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
module Enumerable =
- type Enumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit Base.Enumerator<'U>(result)
+ type Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit Base.Enumerator<'U>(result, seqComponent)
let rec moveNext () =
if (not result.Halted) && source.MoveNext () then
- if t2u.ProcessNext source.Current then
+ if seqComponent.ProcessNext source.Current then
true
else
moveNext ()
else
result.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
+ (Helpers.UpcastISeqComponent seqComponent).OnComplete ()
false
interface IEnumerator with
@@ -1117,8 +1137,9 @@ namespace Microsoft.FSharp.Collections
moveNext ()
interface IDisposable with
- member __.Dispose() = source.Dispose ()
-
+ member __.Dispose() =
+ source.Dispose ()
+ (Helpers.UpcastISeqComponent seqComponent).OnDispose ()
type Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
inherit Base.Enumerable<'U>()
@@ -1148,21 +1169,21 @@ namespace Microsoft.FSharp.Collections
// state
module Array =
- type Enumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit Base.Enumerator<'U>(result)
+ type Enumerator<'T,'U>(array:array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit Base.Enumerator<'U>(result, seqComponent)
let mutable idx = 0
let rec moveNext () =
if (not result.Halted) && idx < array.Length then
idx <- idx+1
- if t2u.ProcessNext array.[idx-1] then
+ if seqComponent.ProcessNext array.[idx-1] then
true
else
moveNext ()
else
result.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
+ (Helpers.UpcastISeqComponent seqComponent).OnComplete ()
false
interface IEnumerator with
@@ -1198,22 +1219,22 @@ namespace Microsoft.FSharp.Collections
// state
module List =
- type Enumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit Base.Enumerator<'U>(result)
+ type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit Base.Enumerator<'U>(result, seqComponent)
let mutable list = alist
let rec moveNext current =
match result.Halted, current with
| false, head::tail ->
- if t2u.ProcessNext head then
+ if seqComponent.ProcessNext head then
list <- tail
true
else
moveNext tail
| _ ->
result.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
+ (Helpers.UpcastISeqComponent seqComponent).OnComplete ()
false
interface IEnumerator with
@@ -1243,8 +1264,8 @@ namespace Microsoft.FSharp.Collections
// so you already know what the count is!! Anyway, someone thought it was a good idea, so
// I have had to add an extra function that is used in Skip to determine if we are touching
// Current or not.
- type Enumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:Result<'U>) =
- inherit Base.Enumerator<'U>(signal)
+ type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) =
+ inherit Base.Enumerator<'U>(signal, seqComponent)
// we are offset by 1 to allow for values going up to System.Int32.MaxValue
// System.Int32.MaxValue is an illegal value for the "infinite" sequence
@@ -1264,11 +1285,11 @@ namespace Microsoft.FSharp.Collections
if maybeSkipping then
// Skip can only is only checked at the start of the sequence, so once
// triggered, we stay triggered.
- maybeSkipping <- t2u.Skipping ()
+ maybeSkipping <- seqComponent.Skipping ()
if maybeSkipping then
moveNext ()
- elif t2u.ProcessNext (f idx) then
+ elif seqComponent.ProcessNext (f idx) then
true
else
moveNext ()
@@ -1276,7 +1297,7 @@ namespace Microsoft.FSharp.Collections
raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue))
else
signal.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
+ (Helpers.UpcastISeqComponent seqComponent).OnComplete ()
false
interface IEnumerator with
From 3069b61dc2838a6ed163877cb766adb51e63986b Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Mon, 10 Oct 2016 19:35:48 +1100
Subject: [PATCH 028/286] Seq.append
This implemention performs vastly better than the previous
implementation, which appeared to be more interested in being
theoretically important than actually being a reasonable implementation.
Anyway, the previous version blew up with stack overflow if you appended
too many things, which the new version doesn't.
---
src/fsharp/FSharp.Core/seq.fs | 238 ++++++++++------------------------
1 file changed, 72 insertions(+), 166 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index ce9cdd1dc04..bb248dd1469 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -318,149 +318,6 @@ namespace Microsoft.FSharp.Collections
f()
}
- // Use generators for some implementations of IEnumerables.
- //
- module Generator =
-
- open System.Collections
- open System.Collections.Generic
-
- []
- type Step<'T> =
- | Stop
- | Yield of 'T
- | Goto of Generator<'T>
-
- and Generator<'T> =
- abstract Apply: (unit -> Step<'T>)
- abstract Disposer: (unit -> unit) option
-
- let disposeG (g:Generator<'T>) =
- match g.Disposer with
- | None -> ()
- | Some f -> f()
-
- let appG (g:Generator<_>) =
- //System.Console.WriteLine("{0}.appG", box g)
- let res = g.Apply()
- match res with
- | Goto(next) ->
- Goto(next)
- | Yield _ ->
- res
- | Stop ->
- //System.Console.WriteLine("appG: Stop")
- disposeG g
- res
-
- // Binding.
- //
- // We use a type definition to apply a local dynamic optimization.
- // We automatically right-associate binding, i.e. push the continuations to the right.
- // That is, bindG (bindG G1 cont1) cont2 --> bindG G1 (cont1 o cont2)
- // This makes constructs such as the following linear rather than quadratic:
- //
- // let rec rwalk n = { if n > 0 then
- // yield! rwalk (n-1)
- // yield n }
-
- type GenerateThen<'T>(g:Generator<'T>, cont : unit -> Generator<'T>) =
- member self.Generator = g
- member self.Cont = cont
- interface Generator<'T> with
- member x.Apply = (fun () ->
- match appG g with
- | Stop ->
- // OK, move onto the generator given by the continuation
- Goto(cont())
-
- | Yield _ as res ->
- res
-
- | Goto next ->
- Goto(GenerateThen<_>.Bind(next,cont)))
- member x.Disposer =
- g.Disposer
-
-
- static member Bind (g:Generator<'T>, cont) =
- match g with
- | :? GenerateThen<'T> as g -> GenerateThen<_>.Bind(g.Generator,(fun () -> GenerateThen<_>.Bind (g.Cont(), cont)))
- | g -> (new GenerateThen<'T>(g, cont) :> Generator<'T>)
-
-
- let bindG g cont = GenerateThen<_>.Bind(g,cont)
-
-
- // Internal type. Drive an underlying generator. Crucially when the generator returns
- // a new generator we simply update our current generator and continue. Thus the enumerator
- // effectively acts as a reference cell holding the current generator. This means that
- // infinite or large generation chains (e.g. caused by long sequences of append's, including
- // possible delay loops) can be referenced via a single enumerator.
- //
- // A classic case where this arises in this sort of sequence expression:
- // let rec data s = { yield s;
- // yield! data (s + random()) }
- //
- // This translates to
- // let rec data s = Seq.delay (fun () -> Seq.append (Seq.singleton s) (Seq.delay (fun () -> data (s+random()))))
- //
- // When you unwind through all the Seq, IEnumerator and Generator objects created,
- // you get (data s).GetEnumerator being an "GenerateFromEnumerator(EnumeratorWrappingLazyGenerator(...))" for the append.
- // After one element is yielded, we move on to the generator for the inner delay, which in turn
- // comes back to be a "GenerateFromEnumerator(EnumeratorWrappingLazyGenerator(...))".
- //
- // Defined as a type so we can optimize Enumerator/Generator chains in enumerateFromLazyGenerator
- // and GenerateFromEnumerator.
-
- []
- type EnumeratorWrappingLazyGenerator<'T>(g:Generator<'T>) =
- let mutable g = g
- let mutable curr = None
- let mutable finished = false
- member e.Generator = g
- interface IEnumerator<'T> with
- member x.Current= match curr with Some(v) -> v | None -> raise <| System.InvalidOperationException (SR.GetString(SR.moveNextNotCalledOrFinished))
- interface System.Collections.IEnumerator with
- member x.Current = box (x :> IEnumerator<_>).Current
- member x.MoveNext() =
- not finished &&
- (match appG g with
- | Stop ->
- curr <- None
- finished <- true
- false
- | Yield(v) ->
- curr <- Some(v)
- true
- | Goto(next) ->
- (g <- next)
- (x :> IEnumerator).MoveNext())
- member x.Reset() = IEnumerator.noReset()
- interface System.IDisposable with
- member x.Dispose() =
- if not finished then disposeG g
-
- // Internal type, used to optimize Enumerator/Generator chains
- type LazyGeneratorWrappingEnumerator<'T>(e:System.Collections.Generic.IEnumerator<'T>) =
- member g.Enumerator = e
- interface Generator<'T> with
- member g.Apply = (fun () ->
- if e.MoveNext() then
- Yield(e.Current)
- else
- Stop)
- member g.Disposer= Some(e.Dispose)
-
- let EnumerateFromGenerator(g:Generator<'T>) =
- match g with
- | :? LazyGeneratorWrappingEnumerator<'T> as g -> g.Enumerator
- | _ -> (new EnumeratorWrappingLazyGenerator<_>(g) :> System.Collections.Generic.IEnumerator<_>)
-
- let GenerateFromEnumerator (e:System.Collections.Generic.IEnumerator<'T>) =
- match e with
- | :? EnumeratorWrappingLazyGenerator<'T> as e -> e.Generator
- | _ -> (new LazyGeneratorWrappingEnumerator<'T>(e) :> Generator<'T>)
namespace Microsoft.FSharp.Core.CompilerServices
@@ -1083,9 +940,9 @@ namespace Microsoft.FSharp.Collections
result.Current <- input
true
- module Base =
+ module Enumerable =
[]
- type Enumerator<'T>(result:Result<'T>, seqComponent:ISeqComponent) =
+ type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) =
interface IDisposable with
member __.Dispose() : unit =
seqComponent.OnDispose ()
@@ -1102,10 +959,11 @@ namespace Microsoft.FSharp.Collections
| SeqProcessNextStates.Finished -> alreadyFinished()
| _ -> result.Current
-
- []
- type Enumerable<'T> () =
+ and [] EnumerableBase<'T> () =
abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
+ abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T>
+
+ default this.Append source = Helpers.UpcastEnumerable (AppendEnumerable [this; source])
interface IEnumerable with
member this.GetEnumerator () : IEnumerator =
@@ -1116,9 +974,8 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'T> with
member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
- module Enumerable =
- type Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit Base.Enumerator<'U>(result, seqComponent)
+ and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit EnumeratorBase<'U>(result, seqComponent)
let rec moveNext () =
if (not result.Halted) && source.MoveNext () then
@@ -1141,8 +998,8 @@ namespace Microsoft.FSharp.Collections
source.Dispose ()
(Helpers.UpcastISeqComponent seqComponent).OnDispose ()
- type Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit Base.Enumerable<'U>()
+ and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
+ inherit EnumerableBase<'U>()
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
@@ -1168,9 +1025,59 @@ namespace Microsoft.FSharp.Collections
//
// state
+ and AppendEnumerator<'T> (sources:list>) =
+ let sources = sources |> List.rev
+
+ let mutable state = SeqProcessNextStates.NotStarted
+ let mutable remaining = sources.Tail
+ let mutable active = sources.Head.GetEnumerator ()
+
+ let rec moveNext () =
+ if active.MoveNext () then true
+ else
+ match remaining with
+ | [] -> false
+ | hd :: tl ->
+ active.Dispose ()
+ active <- hd.GetEnumerator ()
+ remaining <- tl
+
+ moveNext ()
+
+ interface IEnumerator<'T> with
+ member __.Current =
+ match state with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> active.Current
+
+ interface IEnumerator with
+ member __.Current = (Helpers.UpcastEnumeratorNonGeneric active).Current
+ member __.MoveNext () =
+ state <- SeqProcessNextStates.InProcess
+ moveNext ()
+ member __.Reset () = noReset ()
+
+ interface IDisposable with
+ member __.Dispose() =
+ active.Dispose ()
+
+ and AppendEnumerable<'T> (sources:list>) =
+ inherit EnumerableBase<'T>()
+
+ interface IEnumerable<'T> with
+ member this.GetEnumerator () : IEnumerator<'T> =
+ Helpers.UpcastEnumerator (new AppendEnumerator<_> (sources))
+
+ override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
+ Helpers.UpcastEnumerable (Enumerable<'T,'V>(this, next))
+
+ override this.Append source =
+ Helpers.UpcastEnumerable (AppendEnumerable (source :: sources))
+
module Array =
type Enumerator<'T,'U>(array:array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit Base.Enumerator<'U>(result, seqComponent)
+ inherit Enumerable.EnumeratorBase<'U>(result, seqComponent)
let mutable idx = 0
@@ -1192,7 +1099,7 @@ namespace Microsoft.FSharp.Collections
moveNext ()
type Enumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit Base.Enumerable<'U>()
+ inherit Enumerable.EnumerableBase<'U>()
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
@@ -1220,7 +1127,7 @@ namespace Microsoft.FSharp.Collections
module List =
type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit Base.Enumerator<'U>(result, seqComponent)
+ inherit Enumerable.EnumeratorBase<'U>(result, seqComponent)
let mutable list = alist
@@ -1243,7 +1150,7 @@ namespace Microsoft.FSharp.Collections
moveNext list
type Enumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit Base.Enumerable<'U>()
+ inherit Enumerable.EnumerableBase<'U>()
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
@@ -1265,7 +1172,7 @@ namespace Microsoft.FSharp.Collections
// I have had to add an extra function that is used in Skip to determine if we are touching
// Current or not.
type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) =
- inherit Base.Enumerator<'U>(signal, seqComponent)
+ inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent)
// we are offset by 1 to allow for values going up to System.Int32.MaxValue
// System.Int32.MaxValue is an illegal value for the "infinite" sequence
@@ -1306,7 +1213,7 @@ namespace Microsoft.FSharp.Collections
moveNext ()
type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) =
- inherit Base.Enumerable<'U>()
+ inherit Enumerable.EnumerableBase<'U>()
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
@@ -1317,7 +1224,7 @@ namespace Microsoft.FSharp.Collections
Helpers.UpcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next)))
type EnumerableDecider<'T>(count:Nullable, f:int->'T) =
- inherit Base.Enumerable<'T>()
+ inherit Enumerable.EnumerableBase<'T>()
interface IEnumerable<'T> with
member this.GetEnumerator () : IEnumerator<'T> =
@@ -1453,7 +1360,7 @@ namespace Microsoft.FSharp.Collections
let private seqFactory createSeqComponent (source:seq<'T>) =
checkNonNull "source" source
match source with
- | :? SeqComposer.Base.Enumerable<'T> as s -> s.Compose createSeqComponent
+ | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose createSeqComponent
| :? array<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Array.Enumerable<_,_>(a, createSeqComponent))
| :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.List.Enumerable<_,_>(a, createSeqComponent))
| _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Enumerable.Enumerable<_,_>(source, createSeqComponent))
@@ -1484,7 +1391,7 @@ namespace Microsoft.FSharp.Collections
checkNonNull "source1" source1
checkNonNull "source2" source2
match source1 with
- | :? SeqComposer.Base.Enumerable<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2))
+ | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2))
| _ -> source2 |> seqFactory (SeqComposer.Map2SecondFactory (f, source1))
[]
@@ -1629,9 +1536,6 @@ namespace Microsoft.FSharp.Collections
state <- f.Invoke(state, e.Current)
state
- let fromGenerator f = mkSeq(fun () -> Generator.EnumerateFromGenerator (f()))
- let toGenerator (ie : seq<_>) = Generator.GenerateFromEnumerator (ie.GetEnumerator())
-
[]
let replicate count x =
System.Linq.Enumerable.Repeat(x,count)
@@ -1640,7 +1544,9 @@ namespace Microsoft.FSharp.Collections
let append (source1: seq<'T>) (source2: seq<'T>) =
checkNonNull "source1" source1
checkNonNull "source2" source2
- fromGenerator(fun () -> Generator.bindG (toGenerator source1) (fun () -> toGenerator source2))
+ match source1 with
+ | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Append source2
+ | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Enumerable.AppendEnumerable<_>([source2; source1]))
[]
From e7a4efdcdf69297b244802e5d70dfea0cd6e170e Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Mon, 10 Oct 2016 19:42:40 +1100
Subject: [PATCH 029/286] minor perf; assume "InProcess"
---
src/fsharp/FSharp.Core/seq.fs | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index bb248dd1469..02aa5abdc0d 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -661,9 +661,9 @@ namespace Microsoft.FSharp.Collections
let inline UpcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #)
type SeqProcessNextStates =
+ | InProcess = 0
| NotStarted = 1
| Finished = 2
- | InProcess = 3
type Result<'T>() =
let mutable halted = false
@@ -954,10 +954,12 @@ namespace Microsoft.FSharp.Collections
interface IEnumerator<'T> with
member __.Current =
- match result.SeqState with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> result.Current
+ if result.SeqState = SeqProcessNextStates.InProcess then result.Current
+ else
+ match result.SeqState with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> failwith "library implementation error: all states should have been handled"
and [] EnumerableBase<'T> () =
abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
@@ -1046,10 +1048,12 @@ namespace Microsoft.FSharp.Collections
interface IEnumerator<'T> with
member __.Current =
- match state with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> active.Current
+ if state = SeqProcessNextStates.InProcess then active.Current
+ else
+ match state with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> failwith "library implementation error: all states should have been handled"
interface IEnumerator with
member __.Current = (Helpers.UpcastEnumeratorNonGeneric active).Current
From bede7fde90d38e3b1e4c4851e8170fadc891aaa3 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Mon, 10 Oct 2016 19:46:35 +1100
Subject: [PATCH 030/286] Bug fix; ensure exception protocol is followed
---
src/fsharp/FSharp.Core/seq.fs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 02aa5abdc0d..37d3ba5f8bd 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1056,7 +1056,7 @@ namespace Microsoft.FSharp.Collections
| _ -> failwith "library implementation error: all states should have been handled"
interface IEnumerator with
- member __.Current = (Helpers.UpcastEnumeratorNonGeneric active).Current
+ member this.Current = box ((Helpers.UpcastEnumerator this)).Current
member __.MoveNext () =
state <- SeqProcessNextStates.InProcess
moveNext ()
From 052119d18d867faeb398d06d906cfa2255ffd22f Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Tue, 11 Oct 2016 19:32:19 +1100
Subject: [PATCH 031/286] Seq.fold
---
src/fsharp/FSharp.Core/seq.fs | 156 ++++++++++++++++++++++++----------
1 file changed, 113 insertions(+), 43 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 37d3ba5f8bd..72d0a46061a 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -964,6 +964,7 @@ namespace Microsoft.FSharp.Collections
and [] EnumerableBase<'T> () =
abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T>
+ abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State
default this.Append source = Helpers.UpcastEnumerable (AppendEnumerable [this; source])
@@ -1011,21 +1012,20 @@ namespace Microsoft.FSharp.Collections
override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory (current, next)))
- // interface ISeqEnumerable<'U> with
- // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
- // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
- //
- // let enumerator = enumerable.GetEnumerator ()
- // let result = Result<'U> ()
- //
- // let components = current.Create result (Tail result)
- //
- // let mutable state = initialState
- // while (not result.Halted) && enumerator.MoveNext () do
- // if components.ProcessNext (enumerator.Current) then
- // state <- folder'.Invoke (state, result.Current)
- //
- // state
+ override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let enumerator = enumerable.GetEnumerator ()
+ let result = Result<'U> ()
+
+ let components = current.Create result (Tail result)
+
+ let mutable state = initialState
+ while (not result.Halted) && (enumerator.MoveNext ()) do
+ if components.ProcessNext (enumerator.Current) then
+ state <- folder'.Invoke (state, result.Current)
+
+ state
and AppendEnumerator<'T> (sources:list>) =
let sources = sources |> List.rev
@@ -1079,6 +1079,18 @@ namespace Microsoft.FSharp.Collections
override this.Append source =
Helpers.UpcastEnumerable (AppendEnumerable (source :: sources))
+ override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let enumerable = Helpers.UpcastEnumerable (AppendEnumerable sources)
+ let enumerator = enumerable.GetEnumerator ()
+
+ let mutable state = initialState
+ while enumerator.MoveNext () do
+ state <- folder'.Invoke (state, enumerator.Current)
+
+ state
+
module Array =
type Enumerator<'T,'U>(array:array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
inherit Enumerable.EnumeratorBase<'U>(result, seqComponent)
@@ -1113,21 +1125,20 @@ namespace Microsoft.FSharp.Collections
override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory (current, next)))
- // interface ISeqEnumerable<'U> with
- // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
- // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
- //
- // let mutable idx = 0
- // let result = Result<'U> ()
- // let components = current.Create result (Tail result)
- //
- // let mutable state = initialState
- // while (not result.Halted) && idx < array.Length do
- // if components.ProcessNext array.[idx] then
- // state <- folder'.Invoke(state, result.Current)
- // idx <- idx + 1
- //
- // state
+ override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let mutable idx = 0
+ let result = Result<'U> ()
+ let components = current.Create result (Tail result)
+
+ let mutable state = initialState
+ while (not result.Halted) && (idx < array.Length) do
+ if components.ProcessNext array.[idx] then
+ state <- folder'.Invoke (state, result.Current)
+ idx <- idx + 1
+
+ state
module List =
type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
@@ -1164,6 +1175,24 @@ namespace Microsoft.FSharp.Collections
override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory (current, next)))
+ override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let result = Result<'U> ()
+ let components = current.Create result (Tail result)
+
+ let rec fold state lst =
+ match result.Halted, lst with
+ | true, _
+ | false, [] -> state
+ | false, hd :: tl ->
+ if components.ProcessNext hd then
+ fold (folder'.Invoke (state, result.Current)) tl
+ else
+ fold state tl
+
+ fold initialState alist
+
module Init =
// The original implementation of "init" delayed the calculation of Current, and so it was possible
// to do MoveNext without it's value being calculated.
@@ -1175,16 +1204,20 @@ namespace Microsoft.FSharp.Collections
// so you already know what the count is!! Anyway, someone thought it was a good idea, so
// I have had to add an extra function that is used in Skip to determine if we are touching
// Current or not.
- type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) =
- inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent)
+ let getTerminatingIdx (count:Nullable) =
// we are offset by 1 to allow for values going up to System.Int32.MaxValue
// System.Int32.MaxValue is an illegal value for the "infinite" sequence
+ if count.HasValue then
+ count.Value - 1
+ else
+ System.Int32.MaxValue
+
+ type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) =
+ inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent)
+
let terminatingIdx =
- if count.HasValue then
- count.Value - 1
- else
- System.Int32.MaxValue
+ getTerminatingIdx count
let mutable maybeSkipping = true
let mutable idx = -1
@@ -1227,6 +1260,29 @@ namespace Microsoft.FSharp.Collections
override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next)))
+ override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let result = Result<'U> ()
+ let components = current.Create result (Tail result)
+
+ let mutable idx = -1
+ let terminatingIdx = getTerminatingIdx count
+
+ let mutable maybeSkipping = true
+
+ let mutable state = initialState
+ while (not result.Halted) && (idx < terminatingIdx) do
+ if maybeSkipping then
+ maybeSkipping <- components.Skipping ()
+
+ if (not maybeSkipping) && (components.ProcessNext (f (idx+1))) then
+ state <- folder'.Invoke (state, result.Current)
+
+ idx <- idx + 1
+
+ state
+
type EnumerableDecider<'T>(count:Nullable, f:int->'T) =
inherit Enumerable.EnumerableBase<'T>()
@@ -1240,6 +1296,17 @@ namespace Microsoft.FSharp.Collections
override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
Helpers.UpcastEnumerable (Enumerable<'T,'V>(count, f, next))
+ override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let enumerator = (Helpers.UpcastEnumerable this).GetEnumerator ()
+
+ let mutable state = initialState
+ while enumerator.MoveNext () do
+ state <- folder'.Invoke (state, enumerator.Current)
+
+ state
+
#if FX_NO_ICLONEABLE
open Microsoft.FSharp.Core.ICloneableExtensions
#else
@@ -1504,14 +1571,17 @@ namespace Microsoft.FSharp.Collections
state
[]
- let fold<'T,'State> f (x:'State) (source : seq<'T>) =
+ let fold<'T,'State> f (x:'State) (source:seq<'T>) =
checkNonNull "source" source
- use e = source.GetEnumerator()
- let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
- let mutable state = x
- while e.MoveNext() do
- state <- f.Invoke(state, e.Current)
- state
+ match source with
+ | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Fold f x
+ | _ ->
+ use e = source.GetEnumerator()
+ let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
+ let mutable state = x
+ while e.MoveNext() do
+ state <- f.Invoke(state, e.Current)
+ state
[]
let fold2<'T1,'T2,'State> f (state:'State) (source1: seq<'T1>) (source2: seq<'T2>) =
From cea835c65ec92f1b41cb665504d5aed5db52cd2b Mon Sep 17 00:00:00 2001
From: liboz
Date: Tue, 11 Oct 2016 16:28:24 -0400
Subject: [PATCH 032/286] fix typo
---
src/fsharp/FSharp.Core/seq.fs | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 72d0a46061a..75ad5f301e6 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -719,13 +719,13 @@ namespace Microsoft.FSharp.Collections
inherit SeqComponentFactory<'T,'T> ()
override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
- and SkipWhileFactory<'T> (perdicate:'T->bool) =
+ and SkipWhileFactory<'T> (predicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (predicate, next)
- and TakeWhileFactory<'T> (perdicate:'T->bool) =
+ and TakeWhileFactory<'T> (predicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, result, next)
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (predicate, result, next)
and TakeFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
From dfef8a621192cd7cc818a365a388b11125bc403a Mon Sep 17 00:00:00 2001
From: liboz
Date: Tue, 11 Oct 2016 21:16:38 -0400
Subject: [PATCH 033/286] truncate
---
src/fsharp/FSharp.Core/seq.fs | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 75ad5f301e6..9b8d0e933ad 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -730,6 +730,10 @@ namespace Microsoft.FSharp.Collections
and TakeFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next)
+
+ and TruncateFactory<'T> (count:int) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Truncate (count, result, next)
and [] SeqComponent<'T,'U> (next:ISeqComponent) =
abstract ProcessNext : input:'T -> bool
@@ -940,6 +944,21 @@ namespace Microsoft.FSharp.Collections
result.Current <- input
true
+ and Truncate<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>(next)
+
+ let mutable count = 0
+
+ override __.ProcessNext (input:'T) : bool =
+ if count < takeCount then
+ count <- count + 1
+ if count = takeCount then
+ result.StopFurtherProcessing ()
+ next.ProcessNext input
+ else
+ result.StopFurtherProcessing ()
+ false
+
module Enumerable =
[]
type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) =
@@ -1711,12 +1730,7 @@ namespace Microsoft.FSharp.Collections
[]
let truncate n (source: seq<'T>) =
- checkNonNull "source" source
- seq { let i = ref 0
- use ie = source.GetEnumerator()
- while !i < n && ie.MoveNext() do
- i := !i + 1
- yield ie.Current }
+ source |> seqFactory (SeqComposer.TruncateFactory n)
[]
let pairwise<'T> (source:seq<'T>) : seq<'T*'T> =
From 051fff5a90f2f2815ba7fb8bdb1e8889d923ee5c Mon Sep 17 00:00:00 2001
From: liboz
Date: Tue, 11 Oct 2016 22:36:09 -0400
Subject: [PATCH 034/286] using inheritance for take
---
src/fsharp/FSharp.Core/seq.fs | 28 +++++++++-------------------
1 file changed, 9 insertions(+), 19 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 9b8d0e933ad..9336b1bfd7f 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -905,24 +905,12 @@ namespace Microsoft.FSharp.Collections
Helpers.avoidTailCall (next.ProcessNext input)
and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
- inherit SeqComponent<'T,'V>(next)
-
- let mutable count = 0
-
- override __.ProcessNext (input:'T) : bool =
- if count < takeCount then
- count <- count + 1
- if count = takeCount then
- result.StopFurtherProcessing ()
- next.ProcessNext input
- else
- result.StopFurtherProcessing ()
- false
+ inherit Truncate<'T, 'V>(takeCount, result, next)
interface ISeqComponent with
- override __.OnComplete () =
- if count < takeCount then
- let x = takeCount - count
+ override this.OnComplete () =
+ if this.Count < takeCount then
+ let x = takeCount - this.Count
invalidOpFmt "tried to take {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
(Helpers.UpcastISeqComponent next).OnComplete ()
@@ -944,15 +932,17 @@ namespace Microsoft.FSharp.Collections
result.Current <- input
true
- and Truncate<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
+ and Truncate<'T,'V> (truncateCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>(next)
let mutable count = 0
+ member __.Count = count
+
override __.ProcessNext (input:'T) : bool =
- if count < takeCount then
+ if count < truncateCount then
count <- count + 1
- if count = takeCount then
+ if count = truncateCount then
result.StopFurtherProcessing ()
next.ProcessNext input
else
From 162fd0e1968ff25899bdb9a9eec790a3164c0710 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Wed, 12 Oct 2016 19:08:05 +1100
Subject: [PATCH 035/286] Carry on disposing under exceptions
---
src/fsharp/FSharp.Core/seq.fs | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 9336b1bfd7f..80fdf298d39 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -805,8 +805,10 @@ namespace Microsoft.FSharp.Collections
interface ISeqComponent with
override __.OnDispose () =
- input2.Dispose ()
- (Helpers.UpcastISeqComponent next).OnDispose ()
+ try
+ input2.Dispose ()
+ finally
+ (Helpers.UpcastISeqComponent next).OnDispose ()
and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'Second,'V>(next)
@@ -823,8 +825,10 @@ namespace Microsoft.FSharp.Collections
interface ISeqComponent with
override __.OnDispose () =
- input1.Dispose ()
- (Helpers.UpcastISeqComponent next).OnDispose ()
+ try
+ input1.Dispose ()
+ finally
+ (Helpers.UpcastISeqComponent next).OnDispose ()
and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>(next)
@@ -1007,8 +1011,10 @@ namespace Microsoft.FSharp.Collections
interface IDisposable with
member __.Dispose() =
- source.Dispose ()
- (Helpers.UpcastISeqComponent seqComponent).OnDispose ()
+ try
+ source.Dispose ()
+ finally
+ (Helpers.UpcastISeqComponent seqComponent).OnDispose ()
and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
inherit EnumerableBase<'U>()
From c5f850c13bd42002a50cb848b822570cb26ee944 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Wed, 12 Oct 2016 20:23:43 +1100
Subject: [PATCH 036/286] bug fix: "truncate 0" was causing MoveNext on
underlying seq
---
src/fsharp/FSharp.Core/seq.fs | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 80fdf298d39..e8792358d98 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1726,6 +1726,7 @@ namespace Microsoft.FSharp.Collections
[]
let truncate n (source: seq<'T>) =
+ if n <= 0 then empty else
source |> seqFactory (SeqComposer.TruncateFactory n)
[]
From 85dfa258b26a82ff0c3e61cdc79018b6b7310667 Mon Sep 17 00:00:00 2001
From: liboz
Date: Wed, 12 Oct 2016 21:46:26 -0400
Subject: [PATCH 037/286] distinct/distinctby
---
src/fsharp/FSharp.Core/seq.fs | 42 ++++++++++++++++++++++++++---------
1 file changed, 32 insertions(+), 10 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index e8792358d98..880d1488319 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -690,6 +690,14 @@ namespace Microsoft.FSharp.Collections
and ChooseFactory<'T,'U> (filter:'T->option<'U>) =
inherit SeqComponentFactory<'T,'U> ()
override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
+
+ and DistinctFactory<'T when 'T: equality> () =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Distinct (next)
+
+ and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast DistinctBy (keyFunction, next)
and FilterFactory<'T> (filter:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
@@ -762,6 +770,28 @@ namespace Microsoft.FSharp.Collections
| Some value -> Helpers.avoidTailCall (next.ProcessNext value)
| None -> false
+ and Distinct<'T,'V when 'T: equality> (next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>(next)
+
+ let hashSet = HashSet<'T>(HashIdentity.Structural<'T>)
+
+ override __.ProcessNext (input:'T) : bool =
+ if hashSet.Add input then
+ Helpers.avoidTailCall (next.ProcessNext input)
+ else
+ false
+
+ and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>(next)
+
+ let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>)
+
+ override __.ProcessNext (input:'T) : bool =
+ if hashSet.Add(keyFunction input) then
+ Helpers.avoidTailCall (next.ProcessNext input)
+ else
+ false
+
and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>(next)
@@ -1939,19 +1969,11 @@ namespace Microsoft.FSharp.Collections
[]
let distinct source =
- checkNonNull "source" source
- seq { let hashSet = HashSet<'T>(HashIdentity.Structural<'T>)
- for v in source do
- if hashSet.Add(v) then
- yield v }
+ source |> seqFactory (SeqComposer.DistinctFactory ())
[]
let distinctBy keyf source =
- checkNonNull "source" source
- seq { let hashSet = HashSet<_>(HashIdentity.Structural<_>)
- for v in source do
- if hashSet.Add(keyf v) then
- yield v }
+ source |> seqFactory (SeqComposer.DistinctByFactory keyf)
[]
let sortBy keyf source =
From 2c2dc54297462c0acb9065e389104907469916db Mon Sep 17 00:00:00 2001
From: liboz
Date: Thu, 13 Oct 2016 06:19:09 -0400
Subject: [PATCH 038/286] except
---
src/fsharp/FSharp.Core/seq.fs | 27 ++++++++++++++++-----------
1 file changed, 16 insertions(+), 11 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 880d1488319..126c5376e0a 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -698,6 +698,10 @@ namespace Microsoft.FSharp.Collections
and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) =
inherit SeqComponentFactory<'T,'T> ()
override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast DistinctBy (keyFunction, next)
+
+ and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Except (itemsToExclude, next)
and FilterFactory<'T> (filter:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
@@ -792,6 +796,17 @@ namespace Microsoft.FSharp.Collections
else
false
+ and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>(next)
+
+ let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural))
+
+ override __.ProcessNext (input:'T) : bool =
+ if cached.Value.Add input then
+ Helpers.avoidTailCall (next.ProcessNext input)
+ else
+ false
+
and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>(next)
@@ -2306,17 +2321,7 @@ namespace Microsoft.FSharp.Collections
[]
let except (itemsToExclude: seq<'T>) (source: seq<'T>) =
checkNonNull "itemsToExclude" itemsToExclude
- checkNonNull "source" source
-
- seq {
- use e = source.GetEnumerator()
- if e.MoveNext() then
- let cached = HashSet(itemsToExclude, HashIdentity.Structural)
- let next = e.Current
- if (cached.Add next) then yield next
- while e.MoveNext() do
- let next = e.Current
- if (cached.Add next) then yield next }
+ source |> seqFactory (SeqComposer.ExceptFactory itemsToExclude)
[]
let chunkBySize chunkSize (source : seq<_>) =
From 5ce582e51796cf9ae565dd9ff15986e2140bc72d Mon Sep 17 00:00:00 2001
From: liboz
Date: Thu, 13 Oct 2016 21:55:52 -0400
Subject: [PATCH 039/286] indexed
---
src/fsharp/FSharp.Core/seq.fs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 126c5376e0a..26ff381d641 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1538,8 +1538,7 @@ namespace Microsoft.FSharp.Collections
[]
let indexed source =
- checkNonNull "source" source
- mapi (fun i x -> i,x) source
+ source |> seqFactory (SeqComposer.MapiFactory (fun i x -> i,x) )
[]
let zip source1 source2 =
From 15fb50fcf391760c6f1a732f493ed6beb04a6f7c Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Mon, 10 Oct 2016 19:35:48 +1100
Subject: [PATCH 040/286] Seq.append
This implemention performs vastly better than the previous
implementation, which appeared to be more interested in being
theoretically important than actually being a reasonable implementation.
Anyway, the previous version blew up with stack overflow if you appended
too many things, which the new version doesn't.
---
src/fsharp/FSharp.Core/seq.fs | 44 ++++++-----------------------------
1 file changed, 7 insertions(+), 37 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 26ff381d641..85bf3f897a1 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -981,23 +981,6 @@ namespace Microsoft.FSharp.Collections
result.Current <- input
true
- and Truncate<'T,'V> (truncateCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
- inherit SeqComponent<'T,'V>(next)
-
- let mutable count = 0
-
- member __.Count = count
-
- override __.ProcessNext (input:'T) : bool =
- if count < truncateCount then
- count <- count + 1
- if count = truncateCount then
- result.StopFurtherProcessing ()
- next.ProcessNext input
- else
- result.StopFurtherProcessing ()
- false
-
module Enumerable =
[]
type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) =
@@ -1022,7 +1005,6 @@ namespace Microsoft.FSharp.Collections
and [