From d24b92874e297eb6f795741cfece681d8bc62243 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Wed, 28 Sep 2016 19:42:15 +1000
Subject: [PATCH 001/327] Basis of SeqComposer
- Removed all dynamic casting
- Split enumerable/enumerator
- Implementations of map, filter, skip, pairwise
---
src/fsharp/FSharp.Core/seq.fs | 266 ++++++++++++++++++++++++++++------
1 file changed, 223 insertions(+), 43 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index ddf73fb5cc1..bbe26ef30ab 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -22,6 +22,215 @@ namespace Microsoft.FSharp.Collections
let check started = if not started then notStarted()
let dispose (r : System.IDisposable) = r.Dispose()
+ module SeqComposer =
+ module Helpers =
+ // used for performance reasons; these are not recursive calls, so should be safe
+ let inline avoidTailCall x =
+ match x with
+ | true -> true
+ | false -> false
+
+ type Factory =
+ static member Filter f g = Filter (fun x -> f x && g x)
+ static member Map f g = Map (f >> g)
+
+ and [] SeqComponent<'T,'U> () =
+ abstract ProcessNext : 'T * byref<'U> -> bool
+
+ abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
+
+ abstract ComposeMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeFilter : Filter<'T> -> SeqComponent<'T,'U>
+ abstract ComposeFilterMap<'S> : FilterMap<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeMapFilter<'S> : MapFilter<'S,'T> -> SeqComponent<'S,'U>
+
+ override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second)
+
+ default second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
+ default second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+
+ and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'T,'V>()
+
+ override __.ProcessNext (input:'T, output:byref<'V>) :bool =
+ let mutable temp = Unchecked.defaultof<'U>
+ if first.ProcessNext (input, &temp) then
+ Helpers.avoidTailCall (second.ProcessNext (temp, &output))
+ else
+ false
+
+ override __.Composer (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> =
+ upcast Composed (first, second.Composer next)
+
+ member __.First = first
+ member __.Second = second
+
+ and Map<'T,'U> (map:'T->'U) =
+ inherit SeqComponent<'T,'U>()
+
+ override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> =
+ second.ComposeMap first
+
+ override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> =
+ upcast Factory.Map first.Map second.Map
+
+ override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> =
+ upcast FilterMap (first, second)
+
+ override second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> =
+ upcast FilterMap (first.Filter, Factory.Map first.Map.Map second.Map)
+
+ override __.ProcessNext (input:'T, output:byref<'U>) : bool =
+ output <- map input
+ true
+
+ member __.Map :'T->'U = map
+
+ and Filter<'T> (filter:'T->bool) =
+ inherit SeqComponent<'T,'T>()
+
+ override this.Composer (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
+ next.ComposeFilter this
+
+ override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> =
+ upcast MapFilter (first, second)
+
+ override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'T> =
+ upcast Factory.Filter first.Filter second.Filter
+
+ override second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'T> =
+ upcast MapFilter(first.Map, Factory.Filter first.Filter.Filter second.Filter)
+
+ override __.ProcessNext (input:'T, output:byref<'T>) : bool =
+ if filter input then
+ output <- input
+ true
+ else
+ false
+
+ member __.Filter :'T->bool = filter
+
+ and MapFilter<'T,'U> (map:Map<'T,'U>, filter:Filter<'U>) =
+ inherit SeqComponent<'T,'U>()
+
+ override __.ProcessNext (input:'T, output:byref<'U>) :bool =
+ output <- map.Map input
+ Helpers.avoidTailCall (filter.Filter output)
+
+ override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> =
+ second.ComposeMapFilter first
+
+ member __.Map : Map<'T,'U> = map
+ member __.Filter : Filter<'U> = filter
+
+ and FilterMap<'T,'U> (filter:Filter<'T>, map:Map<'T,'U>) =
+ inherit SeqComponent<'T,'U>()
+
+ override __.ProcessNext (input:'T, output:byref<'U>) : bool =
+ if filter.Filter input then
+ output <- map.Map input
+ true
+ else
+ false
+
+ override this.Composer (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.ComposeFilterMap this
+
+ member __.Filter : Filter<'T> = filter
+ member __.Map : Map<'T,'U> = map
+
+ and Pairwise<'T> () =
+ inherit SeqComponent<'T,'T*'T>()
+
+ let mutable isFirst = true
+ let mutable lastValue = Unchecked.defaultof<'T>
+
+ override __.ProcessNext (input:'T, output:byref<'T*'T>) : bool =
+ if isFirst then
+ lastValue <- input
+ isFirst <- false
+ false
+ else
+ output <- lastValue, input
+ lastValue <- input
+ true
+
+ and Skip<'T> (skipCount:int) =
+ inherit SeqComponent<'T,'T>()
+
+ let mutable count = 0
+
+ override __.ProcessNext (input:'T, output:byref<'T>) : bool =
+ if count < skipCount then
+ count <- count + 1
+ false
+ else
+ output <- input
+ true
+
+ type SeqProcessNextStates =
+ | NotStarted = 1
+ | Finished = 2
+ | InProcess = 3
+
+ type SeqEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) =
+ let mutable source = enumerator
+ let mutable state = SeqProcessNextStates.NotStarted
+ let mutable current = Unchecked.defaultof<_>
+
+ let rec moveNext () =
+ if source.MoveNext () then
+ if t2u.ProcessNext (source.Current, ¤t) then
+ true
+ else
+ moveNext ()
+ else
+ state <- SeqProcessNextStates.Finished
+ false
+
+ interface IDisposable with
+ member x.Dispose():unit =
+ match source with
+ | null -> ()
+ | _ ->
+ source.Dispose ()
+ source <- Unchecked.defaultof<_>
+
+ interface IEnumerator with
+ member this.Current : obj = box (this:>IEnumerator<'U>).Current
+ member __.MoveNext () =
+ state <- SeqProcessNextStates.InProcess
+ moveNext ()
+ member __.Reset () : unit = noReset ()
+
+ interface IEnumerator<'U> with
+ member x.Current =
+ match state with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> ()
+ current
+
+ []
+ type SeqEnumerableBase<'T> () =
+ abstract member Compose<'U> : SeqComponent<'T,'U> -> IEnumerable<'U>
+
+ type SeqEnumerable<'T,'U>(generator:IEnumerable<'T>, t2u:SeqComponent<'T,'U>) =
+ inherit SeqEnumerableBase<'U>()
+
+ let getEnumerator () : IEnumerator<'U> =
+ upcast (new SeqEnumerator<'T,'U>(generator.GetEnumerator(), t2u))
+
+ interface IEnumerable with
+ member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
+
+ override __.Compose (u2v:SeqComponent<'U,'V>) =
+ new SeqEnumerable<'T,'V>(generator, t2u.Composer u2v) :> IEnumerable<'V>
+
let cast (e : IEnumerator) : IEnumerator<'T> =
{ new IEnumerator<'T> with
member x.Current = unbox<'T> e.Current
@@ -108,18 +317,6 @@ namespace Microsoft.FSharp.Collections
interface System.IDisposable with
member this.Dispose() = this.Dispose()
- let map f (e : IEnumerator<_>) : IEnumerator<_>=
- upcast
- { new MapEnumerator<_>() with
- member this.DoMoveNext (curr : byref<_>) =
- if e.MoveNext() then
- curr <- (f e.Current)
- true
- else
- false
- member this.Dispose() = e.Dispose()
- }
-
let mapi f (e : IEnumerator<_>) : IEnumerator<_> =
let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
let i = ref (-1)
@@ -215,23 +412,6 @@ namespace Microsoft.FSharp.Collections
interface System.IDisposable with
member x.Dispose() = e.Dispose() }
- let filter f (e : IEnumerator<'T>) =
- let started = ref false
- let this =
- { new IEnumerator<'T> with
- member x.Current = check !started; e.Current
- interface IEnumerator with
- member x.Current = check !started; box e.Current
- member x.MoveNext() =
- let rec next() =
- if not !started then started := true
- e.MoveNext() && (f e.Current || next())
- next()
- member x.Reset() = noReset()
- interface System.IDisposable with
- member x.Dispose() = e.Dispose() }
- this
-
let unfold f x : IEnumerator<_> =
let state = ref x
upcast
@@ -963,17 +1143,21 @@ namespace Microsoft.FSharp.Collections
mkSeq (fun () -> f (ie1.GetEnumerator()) (source2.GetEnumerator()) (source3.GetEnumerator()))
[]
- let filter f source =
+ let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> =
checkNonNull "source" source
- revamp (IEnumerator.filter f) source
+ match source with
+ | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Filter f)
+ | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Filter f))
[]
- let where f source = filter f source
+ let where f source = filter f source
[]
- let map f source =
+ let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> =
checkNonNull "source" source
- revamp (IEnumerator.map f) source
+ match source with
+ | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Map f)
+ | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Map f))
[]
let mapi f source =
@@ -1257,15 +1441,11 @@ namespace Microsoft.FSharp.Collections
yield ie.Current }
[]
- let pairwise (source: seq<'T>) =
- checkNonNull "source" source
- seq { use ie = source.GetEnumerator()
- if ie.MoveNext() then
- let iref = ref ie.Current
- while ie.MoveNext() do
- let j = ie.Current
- yield (!iref, j)
- iref := j }
+ let pairwise<'T> (source:seq<'T>) : seq<'T*'T> =
+ checkNonNull "source" source
+ match source with
+ | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Pairwise ())
+ | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Pairwise ()))
[]
let scan<'T,'State> f (z:'State) (source : seq<'T>) =
From 44e4266184b00aa000c4ce91a66c6e3f40e5ca4c Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Thu, 29 Sep 2016 16:05:23 +1000
Subject: [PATCH 002/327] Fixed output due to change in Seq.map
---
.../analyses/tailcalls.NoNeedToTailcall.output.test.bsl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl
index 5f4e677efc6..785a337a2f4 100644
--- a/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl
+++ b/tests/fsharp/optimize/analyses/tailcalls.NoNeedToTailcall.output.test.bsl
@@ -38,7 +38,7 @@ value simpleLibraryCall6 at line 60 does not make a critical tailcall
value simpleLibraryCall7 at line 61 does not make a critical tailcall
value simpleLibraryCall8 at line 62 does not make a critical tailcall
value simpleLibraryCall9 at line 63 does not make a critical tailcall
-value simpleLibraryCall10 at line 65 does not make a critical tailcall
+value simpleLibraryCall10 at line 65 may make a critical tailcall
value simpleLibraryCall11 at line 66 does not make a critical tailcall
value simpleLibraryCall12 at line 67 does not make a critical tailcall
value simpleLibraryCall13 at line 68 does not make a critical tailcall
From 33929d183b5f7b975b09c242fc760c666dde236c Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Thu, 29 Sep 2016 18:05:20 +1000
Subject: [PATCH 003/327] delayed component creation to respect mutability
- Added take, mapi
- Added same exceptions for skip & take
- Added composable skip & take
- Added array source
- Added source specific folding for functions like sum (required growing
of surface area, so currently not exposed)
---
src/fsharp/FSharp.Core/seq.fs | 644 +++++++++++++++++++++-------------
1 file changed, 405 insertions(+), 239 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index bbe26ef30ab..60282de76fe 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -15,222 +15,12 @@ namespace Microsoft.FSharp.Collections
module IEnumerator =
-
let noReset() = raise (new System.NotSupportedException(SR.GetString(SR.resetNotSupported)))
let notStarted() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationNotStarted)))
let alreadyFinished() = raise (new System.InvalidOperationException(SR.GetString(SR.enumerationAlreadyFinished)))
let check started = if not started then notStarted()
let dispose (r : System.IDisposable) = r.Dispose()
- module SeqComposer =
- module Helpers =
- // used for performance reasons; these are not recursive calls, so should be safe
- let inline avoidTailCall x =
- match x with
- | true -> true
- | false -> false
-
- type Factory =
- static member Filter f g = Filter (fun x -> f x && g x)
- static member Map f g = Map (f >> g)
-
- and [] SeqComponent<'T,'U> () =
- abstract ProcessNext : 'T * byref<'U> -> bool
-
- abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
-
- abstract ComposeMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeFilter : Filter<'T> -> SeqComponent<'T,'U>
- abstract ComposeFilterMap<'S> : FilterMap<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeMapFilter<'S> : MapFilter<'S,'T> -> SeqComponent<'S,'U>
-
- override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second)
-
- default second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
- default second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
-
- and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
-
- override __.ProcessNext (input:'T, output:byref<'V>) :bool =
- let mutable temp = Unchecked.defaultof<'U>
- if first.ProcessNext (input, &temp) then
- Helpers.avoidTailCall (second.ProcessNext (temp, &output))
- else
- false
-
- override __.Composer (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> =
- upcast Composed (first, second.Composer next)
-
- member __.First = first
- member __.Second = second
-
- and Map<'T,'U> (map:'T->'U) =
- inherit SeqComponent<'T,'U>()
-
- override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> =
- second.ComposeMap first
-
- override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> =
- upcast Factory.Map first.Map second.Map
-
- override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> =
- upcast FilterMap (first, second)
-
- override second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> =
- upcast FilterMap (first.Filter, Factory.Map first.Map.Map second.Map)
-
- override __.ProcessNext (input:'T, output:byref<'U>) : bool =
- output <- map input
- true
-
- member __.Map :'T->'U = map
-
- and Filter<'T> (filter:'T->bool) =
- inherit SeqComponent<'T,'T>()
-
- override this.Composer (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
- next.ComposeFilter this
-
- override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> =
- upcast MapFilter (first, second)
-
- override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'T> =
- upcast Factory.Filter first.Filter second.Filter
-
- override second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'T> =
- upcast MapFilter(first.Map, Factory.Filter first.Filter.Filter second.Filter)
-
- override __.ProcessNext (input:'T, output:byref<'T>) : bool =
- if filter input then
- output <- input
- true
- else
- false
-
- member __.Filter :'T->bool = filter
-
- and MapFilter<'T,'U> (map:Map<'T,'U>, filter:Filter<'U>) =
- inherit SeqComponent<'T,'U>()
-
- override __.ProcessNext (input:'T, output:byref<'U>) :bool =
- output <- map.Map input
- Helpers.avoidTailCall (filter.Filter output)
-
- override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> =
- second.ComposeMapFilter first
-
- member __.Map : Map<'T,'U> = map
- member __.Filter : Filter<'U> = filter
-
- and FilterMap<'T,'U> (filter:Filter<'T>, map:Map<'T,'U>) =
- inherit SeqComponent<'T,'U>()
-
- override __.ProcessNext (input:'T, output:byref<'U>) : bool =
- if filter.Filter input then
- output <- map.Map input
- true
- else
- false
-
- override this.Composer (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.ComposeFilterMap this
-
- member __.Filter : Filter<'T> = filter
- member __.Map : Map<'T,'U> = map
-
- and Pairwise<'T> () =
- inherit SeqComponent<'T,'T*'T>()
-
- let mutable isFirst = true
- let mutable lastValue = Unchecked.defaultof<'T>
-
- override __.ProcessNext (input:'T, output:byref<'T*'T>) : bool =
- if isFirst then
- lastValue <- input
- isFirst <- false
- false
- else
- output <- lastValue, input
- lastValue <- input
- true
-
- and Skip<'T> (skipCount:int) =
- inherit SeqComponent<'T,'T>()
-
- let mutable count = 0
-
- override __.ProcessNext (input:'T, output:byref<'T>) : bool =
- if count < skipCount then
- count <- count + 1
- false
- else
- output <- input
- true
-
- type SeqProcessNextStates =
- | NotStarted = 1
- | Finished = 2
- | InProcess = 3
-
- type SeqEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) =
- let mutable source = enumerator
- let mutable state = SeqProcessNextStates.NotStarted
- let mutable current = Unchecked.defaultof<_>
-
- let rec moveNext () =
- if source.MoveNext () then
- if t2u.ProcessNext (source.Current, ¤t) then
- true
- else
- moveNext ()
- else
- state <- SeqProcessNextStates.Finished
- false
-
- interface IDisposable with
- member x.Dispose():unit =
- match source with
- | null -> ()
- | _ ->
- source.Dispose ()
- source <- Unchecked.defaultof<_>
-
- interface IEnumerator with
- member this.Current : obj = box (this:>IEnumerator<'U>).Current
- member __.MoveNext () =
- state <- SeqProcessNextStates.InProcess
- moveNext ()
- member __.Reset () : unit = noReset ()
-
- interface IEnumerator<'U> with
- member x.Current =
- match state with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> ()
- current
-
- []
- type SeqEnumerableBase<'T> () =
- abstract member Compose<'U> : SeqComponent<'T,'U> -> IEnumerable<'U>
-
- type SeqEnumerable<'T,'U>(generator:IEnumerable<'T>, t2u:SeqComponent<'T,'U>) =
- inherit SeqEnumerableBase<'U>()
-
- let getEnumerator () : IEnumerator<'U> =
- upcast (new SeqEnumerator<'T,'U>(generator.GetEnumerator(), t2u))
-
- interface IEnumerable with
- member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
-
- interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
-
- override __.Compose (u2v:SeqComponent<'U,'V>) =
- new SeqEnumerable<'T,'V>(generator, t2u.Composer u2v) :> IEnumerable<'V>
-
let cast (e : IEnumerator) : IEnumerator<'T> =
{ new IEnumerator<'T> with
member x.Current = unbox<'T> e.Current
@@ -1022,6 +812,395 @@ namespace Microsoft.FSharp.Collections
[]
[]
module Seq =
+ type ISeqEnumerable<'T> =
+ abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State
+
+ module SeqComposer =
+ open IEnumerator
+
+ module Helpers =
+ // used for performance reasons; these are not recursive calls, so should be safe
+ let inline avoidTailCall x =
+ match x with
+ | true -> true
+ | false -> false
+
+ let inline ComposeFilter f g x = f x && g x
+
+ type [] SeqComponent<'T,'U> () =
+ abstract ProcessNext : input:'T * halt:byref * output:byref<'U> -> bool
+ abstract OnComplete : unit -> unit
+
+ abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
+
+ abstract ComposeMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeFilter : Filter<'T> -> SeqComponent<'T,'U>
+ abstract ComposeFilterMap<'S> : FilterMap<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeMapFilter<'S> : MapFilter<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeSkip : Skip<'T> -> SeqComponent<'T,'U>
+
+ default __.OnComplete () = ()
+
+ default first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second)
+
+ default second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
+ default second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
+
+ and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'T,'V>()
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) :bool =
+ let mutable temp = Unchecked.defaultof<'U>
+ if first.ProcessNext (input, &halted, &temp) && not halted then
+ second.ProcessNext (temp, &halted, &output)
+ else
+ false
+
+ override __.Composer (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> =
+ upcast Composed (first, second.Composer next)
+
+ override __.OnComplete () =
+ first.OnComplete ()
+ second.OnComplete ()
+
+ and Map<'T,'U> (map:'T->'U) =
+ inherit SeqComponent<'T,'U>()
+
+ override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> =
+ second.ComposeMap first
+
+ override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> =
+ upcast Map (first.Map >> second.Map)
+
+ override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> =
+ upcast FilterMap (first.Filter, second.Map)
+
+ override second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> =
+ upcast FilterMap (first.Filter, first.Map >> second.Map)
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
+ output <- map input
+ true
+
+ member __.Map : 'T->'U = map
+
+ and Mapi<'T,'U> (mapi:int->'T->'U) =
+ inherit SeqComponent<'T,'U>()
+
+ let mutable idx = 0
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
+ output <- mapi idx input
+ idx <- idx + 1
+ true
+
+ member __.Mapi : int->'T->'U = mapi
+
+ and Filter<'T> (filter:'T->bool) =
+ inherit SeqComponent<'T,'T>()
+
+ override this.Composer (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
+ next.ComposeFilter this
+
+ override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> =
+ upcast MapFilter (first.Map, second.Filter)
+
+ override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'T> =
+ upcast Filter (Helpers.ComposeFilter first.Filter second.Filter)
+
+ override second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'T> =
+ upcast MapFilter (first.Map, Helpers.ComposeFilter first.Filter second.Filter)
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ if filter input then
+ output <- input
+ true
+ else
+ false
+
+ member __.Filter :'T->bool = filter
+
+ and MapFilter<'T,'U> (map:'T->'U, filter:'U->bool) =
+ inherit SeqComponent<'T,'U>()
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) :bool =
+ output <- map input
+ Helpers.avoidTailCall (filter output)
+
+ override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> =
+ second.ComposeMapFilter first
+
+ member __.Map : 'T->'U = map
+ member __.Filter : 'U->bool = filter
+
+ and FilterMap<'T,'U> (filter:'T->bool, map:'T->'U) =
+ inherit SeqComponent<'T,'U>()
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
+ if filter input then
+ output <- map input
+ true
+ else
+ false
+
+ override this.Composer (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.ComposeFilterMap this
+
+ member __.Filter : 'T->bool = filter
+ member __.Map : 'T->'U = map
+
+ and Pairwise<'T> () =
+ inherit SeqComponent<'T,'T*'T>()
+
+ let mutable isFirst = true
+ let mutable lastValue = Unchecked.defaultof<'T>
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T*'T>) : bool =
+ if isFirst then
+ lastValue <- input
+ isFirst <- false
+ false
+ else
+ output <- lastValue, input
+ lastValue <- input
+ true
+
+ and Skip<'T> (skipCount:int) =
+ inherit SeqComponent<'T,'T>()
+
+ let mutable count = 0
+
+ override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
+ second.ComposeSkip first
+
+ override second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
+ if System.Int32.MaxValue - second.SkipCount > first.SkipCount then
+ upcast Skip (first.SkipCount + second.SkipCount)
+ else
+ upcast Composed (first, second)
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ if count < skipCount then
+ count <- count + 1
+ false
+ else
+ output <- input
+ true
+
+ override __.OnComplete () =
+ if count < skipCount then
+ let x = skipCount - count
+ invalidOpFmt "tried to skip {0} {1} past the end of the seq"
+ [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+
+ member __.SkipCount = skipCount
+
+ and Take<'T> (takeCount:int) =
+ inherit SeqComponent<'T,'T>()
+
+ let mutable count = 0
+
+ override second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
+ if System.Int32.MaxValue - second.TakeCount > first.SkipCount then
+ upcast SkipTake (first.SkipCount, first.SkipCount+second.TakeCount)
+ else
+ upcast Composed (first, second)
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ if count < takeCount then
+ count <- count + 1
+ output <- input
+ true
+ else
+ halted <- true
+ false
+
+ override __.OnComplete () =
+ if count < takeCount then
+ let x = takeCount - count
+ invalidOpFmt "tried to take {0} {1} past the end of the seq"
+ [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+
+ member __.TakeCount = takeCount
+
+ and SkipTake<'T> (startIdx:int, endIdx:int) =
+ inherit SeqComponent<'T,'T>()
+
+ let mutable count = 0
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ if count < startIdx then
+ count <- count + 1
+ false
+ elif count < endIdx then
+ count <- count + 1
+ output <- input
+ true
+ else
+ halted <- true
+ false
+
+ override __.OnComplete () =
+ if count < startIdx then
+ let x = startIdx - count
+ invalidOpFmt "tried to skip {0} {1} past the end of the seq"
+ [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+ elif count < endIdx then
+ let x = endIdx - count
+ invalidOpFmt "tried to take {0} {1} past the end of the seq"
+ [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+
+ type SeqProcessNextStates =
+ | NotStarted = 1
+ | Finished = 2
+ | InProcess = 3
+
+ type SeqEnumeratorEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) =
+ let mutable state = SeqProcessNextStates.NotStarted
+ let mutable current = Unchecked.defaultof<'U>
+ let mutable halted = false
+
+ let mutable source = enumerator
+
+ let rec moveNext () =
+ if (not halted) && source.MoveNext () then
+ if t2u.ProcessNext (source.Current, &halted, ¤t) then
+ true
+ else
+ moveNext ()
+ else
+ state <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IDisposable with
+ member x.Dispose():unit =
+ match source with
+ | null -> ()
+ | _ -> source.Dispose (); source <- Unchecked.defaultof<_>
+
+ interface IEnumerator with
+ member this.Current : obj = box (this:>IEnumerator<'U>).Current
+ member __.MoveNext () =
+ state <- SeqProcessNextStates.InProcess
+ moveNext ()
+ member __.Reset () : unit = noReset ()
+
+ interface IEnumerator<'U> with
+ member x.Current =
+ match state with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> ()
+ current
+
+ type SeqArrayEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) =
+ let mutable state = SeqProcessNextStates.NotStarted
+ let mutable current = Unchecked.defaultof<'U>
+ let mutable halted = false
+
+ let mutable idx = 0
+
+ let rec moveNext () =
+ if (not halted) && idx < array.Length then
+ idx <- idx+1
+ if t2u.ProcessNext (array.[idx-1], &halted, ¤t) then
+ true
+ else
+ moveNext ()
+ else
+ state <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IDisposable with
+ member x.Dispose() : unit = ()
+
+ interface IEnumerator with
+ member this.Current : obj = box (this:>IEnumerator<'U>).Current
+ member __.MoveNext () =
+ state <- SeqProcessNextStates.InProcess
+ moveNext ()
+ member __.Reset () : unit = noReset ()
+
+ interface IEnumerator<'U> with
+ member x.Current =
+ match state with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> ()
+ current
+
+ []
+ type ComposableEnumerable<'T> () =
+ abstract member Compose<'U> : (unit -> SeqComponent<'T,'U>) -> IEnumerable<'U>
+
+ type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:unit->SeqComponent<'T,'U>) =
+ inherit ComposableEnumerable<'U>()
+
+ let getEnumerator () : IEnumerator<'U> =
+ upcast (new SeqEnumeratorEnumerator<'T,'U>(enumerable.GetEnumerator(), current ()))
+
+ interface IEnumerable with
+ member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
+
+ override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
+ upcast new SeqEnumerable<'T,'V>(enumerable, fun () -> (current ()).Composer (next ()))
+
+ interface ISeqEnumerable<'U> with
+ member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let enumerator = enumerable.GetEnumerator ()
+ let components = current ()
+ let mutable output = Unchecked.defaultof<'U>
+ let mutable halt = false
+
+ let mutable state = initialState
+ while (not halt) && enumerator.MoveNext () do
+ if components.ProcessNext (enumerator.Current, &halt, &output) then
+ state <- folder'.Invoke (state, output)
+
+ state
+
+ type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:unit->SeqComponent<'T,'U>) =
+ inherit ComposableEnumerable<'U>()
+
+ let getEnumerator () : IEnumerator<'U> =
+ upcast (new SeqArrayEnumerator<'T,'U>(array, current ()))
+
+ interface IEnumerable with
+ member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
+
+ override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
+ upcast new SeqArrayEnumerable<'T,'V>(array, fun () -> (current ()).Composer (next ()))
+
+ interface ISeqEnumerable<'U> with
+ member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let mutable idx = 0
+ let components = current ()
+ let mutable current = Unchecked.defaultof<'U>
+ let mutable halt = false
+
+ let mutable state = initialState
+ while (not halt) && idx < array.Length do
+ if components.ProcessNext (array.[idx], &halt, ¤t) then
+ state <- folder'.Invoke(state, current)
+ idx <- idx + 1
+
+ state
+
+
#if FX_NO_ICLONEABLE
open Microsoft.FSharp.Core.ICloneableExtensions
@@ -1142,27 +1321,30 @@ namespace Microsoft.FSharp.Collections
let revamp3 f (ie1 : seq<_>) (source2 : seq<_>) (source3 : seq<_>) =
mkSeq (fun () -> f (ie1.GetEnumerator()) (source2.GetEnumerator()) (source3.GetEnumerator()))
- []
- let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> =
+ let private seqFactory createSeqComponent (source:seq<'T>) =
checkNonNull "source" source
match source with
- | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Filter f)
- | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Filter f))
+ | :? SeqComposer.ComposableEnumerable<'T> as s -> s.Compose createSeqComponent
+ | :? array<'T> as a -> upcast (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent))
+ | _ -> upcast (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent))
+
+ let private seqFactoryForImmutable seqComponent (source:seq<'T>) =
+ source |> seqFactory (fun () -> seqComponent)
+
+ []
+ let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> =
+ source |> seqFactoryForImmutable (SeqComposer.Filter f)
[]
let where f source = filter f source
[]
let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> =
- checkNonNull "source" source
- match source with
- | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Map f)
- | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Map f))
+ source |> seqFactoryForImmutable (SeqComposer.Map f)
[]
let mapi f source =
- checkNonNull "source" source
- revamp (IEnumerator.mapi f) source
+ source |> seqFactory (fun () -> upcast SeqComposer.Mapi f)
[]
let mapi2 f source1 source2 =
@@ -1246,16 +1428,10 @@ namespace Microsoft.FSharp.Collections
[]
let take count (source : seq<'T>) =
- checkNonNull "source" source
if count < 0 then invalidArgInputMustBeNonNegative "count" count
(* Note: don't create or dispose any IEnumerable if n = 0 *)
if count = 0 then empty else
- seq { use e = source.GetEnumerator()
- for x in 0 .. count - 1 do
- if not (e.MoveNext()) then
- invalidOpFmt "tried to take {0} {1} past the end of the seq"
- [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- yield e.Current }
+ source |> seqFactory (fun () -> upcast SeqComposer.Take count)
[]
let isEmpty (source : seq<'T>) =
@@ -1442,10 +1618,7 @@ namespace Microsoft.FSharp.Collections
[]
let pairwise<'T> (source:seq<'T>) : seq<'T*'T> =
- checkNonNull "source" source
- match source with
- | :? IEnumerator.SeqComposer.SeqEnumerableBase<'T> as s -> s.Compose (IEnumerator.SeqComposer.Pairwise ())
- | _ -> upcast (new IEnumerator.SeqComposer.SeqEnumerable<_,_>(source, IEnumerator.SeqComposer.Pairwise ()))
+ source |> seqFactory (fun () -> upcast SeqComposer.Pairwise ())
[]
let scan<'T,'State> f (z:'State) (source : seq<'T>) =
@@ -1883,14 +2056,7 @@ namespace Microsoft.FSharp.Collections
[]
let skip count (source: seq<_>) =
- checkNonNull "source" source
- seq { use e = source.GetEnumerator()
- for x in 1 .. count do
- if not (e.MoveNext()) then
- invalidOpFmt "tried to skip {0} {1} past the end of the seq"
- [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- while e.MoveNext() do
- yield e.Current }
+ source |> seqFactory (fun () -> upcast SeqComposer.Skip count)
[]
let skipWhile p (source: seq<_>) =
From 33864577d82714b73ff29ee53b664ce7dd4a5f3c Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Thu, 29 Sep 2016 18:49:22 +1000
Subject: [PATCH 004/327] Temporarily remove the ISeqEnumerable interface
It was causing build issues as it was currently unused.
---
src/fsharp/FSharp.Core/seq.fs | 66 +++++++++++++++++------------------
1 file changed, 33 insertions(+), 33 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 60282de76fe..0e1022bc3f1 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -812,8 +812,8 @@ namespace Microsoft.FSharp.Collections
[]
[]
module Seq =
- type ISeqEnumerable<'T> =
- abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State
+// type ISeqEnumerable<'T> =
+// abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State
module SeqComposer =
open IEnumerator
@@ -1152,21 +1152,21 @@ namespace Microsoft.FSharp.Collections
override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
upcast new SeqEnumerable<'T,'V>(enumerable, fun () -> (current ()).Composer (next ()))
- interface ISeqEnumerable<'U> with
- member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
- let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
-
- let enumerator = enumerable.GetEnumerator ()
- let components = current ()
- let mutable output = Unchecked.defaultof<'U>
- let mutable halt = false
-
- let mutable state = initialState
- while (not halt) && enumerator.MoveNext () do
- if components.ProcessNext (enumerator.Current, &halt, &output) then
- state <- folder'.Invoke (state, output)
-
- state
+// interface ISeqEnumerable<'U> with
+// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+//
+// let enumerator = enumerable.GetEnumerator ()
+// let components = current ()
+// let mutable output = Unchecked.defaultof<'U>
+// let mutable halt = false
+//
+// let mutable state = initialState
+// while (not halt) && enumerator.MoveNext () do
+// if components.ProcessNext (enumerator.Current, &halt, &output) then
+// state <- folder'.Invoke (state, output)
+//
+// state
type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:unit->SeqComponent<'T,'U>) =
inherit ComposableEnumerable<'U>()
@@ -1183,22 +1183,22 @@ namespace Microsoft.FSharp.Collections
override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
upcast new SeqArrayEnumerable<'T,'V>(array, fun () -> (current ()).Composer (next ()))
- interface ISeqEnumerable<'U> with
- member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
- let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
-
- let mutable idx = 0
- let components = current ()
- let mutable current = Unchecked.defaultof<'U>
- let mutable halt = false
-
- let mutable state = initialState
- while (not halt) && idx < array.Length do
- if components.ProcessNext (array.[idx], &halt, ¤t) then
- state <- folder'.Invoke(state, current)
- idx <- idx + 1
-
- state
+// interface ISeqEnumerable<'U> with
+// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+//
+// let mutable idx = 0
+// let components = current ()
+// let mutable current = Unchecked.defaultof<'U>
+// let mutable halt = false
+//
+// let mutable state = initialState
+// while (not halt) && idx < array.Length do
+// if components.ProcessNext (array.[idx], &halt, ¤t) then
+// state <- folder'.Invoke(state, current)
+// idx <- idx + 1
+//
+// state
From 8173087960f301c8ea886869172b1047139fa5fc Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Thu, 29 Sep 2016 19:59:49 +1000
Subject: [PATCH 005/327] Fixing halting on take
---
src/fsharp/FSharp.Core/seq.fs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 0e1022bc3f1..50f59dafef1 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -854,7 +854,7 @@ namespace Microsoft.FSharp.Collections
override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) :bool =
let mutable temp = Unchecked.defaultof<'U>
- if first.ProcessNext (input, &halted, &temp) && not halted then
+ if first.ProcessNext (input, &halted, &temp) then
second.ProcessNext (temp, &halted, &output)
else
false
@@ -1012,6 +1012,7 @@ namespace Microsoft.FSharp.Collections
if count < takeCount then
count <- count + 1
output <- input
+ halted <- count = takeCount
true
else
halted <- true
@@ -1037,6 +1038,7 @@ namespace Microsoft.FSharp.Collections
elif count < endIdx then
count <- count + 1
output <- input
+ halted <- count = endIdx
true
else
halted <- true
From 4beba0085a6dc0f09b95f8ec5300ced8bc46bd0d Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 2 Oct 2016 18:26:16 +1100
Subject: [PATCH 006/327] Return current as match of match statement for perf
*slight* performance improvement
---
src/fsharp/FSharp.Core/seq.fs | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 50f59dafef1..3910f3f6332 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1095,8 +1095,7 @@ namespace Microsoft.FSharp.Collections
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> ()
- current
+ | _ -> current
type SeqArrayEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) =
let mutable state = SeqProcessNextStates.NotStarted
@@ -1132,8 +1131,7 @@ namespace Microsoft.FSharp.Collections
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> ()
- current
+ | _ -> current
[]
type ComposableEnumerable<'T> () =
From f34b5000a504e595daedf3f0da98500a48c0b64e Mon Sep 17 00:00:00 2001
From: liboz
Date: Mon, 3 Oct 2016 16:34:00 -0400
Subject: [PATCH 007/327] renaming cleanup. Adding ListEnumerable. Adding
Choose
---
src/fsharp/FSharp.Core/seq.fs | 149 ++++++++++++++++++++++++----------
1 file changed, 104 insertions(+), 45 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 3910f3f6332..72d3bdaea04 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -833,21 +833,21 @@ namespace Microsoft.FSharp.Collections
abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
- abstract ComposeMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeFilter : Filter<'T> -> SeqComponent<'T,'U>
- abstract ComposeFilterMap<'S> : FilterMap<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeMapFilter<'S> : MapFilter<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeSkip : Skip<'T> -> SeqComponent<'T,'U>
+ abstract ComposeWithMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeWithFilter : Filter<'T> -> SeqComponent<'T,'U>
+ abstract ComposeWithFilterThenMap<'S> : FilterThenMap<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeWithMapThenFilter<'S> : MapThenFilter<'S,'T> -> SeqComponent<'S,'U>
+ abstract ComposeWithSkip : Skip<'T> -> SeqComponent<'T,'U>
default __.OnComplete () = ()
- default first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second)
+ default first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second)
- default second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
- default second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
+ default second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
+ default second.ComposeWithFilterThenMap<'S> (first:FilterThenMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeWithMapThenFilter<'S> (first:MapThenFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
+ default second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>()
@@ -870,16 +870,16 @@ namespace Microsoft.FSharp.Collections
inherit SeqComponent<'T,'U>()
override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> =
- second.ComposeMap first
+ second.ComposeWithMap first
- override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> =
+ override second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> =
upcast Map (first.Map >> second.Map)
- override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'U> =
- upcast FilterMap (first.Filter, second.Map)
+ override second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'U> =
+ upcast FilterThenMap (first.Filter, second.Map)
- override second.ComposeFilterMap<'S> (first:FilterMap<'S,'T>) : SeqComponent<'S,'U> =
- upcast FilterMap (first.Filter, first.Map >> second.Map)
+ override second.ComposeWithFilterThenMap<'S> (first:FilterThenMap<'S,'T>) : SeqComponent<'S,'U> =
+ upcast FilterThenMap (first.Filter, first.Map >> second.Map)
override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
output <- map input
@@ -902,17 +902,17 @@ namespace Microsoft.FSharp.Collections
and Filter<'T> (filter:'T->bool) =
inherit SeqComponent<'T,'T>()
- override this.Composer (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
- next.ComposeFilter this
+ override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
+ second.ComposeWithFilter first
- override second.ComposeMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> =
- upcast MapFilter (first.Map, second.Filter)
+ override second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> =
+ upcast MapThenFilter (first.Map, second.Filter)
- override second.ComposeFilter (first:Filter<'T>) : SeqComponent<'T,'T> =
+ override second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'T> =
upcast Filter (Helpers.ComposeFilter first.Filter second.Filter)
- override second.ComposeMapFilter<'S> (first:MapFilter<'S,'T>) : SeqComponent<'S,'T> =
- upcast MapFilter (first.Map, Helpers.ComposeFilter first.Filter second.Filter)
+ override second.ComposeWithMapThenFilter<'S> (first:MapThenFilter<'S,'T>) : SeqComponent<'S,'T> =
+ upcast MapThenFilter (first.Map, Helpers.ComposeFilter first.Filter second.Filter)
override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
if filter input then
@@ -923,7 +923,7 @@ namespace Microsoft.FSharp.Collections
member __.Filter :'T->bool = filter
- and MapFilter<'T,'U> (map:'T->'U, filter:'U->bool) =
+ and MapThenFilter<'T,'U> (map:'T->'U, filter:'U->bool) =
inherit SeqComponent<'T,'U>()
override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) :bool =
@@ -931,12 +931,12 @@ namespace Microsoft.FSharp.Collections
Helpers.avoidTailCall (filter output)
override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> =
- second.ComposeMapFilter first
+ second.ComposeWithMapThenFilter first
member __.Map : 'T->'U = map
member __.Filter : 'U->bool = filter
- and FilterMap<'T,'U> (filter:'T->bool, map:'T->'U) =
+ and FilterThenMap<'T,'U> (filter:'T->bool, map:'T->'U) =
inherit SeqComponent<'T,'U>()
override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
@@ -946,7 +946,7 @@ namespace Microsoft.FSharp.Collections
else
false
- override this.Composer (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.ComposeFilterMap this
+ override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = second.ComposeWithFilterThenMap first
member __.Filter : 'T->bool = filter
member __.Map : 'T->'U = map
@@ -973,10 +973,10 @@ namespace Microsoft.FSharp.Collections
let mutable count = 0
override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
- second.ComposeSkip first
+ second.ComposeWithSkip first
- override second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
- if System.Int32.MaxValue - second.SkipCount > first.SkipCount then
+ override second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
+ if Int32.MaxValue - first.SkipCount - second.SkipCount > 0 then
upcast Skip (first.SkipCount + second.SkipCount)
else
upcast Composed (first, second)
@@ -1002,9 +1002,9 @@ namespace Microsoft.FSharp.Collections
let mutable count = 0
- override second.ComposeSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
- if System.Int32.MaxValue - second.TakeCount > first.SkipCount then
- upcast SkipTake (first.SkipCount, first.SkipCount+second.TakeCount)
+ override second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
+ if Int32.MaxValue - first.SkipCount - second.TakeCount > 0 then
+ upcast SkipThenTake (first.SkipCount, first.SkipCount+second.TakeCount)
else
upcast Composed (first, second)
@@ -1026,7 +1026,7 @@ namespace Microsoft.FSharp.Collections
member __.TakeCount = takeCount
- and SkipTake<'T> (startIdx:int, endIdx:int) =
+ and SkipThenTake<'T> (startIdx:int, endIdx:int) =
inherit SeqComponent<'T,'T>()
let mutable count = 0
@@ -1053,13 +1053,22 @@ namespace Microsoft.FSharp.Collections
let x = endIdx - count
invalidOpFmt "tried to take {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+
+ and Choose<'T, 'U> (choose:'T->'U option) =
+ inherit SeqComponent<'T,'U>()
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
+ match choose input with
+ | Some value -> output <- value
+ true
+ | None -> false
type SeqProcessNextStates =
| NotStarted = 1
| Finished = 2
| InProcess = 3
- type SeqEnumeratorEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) =
+ type SeqComposedEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) =
let mutable state = SeqProcessNextStates.NotStarted
let mutable current = Unchecked.defaultof<'U>
let mutable halted = false
@@ -1078,7 +1087,7 @@ namespace Microsoft.FSharp.Collections
false
interface IDisposable with
- member x.Dispose():unit =
+ member __.Dispose():unit =
match source with
| null -> ()
| _ -> source.Dispose (); source <- Unchecked.defaultof<_>
@@ -1091,13 +1100,13 @@ namespace Microsoft.FSharp.Collections
member __.Reset () : unit = noReset ()
interface IEnumerator<'U> with
- member x.Current =
+ member __.Current =
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
| _ -> current
- type SeqArrayEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) =
+ type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) =
let mutable state = SeqProcessNextStates.NotStarted
let mutable current = Unchecked.defaultof<'U>
let mutable halted = false
@@ -1117,7 +1126,7 @@ namespace Microsoft.FSharp.Collections
false
interface IDisposable with
- member x.Dispose() : unit = ()
+ member __.Dispose() : unit = ()
interface IEnumerator with
member this.Current : obj = box (this:>IEnumerator<'U>).Current
@@ -1127,7 +1136,43 @@ namespace Microsoft.FSharp.Collections
member __.Reset () : unit = noReset ()
interface IEnumerator<'U> with
- member x.Current =
+ member __.Current =
+ match state with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> current
+
+ type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>) =
+ let mutable state = SeqProcessNextStates.NotStarted
+ let mutable current = Unchecked.defaultof<'U>
+ let mutable halted = false
+
+ let mutable list = alist
+
+ let rec moveNext () =
+ match halted, list with
+ | false, head::tail ->
+ list <- tail
+ if t2u.ProcessNext (head, &halted, ¤t) then
+ true
+ else
+ moveNext ()
+ | _ -> state <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IDisposable with
+ member __.Dispose() : unit = ()
+
+ interface IEnumerator with
+ member this.Current : obj = box (this:>IEnumerator<'U>).Current
+ member __.MoveNext () =
+ state <- SeqProcessNextStates.InProcess
+ moveNext ()
+ member __.Reset () : unit = noReset ()
+
+ interface IEnumerator<'U> with
+ member __.Current =
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
@@ -1141,7 +1186,7 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- upcast (new SeqEnumeratorEnumerator<'T,'U>(enumerable.GetEnumerator(), current ()))
+ upcast (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current ()))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
@@ -1172,7 +1217,7 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- upcast (new SeqArrayEnumerator<'T,'U>(array, current ()))
+ upcast (new ArrayComposedEnumerator<'T,'U>(array, current ()))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
@@ -1200,6 +1245,20 @@ namespace Microsoft.FSharp.Collections
//
// state
+ type SeqListEnumerable<'T,'U>(alist:list<'T>, current:unit->SeqComponent<'T,'U>) =
+ inherit ComposableEnumerable<'U>()
+
+ let getEnumerator () : IEnumerator<'U> =
+ upcast (new ListComposedEnumerator<'T,'U>(alist, current ()))
+
+ interface IEnumerable with
+ member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
+
+ override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
+ upcast new SeqListEnumerable<'T,'V>(alist, fun () -> (current ()).Composer (next ()))
#if FX_NO_ICLONEABLE
@@ -1326,6 +1385,7 @@ namespace Microsoft.FSharp.Collections
match source with
| :? SeqComposer.ComposableEnumerable<'T> as s -> s.Compose createSeqComponent
| :? array<'T> as a -> upcast (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent))
+ | :? list<'T> as a -> upcast (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent))
| _ -> upcast (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent))
let private seqFactoryForImmutable seqComponent (source:seq<'T>) =
@@ -1367,8 +1427,7 @@ namespace Microsoft.FSharp.Collections
[]
let choose f source =
- checkNonNull "source" source
- revamp (IEnumerator.choose f) source
+ source |> seqFactoryForImmutable (SeqComposer.Choose f)
[]
let indexed source =
From 96e4dc912b197e1ae4e6a49a5a5192cba001db30 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Tue, 4 Oct 2016 20:00:31 +1100
Subject: [PATCH 008/327] Remove unbox.any when upcasting to IEnumer(able|ator)
Thanks to @liboz for reminding me of the performance hit here. This is
noticeable when you have small collections to be iterated.
---
src/fsharp/FSharp.Core/seq.fs | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 72d3bdaea04..e2467d25473 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -827,6 +827,10 @@ namespace Microsoft.FSharp.Collections
let inline ComposeFilter f g x = f x && g x
+ let inline UpcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #)
+ let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #)
+ let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #)
+
type [] SeqComponent<'T,'U> () =
abstract ProcessNext : input:'T * halt:byref * output:byref<'U> -> bool
abstract OnComplete : unit -> unit
@@ -1093,7 +1097,7 @@ namespace Microsoft.FSharp.Collections
| _ -> source.Dispose (); source <- Unchecked.defaultof<_>
interface IEnumerator with
- member this.Current : obj = box (this:>IEnumerator<'U>).Current
+ member this.Current : obj = box (Helpers.UpcastEnumerator this).Current
member __.MoveNext () =
state <- SeqProcessNextStates.InProcess
moveNext ()
@@ -1129,7 +1133,7 @@ namespace Microsoft.FSharp.Collections
member __.Dispose() : unit = ()
interface IEnumerator with
- member this.Current : obj = box (this:>IEnumerator<'U>).Current
+ member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current
member __.MoveNext () =
state <- SeqProcessNextStates.InProcess
moveNext ()
@@ -1186,16 +1190,16 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- upcast (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current ()))
+ Helpers.UpcastEnumerator (new SeqEnumeratorEnumerator<'T,'U>(enumerable.GetEnumerator(), current ()))
interface IEnumerable with
- member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
+ member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
- upcast new SeqEnumerable<'T,'V>(enumerable, fun () -> (current ()).Composer (next ()))
+ Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, fun () -> (current ()).Composer (next ())))
// interface ISeqEnumerable<'U> with
// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
@@ -1217,16 +1221,16 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- upcast (new ArrayComposedEnumerator<'T,'U>(array, current ()))
+ Helpers.UpcastEnumerator (new SeqArrayEnumerator<'T,'U>(array, current ()))
interface IEnumerable with
- member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
+ member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
- upcast new SeqArrayEnumerable<'T,'V>(array, fun () -> (current ()).Composer (next ()))
+ Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, fun () -> (current ()).Composer (next ())))
// interface ISeqEnumerable<'U> with
// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
@@ -1384,9 +1388,9 @@ namespace Microsoft.FSharp.Collections
checkNonNull "source" source
match source with
| :? SeqComposer.ComposableEnumerable<'T> as s -> s.Compose createSeqComponent
- | :? array<'T> as a -> upcast (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent))
- | :? list<'T> as a -> upcast (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent))
- | _ -> upcast (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent))
+ | :? array<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent))
+ | :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent))
+ | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent))
let private seqFactoryForImmutable seqComponent (source:seq<'T>) =
source |> seqFactory (fun () -> seqComponent)
From 12fbe9946c0a12ec079736df8e1c27956e157703 Mon Sep 17 00:00:00 2001
From: liboz
Date: Tue, 4 Oct 2016 22:13:24 -0400
Subject: [PATCH 009/327] remove old mapi function
---
src/fsharp/FSharp.Core/seq.fs | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index e2467d25473..75588427834 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -107,21 +107,6 @@ namespace Microsoft.FSharp.Collections
interface System.IDisposable with
member this.Dispose() = this.Dispose()
- let mapi f (e : IEnumerator<_>) : IEnumerator<_> =
- let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
- let i = ref (-1)
- upcast
- { new MapEnumerator<_>() with
- member this.DoMoveNext curr =
- i := !i + 1
- if e.MoveNext() then
- curr <- f.Invoke(!i, e.Current)
- true
- else
- false
- member this.Dispose() = e.Dispose()
- }
-
let map2 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) : IEnumerator<_>=
let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
upcast
From a294c86f55de9e9ee36ea661161152017c136ce5 Mon Sep 17 00:00:00 2001
From: liboz
Date: Wed, 5 Oct 2016 10:09:17 -0400
Subject: [PATCH 010/327] skipwhile/takewhile
---
src/fsharp/FSharp.Core/seq.fs | 46 +++++++++++++++++++++++------------
1 file changed, 31 insertions(+), 15 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 75588427834..3d1b6a0903c 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1042,7 +1042,35 @@ namespace Microsoft.FSharp.Collections
let x = endIdx - count
invalidOpFmt "tried to take {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
-
+
+ and SkipWhile<'T> (predicate: 'T -> bool) =
+ inherit SeqComponent<'T,'T>()
+
+ let mutable skip = true
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ if skip then
+ skip <- predicate input
+ if skip then
+ false
+ else
+ output <- input
+ true
+ else
+ output <- input
+ true
+
+ and TakeWhile<'T> (predicate: 'T -> bool) =
+ inherit SeqComponent<'T,'T>()
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ if predicate input then
+ output <- input
+ true
+ else
+ halted <- true
+ false
+
and Choose<'T, 'U> (choose:'T->'U option) =
inherit SeqComponent<'T,'U>()
@@ -2096,11 +2124,7 @@ namespace Microsoft.FSharp.Collections
*)
[]
let takeWhile p (source: seq<_>) =
- checkNonNull "source" source
- seq { use e = source.GetEnumerator()
- let latest = ref Unchecked.defaultof<_>
- while e.MoveNext() && (latest := e.Current; p !latest) do
- yield !latest }
+ source |> seqFactory (fun () -> upcast SeqComposer.TakeWhile p)
[]
let skip count (source: seq<_>) =
@@ -2108,15 +2132,7 @@ namespace Microsoft.FSharp.Collections
[]
let skipWhile p (source: seq<_>) =
- checkNonNull "source" source
- seq { use e = source.GetEnumerator()
- let latest = ref (Unchecked.defaultof<_>)
- let ok = ref false
- while e.MoveNext() do
- if (latest := e.Current; (!ok || not (p !latest))) then
- ok := true
- yield !latest }
-
+ source |> seqFactory (fun () -> upcast SeqComposer.SkipWhile p)
[]
let forall2 p (source1: seq<_>) (source2: seq<_>) =
From 19879ea4e18b1ade29a76f6c9711df75b457f58b Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Fri, 7 Oct 2016 20:18:45 +1100
Subject: [PATCH 011/327] Changes SeqComposer to build bottom-up
A more direct calling process. Slows things down *slightly* when only a
single item is being processed, but is a better model to build from
going forward.
---
src/fsharp/FSharp.Core/seq.fs | 319 +++++++++++++---------------------
1 file changed, 125 insertions(+), 194 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 3d1b6a0903c..4936a6bf0a4 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -816,167 +816,137 @@ namespace Microsoft.FSharp.Collections
let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #)
let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #)
- type [] SeqComponent<'T,'U> () =
- abstract ProcessNext : input:'T * halt:byref * output:byref<'U> -> bool
- abstract OnComplete : unit -> unit
+ type [] SeqComponentFactory<'T,'U> () =
+ abstract Create<'V> : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
+
+ member __.Compose<'V> (next:SeqComponent<'U,'V>) = Unchecked.defaultof<_>
- abstract Composer : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
+ and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) =
+ inherit SeqComponentFactory<'T,'V> ()
+ override __.Create<'W> (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create (second.Create next)
- abstract ComposeWithMap<'S> : Map<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeWithFilter : Filter<'T> -> SeqComponent<'T,'U>
- abstract ComposeWithFilterThenMap<'S> : FilterThenMap<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeWithMapThenFilter<'S> : MapThenFilter<'S,'T> -> SeqComponent<'S,'U>
- abstract ComposeWithSkip : Skip<'T> -> SeqComponent<'T,'U>
+ and MapFactory<'T,'U> (map:'T->'U) =
+ inherit SeqComponentFactory<'T,'U> ()
+ override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
- default __.OnComplete () = ()
+ and MapiFactory<'T,'U> (mapi:int->'T->'U) =
+ inherit SeqComponentFactory<'T,'U> ()
+ override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
- default first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Composed (first, second)
+ and FilterFactory<'T> (filter:'T->bool) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Filter (filter, next)
- default second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
- default second.ComposeWithFilterThenMap<'S> (first:FilterThenMap<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeWithMapThenFilter<'S> (first:MapThenFilter<'S,'T>) : SeqComponent<'S,'U> = upcast Composed (first, second)
- default second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'U> = upcast Composed (first, second)
+ and PairwiseFactory<'T> () =
+ inherit SeqComponentFactory<'T,'T*'T> ()
+ override __.Create<'V> (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next
- and Composed<'T,'U,'V> (first:SeqComponent<'T,'U>, second:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
+ and SkipFactory<'T> (count:int) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) :bool =
- let mutable temp = Unchecked.defaultof<'U>
- if first.ProcessNext (input, &halted, &temp) then
- second.ProcessNext (temp, &halted, &output)
- else
- false
+ and SkipWhileFactory<'T> (perdicate:'T->bool) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
- override __.Composer (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> =
- upcast Composed (first, second.Composer next)
+ and TakeWhileFactory<'T> (perdicate:'T->bool) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, next)
- override __.OnComplete () =
- first.OnComplete ()
- second.OnComplete ()
+ and TakeFactory<'T> (count:int) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, next)
- and Map<'T,'U> (map:'T->'U) =
- inherit SeqComponent<'T,'U>()
+ and ChooseFactory<'T,'U> (filter:'T->option<'U>) =
+ inherit SeqComponentFactory<'T,'U> ()
+ override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
- override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> =
- second.ComposeWithMap first
+ and [] SeqComponent<'T,'U> () =
+ abstract ProcessNext : input:'T * halt:byref * output:byref<'U> -> bool
+ abstract OnComplete : unit -> unit
- override second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'U> =
- upcast Map (first.Map >> second.Map)
-
- override second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'U> =
- upcast FilterThenMap (first.Filter, second.Map)
+ abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U>
+ abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U>
- override second.ComposeWithFilterThenMap<'S> (first:FilterThenMap<'S,'T>) : SeqComponent<'S,'U> =
- upcast FilterThenMap (first.Filter, first.Map >> second.Map)
+ default __.OnComplete () = ()
- override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
- output <- map input
- true
+ default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this)
+ default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this)
- member __.Map : 'T->'U = map
+ and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'T,'V>()
- and Mapi<'T,'U> (mapi:int->'T->'U) =
- inherit SeqComponent<'T,'U>()
+ default this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next)
- let mutable idx = 0
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
+ next.ProcessNext (map input, &halted, &output)
- override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
- output <- mapi idx input
- idx <- idx + 1
- true
+ and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'T,'V>()
- member __.Mapi : int->'T->'U = mapi
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
+ let u = map input
+ if filter u then
+ next.ProcessNext (u, &halted, &output)
+ else
+ false
- and Filter<'T> (filter:'T->bool) =
- inherit SeqComponent<'T,'T>()
+ and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'T,'V>()
- override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
- second.ComposeWithFilter first
+ let mutable idx = 0
- override second.ComposeWithMap<'S> (first:Map<'S,'T>) : SeqComponent<'S,'T> =
- upcast MapThenFilter (first.Map, second.Filter)
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
+ idx <- idx + 1
+ next.ProcessNext(mapi (idx-1) input, &halted, &output)
- override second.ComposeWithFilter (first:Filter<'T>) : SeqComponent<'T,'T> =
- upcast Filter (Helpers.ComposeFilter first.Filter second.Filter)
+ and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>()
- override second.ComposeWithMapThenFilter<'S> (first:MapThenFilter<'S,'T>) : SeqComponent<'S,'T> =
- upcast MapThenFilter (first.Map, Helpers.ComposeFilter first.Filter second.Filter)
+ default this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next)
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
if filter input then
- output <- input
- true
+ next.ProcessNext (input, &halted, &output)
else
false
- member __.Filter :'T->bool = filter
-
- and MapThenFilter<'T,'U> (map:'T->'U, filter:'U->bool) =
- inherit SeqComponent<'T,'U>()
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) :bool =
- output <- map input
- Helpers.avoidTailCall (filter output)
-
- override first.Composer (second:SeqComponent<'U,'V>):SeqComponent<'T,'V> =
- second.ComposeWithMapThenFilter first
-
- member __.Map : 'T->'U = map
- member __.Filter : 'U->bool = filter
-
- and FilterThenMap<'T,'U> (filter:'T->bool, map:'T->'U) =
- inherit SeqComponent<'T,'U>()
+ and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'T,'V>()
- override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
if filter input then
- output <- map input
- true
+ next.ProcessNext (map input, &halted, &output)
else
false
- override first.Composer (second:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = second.ComposeWithFilterThenMap first
-
- member __.Filter : 'T->bool = filter
- member __.Map : 'T->'U = map
-
- and Pairwise<'T> () =
- inherit SeqComponent<'T,'T*'T>()
+ and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) =
+ inherit SeqComponent<'T,'V>()
let mutable isFirst = true
let mutable lastValue = Unchecked.defaultof<'T>
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T*'T>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
if isFirst then
lastValue <- input
isFirst <- false
false
else
- output <- lastValue, input
+ let currentPair = lastValue, input
lastValue <- input
- true
+ next.ProcessNext(currentPair, &halted, &output)
- and Skip<'T> (skipCount:int) =
- inherit SeqComponent<'T,'T>()
+ and Skip<'T,'V> (skipCount:int, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>()
let mutable count = 0
- override first.Composer (second:SeqComponent<'T,'V>) : SeqComponent<'T,'V> =
- second.ComposeWithSkip first
-
- override second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
- if Int32.MaxValue - first.SkipCount - second.SkipCount > 0 then
- upcast Skip (first.SkipCount + second.SkipCount)
- else
- upcast Composed (first, second)
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
if count < skipCount then
count <- count + 1
false
else
- output <- input
- true
+ next.ProcessNext (input, &halted, &output)
override __.OnComplete () =
if count < skipCount then
@@ -984,25 +954,16 @@ namespace Microsoft.FSharp.Collections
invalidOpFmt "tried to skip {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- member __.SkipCount = skipCount
-
- and Take<'T> (takeCount:int) =
- inherit SeqComponent<'T,'T>()
+ and Take<'T,'V> (takeCount:int, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>()
let mutable count = 0
- override second.ComposeWithSkip (first:Skip<'T>) : SeqComponent<'T,'T> =
- if Int32.MaxValue - first.SkipCount - second.TakeCount > 0 then
- upcast SkipThenTake (first.SkipCount, first.SkipCount+second.TakeCount)
- else
- upcast Composed (first, second)
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
if count < takeCount then
count <- count + 1
- output <- input
halted <- count = takeCount
- true
+ next.ProcessNext (input, &halted, &output)
else
halted <- true
false
@@ -1013,73 +974,46 @@ namespace Microsoft.FSharp.Collections
invalidOpFmt "tried to take {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- member __.TakeCount = takeCount
-
- and SkipThenTake<'T> (startIdx:int, endIdx:int) =
- inherit SeqComponent<'T,'T>()
-
- let mutable count = 0
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
- if count < startIdx then
- count <- count + 1
- false
- elif count < endIdx then
- count <- count + 1
- output <- input
- halted <- count = endIdx
- true
- else
- halted <- true
- false
-
- override __.OnComplete () =
- if count < startIdx then
- let x = startIdx - count
- invalidOpFmt "tried to skip {0} {1} past the end of the seq"
- [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- elif count < endIdx then
- let x = endIdx - count
- invalidOpFmt "tried to take {0} {1} past the end of the seq"
- [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
-
- and SkipWhile<'T> (predicate: 'T -> bool) =
- inherit SeqComponent<'T,'T>()
+ and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>()
let mutable skip = true
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
if skip then
skip <- predicate input
if skip then
false
else
- output <- input
- true
+ next.ProcessNext (input, &halted, &output)
else
- output <- input
- true
+ next.ProcessNext (input, &halted, &output)
- and TakeWhile<'T> (predicate: 'T -> bool) =
- inherit SeqComponent<'T,'T>()
+ and TakeWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>()
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
if predicate input then
- output <- input
- true
+ next.ProcessNext(input, &halted, &output)
else
halted <- true
false
- and Choose<'T, 'U> (choose:'T->'U option) =
- inherit SeqComponent<'T,'U>()
+ and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'T,'V>()
- override __.ProcessNext (input:'T, halted:byref, output:byref<'U>) : bool =
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
match choose input with
- | Some value -> output <- value
- true
+ | Some value -> next.ProcessNext (value, &halted, &output)
| None -> false
+ and Tail<'T> () =
+ inherit SeqComponent<'T,'T>()
+
+ override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
+ output <- input
+ true
+
type SeqProcessNextStates =
| NotStarted = 1
| Finished = 2
@@ -1197,13 +1131,13 @@ namespace Microsoft.FSharp.Collections
[]
type ComposableEnumerable<'T> () =
- abstract member Compose<'U> : (unit -> SeqComponent<'T,'U>) -> IEnumerable<'U>
+ abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
- type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:unit->SeqComponent<'T,'U>) =
+ type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- Helpers.UpcastEnumerator (new SeqEnumeratorEnumerator<'T,'U>(enumerable.GetEnumerator(), current ()))
+ Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create (Tail ())))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
@@ -1211,8 +1145,8 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
- override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, fun () -> (current ()).Composer (next ())))
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, ComposedFactory (current, next)))
// interface ISeqEnumerable<'U> with
// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
@@ -1230,11 +1164,11 @@ namespace Microsoft.FSharp.Collections
//
// state
- type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:unit->SeqComponent<'T,'U>) =
+ type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- Helpers.UpcastEnumerator (new SeqArrayEnumerator<'T,'U>(array, current ()))
+ Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create (Tail ())))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
@@ -1242,8 +1176,8 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
- override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, fun () -> (current ()).Composer (next ())))
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, ComposedFactory (current, next)))
// interface ISeqEnumerable<'U> with
// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
@@ -1262,11 +1196,11 @@ namespace Microsoft.FSharp.Collections
//
// state
- type SeqListEnumerable<'T,'U>(alist:list<'T>, current:unit->SeqComponent<'T,'U>) =
+ type SeqListEnumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- upcast (new ListComposedEnumerator<'T,'U>(alist, current ()))
+ Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create (Tail ())))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
@@ -1274,8 +1208,8 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
- override __.Compose (next:unit->SeqComponent<'U,'V>) : IEnumerable<'V> =
- upcast new SeqListEnumerable<'T,'V>(alist, fun () -> (current ()).Composer (next ()))
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next)))
#if FX_NO_ICLONEABLE
@@ -1405,23 +1339,20 @@ namespace Microsoft.FSharp.Collections
| :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent))
| _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent))
- let private seqFactoryForImmutable seqComponent (source:seq<'T>) =
- source |> seqFactory (fun () -> seqComponent)
-
[]
let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> =
- source |> seqFactoryForImmutable (SeqComposer.Filter f)
+ source |> seqFactory (SeqComposer.FilterFactory f)
[]
let where f source = filter f source
[]
let map<'T,'U> (f:'T->'U) (source:seq<'T>) : seq<'U> =
- source |> seqFactoryForImmutable (SeqComposer.Map f)
+ source |> seqFactory (SeqComposer.MapFactory f)
[]
let mapi f source =
- source |> seqFactory (fun () -> upcast SeqComposer.Mapi f)
+ source |> seqFactory (SeqComposer.MapiFactory f)
[]
let mapi2 f source1 source2 =
@@ -1444,7 +1375,7 @@ namespace Microsoft.FSharp.Collections
[]
let choose f source =
- source |> seqFactoryForImmutable (SeqComposer.Choose f)
+ source |> seqFactory (SeqComposer.ChooseFactory f)
[]
let indexed source =
@@ -1507,7 +1438,7 @@ namespace Microsoft.FSharp.Collections
if count < 0 then invalidArgInputMustBeNonNegative "count" count
(* Note: don't create or dispose any IEnumerable if n = 0 *)
if count = 0 then empty else
- source |> seqFactory (fun () -> upcast SeqComposer.Take count)
+ source |> seqFactory (SeqComposer.TakeFactory count)
[]
let isEmpty (source : seq<'T>) =
@@ -1694,7 +1625,7 @@ namespace Microsoft.FSharp.Collections
[]
let pairwise<'T> (source:seq<'T>) : seq<'T*'T> =
- source |> seqFactory (fun () -> upcast SeqComposer.Pairwise ())
+ source |> seqFactory (SeqComposer.PairwiseFactory ())
[]
let scan<'T,'State> f (z:'State) (source : seq<'T>) =
@@ -2124,15 +2055,15 @@ namespace Microsoft.FSharp.Collections
*)
[]
let takeWhile p (source: seq<_>) =
- source |> seqFactory (fun () -> upcast SeqComposer.TakeWhile p)
+ source |> seqFactory (SeqComposer.TakeWhileFactory p)
[]
let skip count (source: seq<_>) =
- source |> seqFactory (fun () -> upcast SeqComposer.Skip count)
+ source |> seqFactory (SeqComposer.SkipFactory count)
[]
let skipWhile p (source: seq<_>) =
- source |> seqFactory (fun () -> upcast SeqComposer.SkipWhile p)
+ source |> seqFactory (SeqComposer.SkipWhileFactory p)
[]
let forall2 p (source1: seq<_>) (source2: seq<_>) =
From 896f01d2d3726bd147ccb8c13341ccf4df8c8f01 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Fri, 7 Oct 2016 20:30:18 +1100
Subject: [PATCH 012/327] Remove unused member
---
src/fsharp/FSharp.Core/seq.fs | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 4936a6bf0a4..97e0c919788 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -818,8 +818,6 @@ namespace Microsoft.FSharp.Collections
type [] SeqComponentFactory<'T,'U> () =
abstract Create<'V> : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
-
- member __.Compose<'V> (next:SeqComponent<'U,'V>) = Unchecked.defaultof<_>
and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) =
inherit SeqComponentFactory<'T,'V> ()
From ed56658be342232985581c5f401b7d5a1a769383 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sat, 8 Oct 2016 06:55:59 +1100
Subject: [PATCH 013/327] Simplified ProcessNext call by creating Result object
Due to the bottom-up build process I now have a consistent output
signature, which allowed it to be wrapped in an single object rather
than being passed up and down the chain of ProcessNext calls.
---
src/fsharp/FSharp.Core/seq.fs | 222 +++++++++++++++++-----------------
1 file changed, 114 insertions(+), 108 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 97e0c919788..2608ce8a27e 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -816,107 +816,123 @@ namespace Microsoft.FSharp.Collections
let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #)
let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #)
+ type Result<'T>() =
+ let mutable halted = false
+
+ member __.StopFurtherProcessing () = halted <- true
+ member __.Halted = halted
+
+ member val Current = Unchecked.defaultof<'T> with get, set
+
type [] SeqComponentFactory<'T,'U> () =
- abstract Create<'V> : SeqComponent<'U,'V> -> SeqComponent<'T,'V>
+ abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V>
and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) =
inherit SeqComponentFactory<'T,'V> ()
- override __.Create<'W> (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create (second.Create next)
+ override __.Create<'W> (result:Result<'W>) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create result (second.Create result next)
+
+ and ChooseFactory<'T,'U> (filter:'T->option<'U>) =
+ inherit SeqComponentFactory<'T,'U> ()
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
+
+ and FilterFactory<'T> (filter:'T->bool) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter
and MapFactory<'T,'U> (map:'T->'U) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
and MapiFactory<'T,'U> (mapi:int->'T->'U) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
-
- and FilterFactory<'T> (filter:'T->bool) =
- inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Filter (filter, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
and PairwiseFactory<'T> () =
inherit SeqComponentFactory<'T,'T*'T> ()
- override __.Create<'V> (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next
and SkipFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
and SkipWhileFactory<'T> (perdicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
and TakeWhileFactory<'T> (perdicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, next)
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, result, next)
and TakeFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, next)
-
- and ChooseFactory<'T,'U> (filter:'T->option<'U>) =
- inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next)
and [] SeqComponent<'T,'U> () =
- abstract ProcessNext : input:'T * halt:byref * output:byref<'U> -> bool
+ abstract ProcessNext : input:'T -> bool
abstract OnComplete : unit -> unit
- abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U>
- abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U>
+ abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U>
+ abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U>
default __.OnComplete () = ()
- default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this)
- default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this)
+ default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this)
+ default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this)
- and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) =
+ and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>()
- default this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next)
+ override __.ProcessNext (input:'T) : bool =
+ match choose input with
+ | Some value -> Helpers.avoidTailCall (next.ProcessNext value)
+ | None -> false
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
- next.ProcessNext (map input, &halted, &output)
+ and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>()
- and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) =
+ default this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next)
+
+ override __.ProcessNext (input:'T) : bool =
+ if filter input then
+ Helpers.avoidTailCall (next.ProcessNext input)
+ else
+ false
+
+ and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>()
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
- let u = map input
- if filter u then
- next.ProcessNext (u, &halted, &output)
+ override __.ProcessNext (input:'T) : bool =
+ if filter input then
+ Helpers.avoidTailCall (next.ProcessNext (map input))
else
false
- and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqComponent<'U,'V>) =
+ and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>()
- let mutable idx = 0
+ override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next)
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
- idx <- idx + 1
- next.ProcessNext(mapi (idx-1) input, &halted, &output)
+ override __.ProcessNext (input:'T) : bool =
+ Helpers.avoidTailCall (next.ProcessNext (map input))
- and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) =
+ and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>()
- default this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next)
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
- if filter input then
- next.ProcessNext (input, &halted, &output)
+ override __.ProcessNext (input:'T) : bool =
+ let u = map input
+ if filter u then
+ Helpers.avoidTailCall (next.ProcessNext u)
else
false
- and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqComponent<'U,'V>) =
+ and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>()
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
- if filter input then
- next.ProcessNext (map input, &halted, &output)
- else
- false
+ let mutable idx = 0
+
+ override __.ProcessNext (input:'T) : bool =
+ idx <- idx + 1
+ Helpers.avoidTailCall (next.ProcessNext (mapi (idx-1) input))
and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) =
inherit SeqComponent<'T,'V>()
@@ -924,7 +940,7 @@ namespace Microsoft.FSharp.Collections
let mutable isFirst = true
let mutable lastValue = Unchecked.defaultof<'T>
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
+ override __.ProcessNext (input:'T) : bool =
if isFirst then
lastValue <- input
isFirst <- false
@@ -932,19 +948,19 @@ namespace Microsoft.FSharp.Collections
else
let currentPair = lastValue, input
lastValue <- input
- next.ProcessNext(currentPair, &halted, &output)
+ Helpers.avoidTailCall (next.ProcessNext currentPair)
and Skip<'T,'V> (skipCount:int, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
let mutable count = 0
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
+ override __.ProcessNext (input:'T) : bool =
if count < skipCount then
count <- count + 1
false
else
- next.ProcessNext (input, &halted, &output)
+ Helpers.avoidTailCall (next.ProcessNext input)
override __.OnComplete () =
if count < skipCount then
@@ -952,18 +968,34 @@ namespace Microsoft.FSharp.Collections
invalidOpFmt "tried to skip {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- and Take<'T,'V> (takeCount:int, next:SeqComponent<'T,'V>) =
+ and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>()
+
+ let mutable skip = true
+
+ override __.ProcessNext (input:'T) : bool =
+ if skip then
+ skip <- predicate input
+ if skip then
+ false
+ else
+ Helpers.avoidTailCall (next.ProcessNext input)
+ else
+ Helpers.avoidTailCall (next.ProcessNext input)
+
+ and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
let mutable count = 0
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
+ override __.ProcessNext (input:'T) : bool =
if count < takeCount then
count <- count + 1
- halted <- count = takeCount
- next.ProcessNext (input, &halted, &output)
+ if count = takeCount then
+ result.StopFurtherProcessing ()
+ next.ProcessNext input
else
- halted <- true
+ result.StopFurtherProcessing ()
false
override __.OnComplete () =
@@ -972,44 +1004,21 @@ namespace Microsoft.FSharp.Collections
invalidOpFmt "tried to take {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) =
+ and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
- let mutable skip = true
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
- if skip then
- skip <- predicate input
- if skip then
- false
- else
- next.ProcessNext (input, &halted, &output)
- else
- next.ProcessNext (input, &halted, &output)
-
- and TakeWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) =
- inherit SeqComponent<'T,'V>()
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
+ override __.ProcessNext (input:'T) : bool =
if predicate input then
- next.ProcessNext(input, &halted, &output)
+ next.ProcessNext input
else
- halted <- true
+ result.StopFurtherProcessing ()
false
- and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
-
- override __.ProcessNext (input:'T, halted:byref, output:byref<'V>) : bool =
- match choose input with
- | Some value -> next.ProcessNext (value, &halted, &output)
- | None -> false
-
- and Tail<'T> () =
+ and Tail<'T> (result:Result<'T>) =
inherit SeqComponent<'T,'T>()
- override __.ProcessNext (input:'T, halted:byref, output:byref<'T>) : bool =
- output <- input
+ override __.ProcessNext (input:'T) : bool =
+ result.Current <- input
true
type SeqProcessNextStates =
@@ -1017,16 +1026,14 @@ namespace Microsoft.FSharp.Collections
| Finished = 2
| InProcess = 3
- type SeqComposedEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>) =
+ type SeqComposedEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
let mutable state = SeqProcessNextStates.NotStarted
- let mutable current = Unchecked.defaultof<'U>
- let mutable halted = false
let mutable source = enumerator
let rec moveNext () =
- if (not halted) && source.MoveNext () then
- if t2u.ProcessNext (source.Current, &halted, ¤t) then
+ if (not result.Halted) && source.MoveNext () then
+ if t2u.ProcessNext source.Current then
true
else
moveNext ()
@@ -1053,19 +1060,17 @@ namespace Microsoft.FSharp.Collections
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> current
+ | _ -> result.Current
- type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>) =
+ type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
let mutable state = SeqProcessNextStates.NotStarted
- let mutable current = Unchecked.defaultof<'U>
- let mutable halted = false
let mutable idx = 0
let rec moveNext () =
- if (not halted) && idx < array.Length then
+ if (not result.Halted) && idx < array.Length then
idx <- idx+1
- if t2u.ProcessNext (array.[idx-1], &halted, ¤t) then
+ if t2u.ProcessNext array.[idx-1] then
true
else
moveNext ()
@@ -1089,20 +1094,18 @@ namespace Microsoft.FSharp.Collections
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> current
+ | _ -> result.Current
- type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>) =
+ type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
let mutable state = SeqProcessNextStates.NotStarted
- let mutable current = Unchecked.defaultof<'U>
- let mutable halted = false
let mutable list = alist
let rec moveNext () =
- match halted, list with
+ match result.Halted, list with
| false, head::tail ->
list <- tail
- if t2u.ProcessNext (head, &halted, ¤t) then
+ if t2u.ProcessNext head then
true
else
moveNext ()
@@ -1125,7 +1128,7 @@ namespace Microsoft.FSharp.Collections
match state with
| SeqProcessNextStates.NotStarted -> notStarted()
| SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> current
+ | _ -> result.Current
[]
type ComposableEnumerable<'T> () =
@@ -1135,7 +1138,8 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create (Tail ())))
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
@@ -1166,7 +1170,8 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create (Tail ())))
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
@@ -1198,7 +1203,8 @@ namespace Microsoft.FSharp.Collections
inherit ComposableEnumerable<'U>()
let getEnumerator () : IEnumerator<'U> =
- Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create (Tail ())))
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result))
interface IEnumerable with
member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
From 72a651aef1125282c36566d8dda4cd40cdbc8556 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sat, 8 Oct 2016 10:36:05 +1100
Subject: [PATCH 014/327] default -> override
---
src/fsharp/FSharp.Core/seq.fs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 2608ce8a27e..d79d81945f1 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -890,7 +890,7 @@ namespace Microsoft.FSharp.Collections
and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
- default this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next)
+ override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next)
override __.ProcessNext (input:'T) : bool =
if filter input then
From 512f90d0b5ca13667ce1bd34ee7f8017e03105fe Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sat, 8 Oct 2016 19:35:08 +1100
Subject: [PATCH 015/327] OptimizedClosure for mapi
---
src/fsharp/FSharp.Core/seq.fs | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index d79d81945f1..04d763c1c79 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -929,10 +929,11 @@ namespace Microsoft.FSharp.Collections
inherit SeqComponent<'T,'V>()
let mutable idx = 0
+ let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi
override __.ProcessNext (input:'T) : bool =
idx <- idx + 1
- Helpers.avoidTailCall (next.ProcessNext (mapi (idx-1) input))
+ Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input)))
and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) =
inherit SeqComponent<'T,'V>()
@@ -1155,14 +1156,14 @@ namespace Microsoft.FSharp.Collections
// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
//
// let enumerator = enumerable.GetEnumerator ()
-// let components = current ()
-// let mutable output = Unchecked.defaultof<'U>
-// let mutable halt = false
+// let result = Result<'U> ()
+//
+// let components = current.Create result (Tail result)
//
// let mutable state = initialState
-// while (not halt) && enumerator.MoveNext () do
-// if components.ProcessNext (enumerator.Current, &halt, &output) then
-// state <- folder'.Invoke (state, output)
+// while (not result.Halted) && enumerator.MoveNext () do
+// if components.ProcessNext (enumerator.Current) then
+// state <- folder'.Invoke (state, result.Current)
//
// state
@@ -1187,14 +1188,13 @@ namespace Microsoft.FSharp.Collections
// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
//
// let mutable idx = 0
-// let components = current ()
-// let mutable current = Unchecked.defaultof<'U>
-// let mutable halt = false
+// let result = Result<'U> ()
+// let components = current.Create result (Tail result)
//
// let mutable state = initialState
-// while (not halt) && idx < array.Length do
-// if components.ProcessNext (array.[idx], &halt, ¤t) then
-// state <- folder'.Invoke(state, current)
+// while (not result.Halted) && idx < array.Length do
+// if components.ProcessNext array.[idx] then
+// state <- folder'.Invoke(state, result.Current)
// idx <- idx + 1
//
// state
From 61d886a76bf9db9e945d9c4bfdec1dd2c1ca5a71 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sat, 8 Oct 2016 20:19:46 +1100
Subject: [PATCH 016/327] Consolidated code in base class ensuring performance
Retained MoveNext in derived class to ensure we didn't add an extra
virtual call into the call stack.
---
src/fsharp/FSharp.Core/seq.fs | 144 ++++++++++++++--------------------
1 file changed, 60 insertions(+), 84 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 04d763c1c79..b29e64202a8 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -816,9 +816,16 @@ namespace Microsoft.FSharp.Collections
let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #)
let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #)
+ type SeqProcessNextStates =
+ | NotStarted = 1
+ | Finished = 2
+ | InProcess = 3
+
type Result<'T>() =
let mutable halted = false
+ member val SeqState = SeqProcessNextStates.NotStarted with get, set
+
member __.StopFurtherProcessing () = halted <- true
member __.Halted = halted
@@ -1022,15 +1029,25 @@ namespace Microsoft.FSharp.Collections
result.Current <- input
true
- type SeqProcessNextStates =
- | NotStarted = 1
- | Finished = 2
- | InProcess = 3
+ []
+ type ComposedEnumerator<'T>(result:Result<'T>) =
+ interface IDisposable with
+ member __.Dispose() : unit = ()
- type SeqComposedEnumerator<'T,'U>(enumerator:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- let mutable state = SeqProcessNextStates.NotStarted
+ interface IEnumerator with
+ member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current
+ member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)"
+ member __.Reset () : unit = noReset ()
- let mutable source = enumerator
+ interface IEnumerator<'T> with
+ member __.Current =
+ match result.SeqState with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> result.Current
+
+ type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit ComposedEnumerator<'U>(result)
let rec moveNext () =
if (not result.Halted) && source.MoveNext () then
@@ -1039,32 +1056,20 @@ namespace Microsoft.FSharp.Collections
else
moveNext ()
else
- state <- SeqProcessNextStates.Finished
+ result.SeqState <- SeqProcessNextStates.Finished
t2u.OnComplete ()
false
- interface IDisposable with
- member __.Dispose():unit =
- match source with
- | null -> ()
- | _ -> source.Dispose (); source <- Unchecked.defaultof<_>
-
interface IEnumerator with
- member this.Current : obj = box (Helpers.UpcastEnumerator this).Current
member __.MoveNext () =
- state <- SeqProcessNextStates.InProcess
+ result.SeqState <- SeqProcessNextStates.InProcess
moveNext ()
- member __.Reset () : unit = noReset ()
- interface IEnumerator<'U> with
- member __.Current =
- match state with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> result.Current
+ interface IDisposable with
+ member __.Dispose() = source.Dispose ()
type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- let mutable state = SeqProcessNextStates.NotStarted
+ inherit ComposedEnumerator<'U>(result)
let mutable idx = 0
@@ -1076,77 +1081,58 @@ namespace Microsoft.FSharp.Collections
else
moveNext ()
else
- state <- SeqProcessNextStates.Finished
+ result.SeqState <- SeqProcessNextStates.Finished
t2u.OnComplete ()
false
- interface IDisposable with
- member __.Dispose() : unit = ()
-
interface IEnumerator with
- member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current
member __.MoveNext () =
- state <- SeqProcessNextStates.InProcess
+ result.SeqState <- SeqProcessNextStates.InProcess
moveNext ()
- member __.Reset () : unit = noReset ()
-
- interface IEnumerator<'U> with
- member __.Current =
- match state with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> result.Current
type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- let mutable state = SeqProcessNextStates.NotStarted
+ inherit ComposedEnumerator<'U>(result)
let mutable list = alist
- let rec moveNext () =
- match result.Halted, list with
+ let rec moveNext current =
+ match result.Halted, current with
| false, head::tail ->
- list <- tail
if t2u.ProcessNext head then
+ list <- tail
true
else
- moveNext ()
- | _ -> state <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
- false
-
- interface IDisposable with
- member __.Dispose() : unit = ()
+ moveNext tail
+ | _ ->
+ result.SeqState <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
interface IEnumerator with
- member this.Current : obj = box (this:>IEnumerator<'U>).Current
member __.MoveNext () =
- state <- SeqProcessNextStates.InProcess
- moveNext ()
- member __.Reset () : unit = noReset ()
-
- interface IEnumerator<'U> with
- member __.Current =
- match state with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> result.Current
+ result.SeqState <- SeqProcessNextStates.InProcess
+ moveNext list
[]
type ComposableEnumerable<'T> () =
abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
+ interface IEnumerable with
+ member this.GetEnumerator () : IEnumerator =
+ let genericEnumerable = Helpers.UpcastEnumerable this
+ let genericEnumerator = genericEnumerable.GetEnumerator ()
+ Helpers.UpcastEnumeratorNonGeneric genericEnumerator
+
+ interface IEnumerable<'T> with
+ member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
+
type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerable<'U>()
- let getEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result))
-
- interface IEnumerable with
- member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
-
interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result))
override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, ComposedFactory (current, next)))
@@ -1170,15 +1156,10 @@ namespace Microsoft.FSharp.Collections
type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerable<'U>()
- let getEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result))
-
- interface IEnumerable with
- member this.GetEnumerator () : IEnumerator = Helpers.UpcastEnumeratorNonGeneric (getEnumerator ())
-
interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result))
override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, ComposedFactory (current, next)))
@@ -1202,15 +1183,10 @@ namespace Microsoft.FSharp.Collections
type SeqListEnumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerable<'U>()
- let getEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result))
-
- interface IEnumerable with
- member this.GetEnumerator () : IEnumerator = upcast (getEnumerator ())
-
interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> = getEnumerator ()
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result))
override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next)))
From 8ce97ee17964a86bcecf24bf64891404267bc06e Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sat, 8 Oct 2016 20:38:54 +1100
Subject: [PATCH 017/327] Added ComposableEnumerableFactoryHelper
Sweeping up common functionality
---
src/fsharp/FSharp.Core/seq.fs | 46 ++++++++++++++++++++++-------------
1 file changed, 29 insertions(+), 17 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index b29e64202a8..8e64a12307d 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1126,16 +1126,28 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'T> with
member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
- type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
+ []
+ type ComposableEnumerableFactoryHelper<'T,'U> (seqComponentFactory:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerable<'U>()
+ member __.FactoryCompose next =
+ ComposedFactory (seqComponentFactory, next)
+
+ member __.CreateSeqComponent () =
+ let result = Result<'U> ()
+ let seqComponent = seqComponentFactory.Create result (Tail result)
+ result, seqComponent
+
+ type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
+
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result))
+ let result, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), seqComponent, result))
- override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, ComposedFactory (current, next)))
+ override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, this.FactoryCompose next))
// interface ISeqEnumerable<'U> with
// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
@@ -1153,16 +1165,16 @@ namespace Microsoft.FSharp.Collections
//
// state
- type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerable<'U>()
+ type SeqArrayEnumerable<'T,'U>(array:array<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result))
+ let result, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, seqComponent, result))
- override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, ComposedFactory (current, next)))
+ override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, this.FactoryCompose next))
// interface ISeqEnumerable<'U> with
// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
@@ -1180,16 +1192,16 @@ namespace Microsoft.FSharp.Collections
//
// state
- type SeqListEnumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerable<'U>()
+ type SeqListEnumerable<'T,'U>(alist:list<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result))
+ let result, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, seqComponent, result))
- override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next)))
+ override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, this.FactoryCompose next))
#if FX_NO_ICLONEABLE
From 17b3464ef3574cbd6e6f3ecba7e151e9f18401d7 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 05:36:56 +1100
Subject: [PATCH 018/327] init(Infinite)? implementations
Not as simple as it should be due to the original implementation
deciding to evaluate Current in a lazy fashion. Comments have been
splattered around hopefully describing the situation in enough detail.
---
src/fsharp/FSharp.Core/seq.fs | 92 ++++++++++++++++++++++++++++++++++-
1 file changed, 90 insertions(+), 2 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 8e64a12307d..98298a14914 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -877,12 +877,18 @@ namespace Microsoft.FSharp.Collections
and [] SeqComponent<'T,'U> () =
abstract ProcessNext : input:'T -> bool
abstract OnComplete : unit -> unit
+
+ // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip
+ // and it can only do it at the start of a sequence
+ abstract Skipping : unit -> bool
abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U>
abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U>
default __.OnComplete () = ()
+ default __.Skipping () = false
+
default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this)
default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this)
@@ -963,6 +969,13 @@ namespace Microsoft.FSharp.Collections
let mutable count = 0
+ override __.Skipping () =
+ if count < skipCount then
+ count <- count + 1
+ true
+ else
+ false
+
override __.ProcessNext (input:'T) : bool =
if count < skipCount then
count <- count + 1
@@ -1203,6 +1216,79 @@ namespace Microsoft.FSharp.Collections
override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, this.FactoryCompose next))
+ // The original implementation of "init" delayed the calculation of Current, and so it was possible
+ // to do MoveNext without it's value being calculated.
+ // I can imagine only two scenerios where that is possibly sane, although a simple solution is readily
+ // at hand in both cases. The first is that of an expensive generator function, where you skip the
+ // first n elements. The simple solution would have just been to have a map ((+) n) as the first operation
+ // instead. The second case would be counting elements, but that is only of use if you're not filtering
+ // or mapping or doing anything else (as that would cause Current to be evaluated!) and
+ // so you already know what the count is!! Anyway, someone thought it was a good idea, so
+ // I have had to add an extra function that is used in Skip to determine if we are touching
+ // Current or not.
+ type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit ComposedEnumerator<'U>(result)
+
+ // we are offset by 1 to allow for values going up to System.Int32.MaxValue
+ // System.Int32.MaxValue is an illegal value for the "infinite" sequence
+ let terminatingIdx =
+ if count.HasValue then
+ count.Value - 1
+ else
+ System.Int32.MaxValue
+
+ let mutable maybeSkipping = true
+ let mutable idx = -1
+
+ let rec moveNext () =
+ if (not result.Halted) && idx < terminatingIdx then
+ idx <- idx + 1
+
+ if maybeSkipping then
+ // Skip can only is only checked at the start of the sequence, so once
+ // triggered, we stay triggered.
+ maybeSkipping <- t2u.Skipping ()
+
+ if maybeSkipping || t2u.ProcessNext (f idx) then
+ true
+ else
+ moveNext ()
+ elif (not result.Halted) && idx = System.Int32.MaxValue then
+ raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue))
+ else
+ result.SeqState <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ result.SeqState <- SeqProcessNextStates.InProcess
+ moveNext ()
+
+ type InitComposingEnumerable<'T,'U>(count:Nullable, f:int->'T, seqComponentFactory:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, seqComponent, result))
+
+ override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new InitComposingEnumerable<'T,'V>(count, f, this.FactoryCompose next))
+
+ type InitEnumerable<'T>(count:Nullable, f:int->'T) =
+ inherit ComposableEnumerable<'T>()
+
+ interface IEnumerable<'T> with
+ member this.GetEnumerator () : IEnumerator<'T> =
+ // we defer back to the original implementation as, as it's quite idiomatic in it's decision
+ // to calculate Current in a lazy fashion. I doubt anyone is really using this functionality
+ // in the way presented, but it's possible.
+ upto (if count.HasValue then Some count.Value else None) f
+
+ override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
+ Helpers.UpcastEnumerable (InitComposingEnumerable<'T,'V>(count, f, next))
+
#if FX_NO_ICLONEABLE
open Microsoft.FSharp.Core.ICloneableExtensions
@@ -1225,12 +1311,14 @@ namespace Microsoft.FSharp.Collections
let empty<'T> = (EmptyEnumerable :> seq<'T>)
[]
- let initInfinite f = mkSeq (fun () -> IEnumerator.upto None f)
+ let initInfinite<'T> (f:int->'T) : IEnumerable<'T> =
+ SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable (), f))
[]
let init count f =
if count < 0 then invalidArgInputMustBeNonNegative "count" count
- mkSeq (fun () -> IEnumerator.upto (Some (count-1)) f)
+ elif count = 0 then empty else
+ SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable count, f))
[]
let iter f (source : seq<'T>) =
From 8cf65123d0b3bb8ebf4725e73eab192f172222da Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 06:00:07 +1100
Subject: [PATCH 019/327] Split Result object in multi-leveled Signal
The plan is to then implement fold like functionality in a Tail like
object that we can expose out in a public interface, so I'm trying to
minimize what would be needed to be visible externally.
---
src/fsharp/FSharp.Core/seq.fs | 131 +++++++++++++++++-----------------
1 file changed, 67 insertions(+), 64 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 98298a14914..8aa873a869a 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -816,63 +816,57 @@ namespace Microsoft.FSharp.Collections
let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #)
let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #)
- type SeqProcessNextStates =
- | NotStarted = 1
- | Finished = 2
- | InProcess = 3
-
- type Result<'T>() =
+ type SeqSignal () =
let mutable halted = false
-
- member val SeqState = SeqProcessNextStates.NotStarted with get, set
-
member __.StopFurtherProcessing () = halted <- true
member __.Halted = halted
+ type TailSignal<'T> () =
+ inherit SeqSignal ()
member val Current = Unchecked.defaultof<'T> with get, set
type [] SeqComponentFactory<'T,'U> () =
- abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V>
+ abstract Create<'V> : SeqSignal -> SeqComponent<'U,'V> -> SeqComponent<'T,'V>
and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) =
inherit SeqComponentFactory<'T,'V> ()
- override __.Create<'W> (result:Result<'W>) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create result (second.Create result next)
+ override __.Create<'W> (signal:SeqSignal) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create signal (second.Create signal next)
and ChooseFactory<'T,'U> (filter:'T->option<'U>) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
+ override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
and FilterFactory<'T> (filter:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter
+ override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter
and MapFactory<'T,'U> (map:'T->'U) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
+ override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
and MapiFactory<'T,'U> (mapi:int->'T->'U) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
+ override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
and PairwiseFactory<'T> () =
inherit SeqComponentFactory<'T,'T*'T> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next
+ override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next
and SkipFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
+ override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
and SkipWhileFactory<'T> (perdicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
+ override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
and TakeWhileFactory<'T> (perdicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, result, next)
+ override __.Create<'V> (signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, signal, next)
and TakeFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next)
+ override __.Create<'V> (signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, signal, next)
and [] SeqComponent<'T,'U> () =
abstract ProcessNext : input:'T -> bool
@@ -1004,7 +998,7 @@ namespace Microsoft.FSharp.Collections
else
Helpers.avoidTailCall (next.ProcessNext input)
- and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
+ and Take<'T,'V> (takeCount:int, signal:SeqSignal, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
let mutable count = 0
@@ -1013,10 +1007,10 @@ namespace Microsoft.FSharp.Collections
if count < takeCount then
count <- count + 1
if count = takeCount then
- result.StopFurtherProcessing ()
+ signal.StopFurtherProcessing ()
next.ProcessNext input
else
- result.StopFurtherProcessing ()
+ signal.StopFurtherProcessing ()
false
override __.OnComplete () =
@@ -1025,25 +1019,34 @@ namespace Microsoft.FSharp.Collections
invalidOpFmt "tried to take {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) =
+ and TakeWhile<'T,'V> (predicate:'T->bool, signal:SeqSignal, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
override __.ProcessNext (input:'T) : bool =
if predicate input then
next.ProcessNext input
else
- result.StopFurtherProcessing ()
+ signal.StopFurtherProcessing ()
false
- and Tail<'T> (result:Result<'T>) =
+ and Tail<'T> (signal:TailSignal<'T>) =
inherit SeqComponent<'T,'T>()
override __.ProcessNext (input:'T) : bool =
- result.Current <- input
+ signal.Current <- input
true
+ type SeqEnumeratorState =
+ | NotStarted = 1
+ | Finished = 2
+ | InProcess = 3
+
+ type EnumeratorSignal<'T>() =
+ inherit TailSignal<'T>()
+ member val EnumeratorState = SeqEnumeratorState.NotStarted with get, set
+
[]
- type ComposedEnumerator<'T>(result:Result<'T>) =
+ type ComposedEnumerator<'T>(signal:EnumeratorSignal<'T>) =
interface IDisposable with
member __.Dispose() : unit = ()
@@ -1054,62 +1057,62 @@ namespace Microsoft.FSharp.Collections
interface IEnumerator<'T> with
member __.Current =
- match result.SeqState with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> result.Current
+ match signal.EnumeratorState with
+ | SeqEnumeratorState.NotStarted -> notStarted()
+ | SeqEnumeratorState.Finished -> alreadyFinished()
+ | _ -> signal.Current
- type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit ComposedEnumerator<'U>(result)
+ type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
let rec moveNext () =
- if (not result.Halted) && source.MoveNext () then
+ if (not signal.Halted) && source.MoveNext () then
if t2u.ProcessNext source.Current then
true
else
moveNext ()
else
- result.SeqState <- SeqProcessNextStates.Finished
+ signal.EnumeratorState <- SeqEnumeratorState.Finished
t2u.OnComplete ()
false
interface IEnumerator with
member __.MoveNext () =
- result.SeqState <- SeqProcessNextStates.InProcess
+ signal.EnumeratorState <- SeqEnumeratorState.InProcess
moveNext ()
interface IDisposable with
member __.Dispose() = source.Dispose ()
- type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit ComposedEnumerator<'U>(result)
+ type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
let mutable idx = 0
let rec moveNext () =
- if (not result.Halted) && idx < array.Length then
+ if (not signal.Halted) && idx < array.Length then
idx <- idx+1
if t2u.ProcessNext array.[idx-1] then
true
else
moveNext ()
else
- result.SeqState <- SeqProcessNextStates.Finished
+ signal.EnumeratorState <- SeqEnumeratorState.Finished
t2u.OnComplete ()
false
interface IEnumerator with
member __.MoveNext () =
- result.SeqState <- SeqProcessNextStates.InProcess
+ signal.EnumeratorState <- SeqEnumeratorState.InProcess
moveNext ()
- type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit ComposedEnumerator<'U>(result)
+ type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
let mutable list = alist
let rec moveNext current =
- match result.Halted, current with
+ match signal.Halted, current with
| false, head::tail ->
if t2u.ProcessNext head then
list <- tail
@@ -1117,13 +1120,13 @@ namespace Microsoft.FSharp.Collections
else
moveNext tail
| _ ->
- result.SeqState <- SeqProcessNextStates.Finished
+ signal.EnumeratorState <- SeqEnumeratorState.Finished
t2u.OnComplete ()
false
interface IEnumerator with
member __.MoveNext () =
- result.SeqState <- SeqProcessNextStates.InProcess
+ signal.EnumeratorState <- SeqEnumeratorState.InProcess
moveNext list
[]
@@ -1147,17 +1150,17 @@ namespace Microsoft.FSharp.Collections
ComposedFactory (seqComponentFactory, next)
member __.CreateSeqComponent () =
- let result = Result<'U> ()
- let seqComponent = seqComponentFactory.Create result (Tail result)
- result, seqComponent
+ let signal = EnumeratorSignal<'U> ()
+ let seqComponent = seqComponentFactory.Create signal (Tail signal)
+ signal, seqComponent
type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let result, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), seqComponent, result))
+ let signal, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), seqComponent, signal))
override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, this.FactoryCompose next))
@@ -1183,8 +1186,8 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let result, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, seqComponent, result))
+ let signal, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, seqComponent, signal))
override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, this.FactoryCompose next))
@@ -1210,8 +1213,8 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let result, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, seqComponent, result))
+ let signal, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, seqComponent, signal))
override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, this.FactoryCompose next))
@@ -1226,8 +1229,8 @@ namespace Microsoft.FSharp.Collections
// so you already know what the count is!! Anyway, someone thought it was a good idea, so
// I have had to add an extra function that is used in Skip to determine if we are touching
// Current or not.
- type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit ComposedEnumerator<'U>(result)
+ type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
// we are offset by 1 to allow for values going up to System.Int32.MaxValue
// System.Int32.MaxValue is an illegal value for the "infinite" sequence
@@ -1241,7 +1244,7 @@ namespace Microsoft.FSharp.Collections
let mutable idx = -1
let rec moveNext () =
- if (not result.Halted) && idx < terminatingIdx then
+ if (not signal.Halted) && idx < terminatingIdx then
idx <- idx + 1
if maybeSkipping then
@@ -1253,16 +1256,16 @@ namespace Microsoft.FSharp.Collections
true
else
moveNext ()
- elif (not result.Halted) && idx = System.Int32.MaxValue then
+ elif (not signal.Halted) && idx = System.Int32.MaxValue then
raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue))
else
- result.SeqState <- SeqProcessNextStates.Finished
+ signal.EnumeratorState <- SeqEnumeratorState.Finished
t2u.OnComplete ()
false
interface IEnumerator with
member __.MoveNext () =
- result.SeqState <- SeqProcessNextStates.InProcess
+ signal.EnumeratorState <- SeqEnumeratorState.InProcess
moveNext ()
type InitComposingEnumerable<'T,'U>(count:Nullable, f:int->'T, seqComponentFactory:SeqComponentFactory<'T,'U>) =
@@ -1270,8 +1273,8 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let result, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, seqComponent, result))
+ let signal, seqComponent = this.CreateSeqComponent ()
+ Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, seqComponent, signal))
override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new InitComposingEnumerable<'T,'V>(count, f, this.FactoryCompose next))
From 04d8b39fe54e700ee6845532d6a5b77d37edbebd Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 06:12:42 +1100
Subject: [PATCH 020/327] Rearranged Enumerator/Enumerable pairs together
---
src/fsharp/FSharp.Core/seq.fs | 160 ++++++++++++++++++----------------
1 file changed, 85 insertions(+), 75 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 8aa873a869a..2e1584a2c7a 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1045,6 +1045,8 @@ namespace Microsoft.FSharp.Collections
inherit TailSignal<'T>()
member val EnumeratorState = SeqEnumeratorState.NotStarted with get, set
+ // ----- base classes for enumerator/enumerable -----
+
[]
type ComposedEnumerator<'T>(signal:EnumeratorSignal<'T>) =
interface IDisposable with
@@ -1062,73 +1064,6 @@ namespace Microsoft.FSharp.Collections
| SeqEnumeratorState.Finished -> alreadyFinished()
| _ -> signal.Current
- type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
- inherit ComposedEnumerator<'U>(signal)
-
- let rec moveNext () =
- if (not signal.Halted) && source.MoveNext () then
- if t2u.ProcessNext source.Current then
- true
- else
- moveNext ()
- else
- signal.EnumeratorState <- SeqEnumeratorState.Finished
- t2u.OnComplete ()
- false
-
- interface IEnumerator with
- member __.MoveNext () =
- signal.EnumeratorState <- SeqEnumeratorState.InProcess
- moveNext ()
-
- interface IDisposable with
- member __.Dispose() = source.Dispose ()
-
- type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
- inherit ComposedEnumerator<'U>(signal)
-
- let mutable idx = 0
-
- let rec moveNext () =
- if (not signal.Halted) && idx < array.Length then
- idx <- idx+1
- if t2u.ProcessNext array.[idx-1] then
- true
- else
- moveNext ()
- else
- signal.EnumeratorState <- SeqEnumeratorState.Finished
- t2u.OnComplete ()
- false
-
- interface IEnumerator with
- member __.MoveNext () =
- signal.EnumeratorState <- SeqEnumeratorState.InProcess
- moveNext ()
-
- type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
- inherit ComposedEnumerator<'U>(signal)
-
- let mutable list = alist
-
- let rec moveNext current =
- match signal.Halted, current with
- | false, head::tail ->
- if t2u.ProcessNext head then
- list <- tail
- true
- else
- moveNext tail
- | _ ->
- signal.EnumeratorState <- SeqEnumeratorState.Finished
- t2u.OnComplete ()
- false
-
- interface IEnumerator with
- member __.MoveNext () =
- signal.EnumeratorState <- SeqEnumeratorState.InProcess
- moveNext list
-
[]
type ComposableEnumerable<'T> () =
abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
@@ -1154,6 +1089,30 @@ namespace Microsoft.FSharp.Collections
let seqComponent = seqComponentFactory.Create signal (Tail signal)
signal, seqComponent
+ // ----- seq -----
+
+ type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
+
+ let rec moveNext () =
+ if (not signal.Halted) && source.MoveNext () then
+ if t2u.ProcessNext source.Current then
+ true
+ else
+ moveNext ()
+ else
+ signal.EnumeratorState <- SeqEnumeratorState.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ signal.EnumeratorState <- SeqEnumeratorState.InProcess
+ moveNext ()
+
+ interface IDisposable with
+ member __.Dispose() = source.Dispose ()
+
type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
@@ -1170,17 +1129,41 @@ namespace Microsoft.FSharp.Collections
// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
//
// let enumerator = enumerable.GetEnumerator ()
-// let result = Result<'U> ()
+// let signal = TailSignal<'U> ()
//
-// let components = current.Create result (Tail result)
+// let components = seqComponentFactory.Create signal (Tail signal)
//
// let mutable state = initialState
-// while (not result.Halted) && enumerator.MoveNext () do
+// while (not signal.Halted) && enumerator.MoveNext () do
// if components.ProcessNext (enumerator.Current) then
-// state <- folder'.Invoke (state, result.Current)
+// state <- folder'.Invoke (state, signal.Current)
//
// state
+ // ----- array -----
+
+ type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
+
+ let mutable idx = 0
+
+ let rec moveNext () =
+ if (not signal.Halted) && idx < array.Length then
+ idx <- idx+1
+ if t2u.ProcessNext array.[idx-1] then
+ true
+ else
+ moveNext ()
+ else
+ signal.EnumeratorState <- SeqEnumeratorState.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ signal.EnumeratorState <- SeqEnumeratorState.InProcess
+ moveNext ()
+
type SeqArrayEnumerable<'T,'U>(array:array<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
@@ -1197,17 +1180,42 @@ namespace Microsoft.FSharp.Collections
// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
//
// let mutable idx = 0
-// let result = Result<'U> ()
-// let components = current.Create result (Tail result)
+// let signal = TailSignal<'U> ()
+// let components = seqComponentFactory.Create signal (Tail signal)
//
// let mutable state = initialState
-// while (not result.Halted) && idx < array.Length do
+// while (not signal.Halted) && idx < array.Length do
// if components.ProcessNext array.[idx] then
-// state <- folder'.Invoke(state, result.Current)
+// state <- folder'.Invoke(state, signal.Current)
// idx <- idx + 1
//
// state
+ // ----- list -----
+
+ type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
+
+ let mutable list = alist
+
+ let rec moveNext current =
+ match signal.Halted, current with
+ | false, head::tail ->
+ if t2u.ProcessNext head then
+ list <- tail
+ true
+ else
+ moveNext tail
+ | _ ->
+ signal.EnumeratorState <- SeqEnumeratorState.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ signal.EnumeratorState <- SeqEnumeratorState.InProcess
+ moveNext list
+
type SeqListEnumerable<'T,'U>(alist:list<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
@@ -1219,6 +1227,8 @@ namespace Microsoft.FSharp.Collections
override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, this.FactoryCompose next))
+ // ----- init -----
+
// The original implementation of "init" delayed the calculation of Current, and so it was possible
// to do MoveNext without it's value being calculated.
// I can imagine only two scenerios where that is possibly sane, although a simple solution is readily
From f1792619d79514635d03db3457d7ee04fa803760 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 06:32:14 +1100
Subject: [PATCH 021/327] Fix bug in skipping an init seq
---
src/fsharp/FSharp.Core/seq.fs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 2e1584a2c7a..8bac6bfed9a 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1262,7 +1262,9 @@ namespace Microsoft.FSharp.Collections
// triggered, we stay triggered.
maybeSkipping <- t2u.Skipping ()
- if maybeSkipping || t2u.ProcessNext (f idx) then
+ if maybeSkipping then
+ moveNext ()
+ elif t2u.ProcessNext (f idx) then
true
else
moveNext ()
From beaedd5b285c766bbbd19d4e2e647431905488e9 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 08:19:24 +1100
Subject: [PATCH 022/327] Restoring to last successful build server build
I probably don't have any more time today to bug issues
---
src/fsharp/FSharp.Core/seq.fs | 341 +++++++++++-----------------------
1 file changed, 113 insertions(+), 228 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 8bac6bfed9a..b29e64202a8 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -816,73 +816,73 @@ namespace Microsoft.FSharp.Collections
let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #)
let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #)
- type SeqSignal () =
+ type SeqProcessNextStates =
+ | NotStarted = 1
+ | Finished = 2
+ | InProcess = 3
+
+ type Result<'T>() =
let mutable halted = false
+
+ member val SeqState = SeqProcessNextStates.NotStarted with get, set
+
member __.StopFurtherProcessing () = halted <- true
member __.Halted = halted
- type TailSignal<'T> () =
- inherit SeqSignal ()
member val Current = Unchecked.defaultof<'T> with get, set
type [] SeqComponentFactory<'T,'U> () =
- abstract Create<'V> : SeqSignal -> SeqComponent<'U,'V> -> SeqComponent<'T,'V>
+ abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V>
and ComposedFactory<'T,'U,'V> (first:SeqComponentFactory<'T,'U>, second:SeqComponentFactory<'U,'V>) =
inherit SeqComponentFactory<'T,'V> ()
- override __.Create<'W> (signal:SeqSignal) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create signal (second.Create signal next)
+ override __.Create<'W> (result:Result<'W>) (next:SeqComponent<'V,'W>) : SeqComponent<'T,'W> = first.Create result (second.Create result next)
and ChooseFactory<'T,'U> (filter:'T->option<'U>) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
and FilterFactory<'T> (filter:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = next.CreateFilter filter
and MapFactory<'T,'U> (map:'T->'U) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
and MapiFactory<'T,'U> (mapi:int->'T->'U) =
inherit SeqComponentFactory<'T,'U> ()
- override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
and PairwiseFactory<'T> () =
inherit SeqComponentFactory<'T,'T*'T> ()
- override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T*'T,'V>) : SeqComponent<'T,'V> = upcast Pairwise next
and SkipFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
and SkipWhileFactory<'T> (perdicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (_signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
and TakeWhileFactory<'T> (perdicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, signal, next)
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, result, next)
and TakeFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (signal:SeqSignal) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, signal, next)
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next)
and [] SeqComponent<'T,'U> () =
abstract ProcessNext : input:'T -> bool
abstract OnComplete : unit -> unit
-
- // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip
- // and it can only do it at the start of a sequence
- abstract Skipping : unit -> bool
abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U>
abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U>
default __.OnComplete () = ()
- default __.Skipping () = false
-
default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this)
default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this)
@@ -963,13 +963,6 @@ namespace Microsoft.FSharp.Collections
let mutable count = 0
- override __.Skipping () =
- if count < skipCount then
- count <- count + 1
- true
- else
- false
-
override __.ProcessNext (input:'T) : bool =
if count < skipCount then
count <- count + 1
@@ -998,7 +991,7 @@ namespace Microsoft.FSharp.Collections
else
Helpers.avoidTailCall (next.ProcessNext input)
- and Take<'T,'V> (takeCount:int, signal:SeqSignal, next:SeqComponent<'T,'V>) =
+ and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
let mutable count = 0
@@ -1007,10 +1000,10 @@ namespace Microsoft.FSharp.Collections
if count < takeCount then
count <- count + 1
if count = takeCount then
- signal.StopFurtherProcessing ()
+ result.StopFurtherProcessing ()
next.ProcessNext input
else
- signal.StopFurtherProcessing ()
+ result.StopFurtherProcessing ()
false
override __.OnComplete () =
@@ -1019,36 +1012,25 @@ namespace Microsoft.FSharp.Collections
invalidOpFmt "tried to take {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
- and TakeWhile<'T,'V> (predicate:'T->bool, signal:SeqSignal, next:SeqComponent<'T,'V>) =
+ and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>()
override __.ProcessNext (input:'T) : bool =
if predicate input then
next.ProcessNext input
else
- signal.StopFurtherProcessing ()
+ result.StopFurtherProcessing ()
false
- and Tail<'T> (signal:TailSignal<'T>) =
+ and Tail<'T> (result:Result<'T>) =
inherit SeqComponent<'T,'T>()
override __.ProcessNext (input:'T) : bool =
- signal.Current <- input
+ result.Current <- input
true
- type SeqEnumeratorState =
- | NotStarted = 1
- | Finished = 2
- | InProcess = 3
-
- type EnumeratorSignal<'T>() =
- inherit TailSignal<'T>()
- member val EnumeratorState = SeqEnumeratorState.NotStarted with get, set
-
- // ----- base classes for enumerator/enumerable -----
-
[]
- type ComposedEnumerator<'T>(signal:EnumeratorSignal<'T>) =
+ type ComposedEnumerator<'T>(result:Result<'T>) =
interface IDisposable with
member __.Dispose() : unit = ()
@@ -1059,147 +1041,62 @@ namespace Microsoft.FSharp.Collections
interface IEnumerator<'T> with
member __.Current =
- match signal.EnumeratorState with
- | SeqEnumeratorState.NotStarted -> notStarted()
- | SeqEnumeratorState.Finished -> alreadyFinished()
- | _ -> signal.Current
-
- []
- type ComposableEnumerable<'T> () =
- abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
-
- interface IEnumerable with
- member this.GetEnumerator () : IEnumerator =
- let genericEnumerable = Helpers.UpcastEnumerable this
- let genericEnumerator = genericEnumerable.GetEnumerator ()
- Helpers.UpcastEnumeratorNonGeneric genericEnumerator
+ match result.SeqState with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> result.Current
- interface IEnumerable<'T> with
- member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
-
- []
- type ComposableEnumerableFactoryHelper<'T,'U> (seqComponentFactory:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerable<'U>()
-
- member __.FactoryCompose next =
- ComposedFactory (seqComponentFactory, next)
-
- member __.CreateSeqComponent () =
- let signal = EnumeratorSignal<'U> ()
- let seqComponent = seqComponentFactory.Create signal (Tail signal)
- signal, seqComponent
-
- // ----- seq -----
-
- type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
- inherit ComposedEnumerator<'U>(signal)
+ type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit ComposedEnumerator<'U>(result)
let rec moveNext () =
- if (not signal.Halted) && source.MoveNext () then
+ if (not result.Halted) && source.MoveNext () then
if t2u.ProcessNext source.Current then
true
else
moveNext ()
else
- signal.EnumeratorState <- SeqEnumeratorState.Finished
+ result.SeqState <- SeqProcessNextStates.Finished
t2u.OnComplete ()
false
interface IEnumerator with
member __.MoveNext () =
- signal.EnumeratorState <- SeqEnumeratorState.InProcess
+ result.SeqState <- SeqProcessNextStates.InProcess
moveNext ()
interface IDisposable with
member __.Dispose() = source.Dispose ()
- type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
-
- interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> =
- let signal, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), seqComponent, signal))
-
- override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, this.FactoryCompose next))
-
-// interface ISeqEnumerable<'U> with
-// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
-// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
-//
-// let enumerator = enumerable.GetEnumerator ()
-// let signal = TailSignal<'U> ()
-//
-// let components = seqComponentFactory.Create signal (Tail signal)
-//
-// let mutable state = initialState
-// while (not signal.Halted) && enumerator.MoveNext () do
-// if components.ProcessNext (enumerator.Current) then
-// state <- folder'.Invoke (state, signal.Current)
-//
-// state
-
- // ----- array -----
-
- type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
- inherit ComposedEnumerator<'U>(signal)
+ type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit ComposedEnumerator<'U>(result)
let mutable idx = 0
let rec moveNext () =
- if (not signal.Halted) && idx < array.Length then
+ if (not result.Halted) && idx < array.Length then
idx <- idx+1
if t2u.ProcessNext array.[idx-1] then
true
else
moveNext ()
else
- signal.EnumeratorState <- SeqEnumeratorState.Finished
+ result.SeqState <- SeqProcessNextStates.Finished
t2u.OnComplete ()
false
interface IEnumerator with
member __.MoveNext () =
- signal.EnumeratorState <- SeqEnumeratorState.InProcess
+ result.SeqState <- SeqProcessNextStates.InProcess
moveNext ()
- type SeqArrayEnumerable<'T,'U>(array:array<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
-
- interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> =
- let signal, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, seqComponent, signal))
-
- override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, this.FactoryCompose next))
-
-// interface ISeqEnumerable<'U> with
-// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
-// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
-//
-// let mutable idx = 0
-// let signal = TailSignal<'U> ()
-// let components = seqComponentFactory.Create signal (Tail signal)
-//
-// let mutable state = initialState
-// while (not signal.Halted) && idx < array.Length do
-// if components.ProcessNext array.[idx] then
-// state <- folder'.Invoke(state, signal.Current)
-// idx <- idx + 1
-//
-// state
-
- // ----- list -----
-
- type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
- inherit ComposedEnumerator<'U>(signal)
+ type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit ComposedEnumerator<'U>(result)
let mutable list = alist
let rec moveNext current =
- match signal.Halted, current with
+ match result.Halted, current with
| false, head::tail ->
if t2u.ProcessNext head then
list <- tail
@@ -1207,102 +1104,92 @@ namespace Microsoft.FSharp.Collections
else
moveNext tail
| _ ->
- signal.EnumeratorState <- SeqEnumeratorState.Finished
+ result.SeqState <- SeqProcessNextStates.Finished
t2u.OnComplete ()
false
interface IEnumerator with
member __.MoveNext () =
- signal.EnumeratorState <- SeqEnumeratorState.InProcess
+ result.SeqState <- SeqProcessNextStates.InProcess
moveNext list
- type SeqListEnumerable<'T,'U>(alist:list<'T>, seqComponentFactory:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
+ []
+ type ComposableEnumerable<'T> () =
+ abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
+
+ interface IEnumerable with
+ member this.GetEnumerator () : IEnumerator =
+ let genericEnumerable = Helpers.UpcastEnumerable this
+ let genericEnumerator = genericEnumerable.GetEnumerator ()
+ Helpers.UpcastEnumeratorNonGeneric genericEnumerator
+
+ interface IEnumerable<'T> with
+ member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
+
+ type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerable<'U>()
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let signal, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, seqComponent, signal))
-
- override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, this.FactoryCompose next))
-
- // ----- init -----
-
- // The original implementation of "init" delayed the calculation of Current, and so it was possible
- // to do MoveNext without it's value being calculated.
- // I can imagine only two scenerios where that is possibly sane, although a simple solution is readily
- // at hand in both cases. The first is that of an expensive generator function, where you skip the
- // first n elements. The simple solution would have just been to have a map ((+) n) as the first operation
- // instead. The second case would be counting elements, but that is only of use if you're not filtering
- // or mapping or doing anything else (as that would cause Current to be evaluated!) and
- // so you already know what the count is!! Anyway, someone thought it was a good idea, so
- // I have had to add an extra function that is used in Skip to determine if we are touching
- // Current or not.
- type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:EnumeratorSignal<'U>) =
- inherit ComposedEnumerator<'U>(signal)
-
- // we are offset by 1 to allow for values going up to System.Int32.MaxValue
- // System.Int32.MaxValue is an illegal value for the "infinite" sequence
- let terminatingIdx =
- if count.HasValue then
- count.Value - 1
- else
- System.Int32.MaxValue
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result))
- let mutable maybeSkipping = true
- let mutable idx = -1
-
- let rec moveNext () =
- if (not signal.Halted) && idx < terminatingIdx then
- idx <- idx + 1
-
- if maybeSkipping then
- // Skip can only is only checked at the start of the sequence, so once
- // triggered, we stay triggered.
- maybeSkipping <- t2u.Skipping ()
-
- if maybeSkipping then
- moveNext ()
- elif t2u.ProcessNext (f idx) then
- true
- else
- moveNext ()
- elif (not signal.Halted) && idx = System.Int32.MaxValue then
- raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue))
- else
- signal.EnumeratorState <- SeqEnumeratorState.Finished
- t2u.OnComplete ()
- false
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, ComposedFactory (current, next)))
- interface IEnumerator with
- member __.MoveNext () =
- signal.EnumeratorState <- SeqEnumeratorState.InProcess
- moveNext ()
+// interface ISeqEnumerable<'U> with
+// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+//
+// let enumerator = enumerable.GetEnumerator ()
+// let result = Result<'U> ()
+//
+// let components = current.Create result (Tail result)
+//
+// let mutable state = initialState
+// while (not result.Halted) && enumerator.MoveNext () do
+// if components.ProcessNext (enumerator.Current) then
+// state <- folder'.Invoke (state, result.Current)
+//
+// state
- type InitComposingEnumerable<'T,'U>(count:Nullable, f:int->'T, seqComponentFactory:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerableFactoryHelper<'T,'U>(seqComponentFactory)
+ type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerable<'U>()
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
- let signal, seqComponent = this.CreateSeqComponent ()
- Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, seqComponent, signal))
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result))
- override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new InitComposingEnumerable<'T,'V>(count, f, this.FactoryCompose next))
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, ComposedFactory (current, next)))
- type InitEnumerable<'T>(count:Nullable, f:int->'T) =
- inherit ComposableEnumerable<'T>()
+// interface ISeqEnumerable<'U> with
+// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+//
+// let mutable idx = 0
+// let result = Result<'U> ()
+// let components = current.Create result (Tail result)
+//
+// let mutable state = initialState
+// while (not result.Halted) && idx < array.Length do
+// if components.ProcessNext array.[idx] then
+// state <- folder'.Invoke(state, result.Current)
+// idx <- idx + 1
+//
+// state
- interface IEnumerable<'T> with
- member this.GetEnumerator () : IEnumerator<'T> =
- // we defer back to the original implementation as, as it's quite idiomatic in it's decision
- // to calculate Current in a lazy fashion. I doubt anyone is really using this functionality
- // in the way presented, but it's possible.
- upto (if count.HasValue then Some count.Value else None) f
+ type SeqListEnumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerable<'U>()
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result))
- override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
- Helpers.UpcastEnumerable (InitComposingEnumerable<'T,'V>(count, f, next))
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next)))
#if FX_NO_ICLONEABLE
@@ -1326,14 +1213,12 @@ namespace Microsoft.FSharp.Collections
let empty<'T> = (EmptyEnumerable :> seq<'T>)
[]
- let initInfinite<'T> (f:int->'T) : IEnumerable<'T> =
- SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable (), f))
+ let initInfinite f = mkSeq (fun () -> IEnumerator.upto None f)
[]
let init count f =
if count < 0 then invalidArgInputMustBeNonNegative "count" count
- elif count = 0 then empty else
- SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable count, f))
+ mkSeq (fun () -> IEnumerator.upto (Some (count-1)) f)
[]
let iter f (source : seq<'T>) =
From 71d273a8f980f834f5f39cf98f4f10a5df61252b Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 13:32:57 +1100
Subject: [PATCH 023/327] init/initInfinite
Try again, without any other clutter
---
src/fsharp/FSharp.Core/seq.fs | 97 +++++++++++++++++++++++++++++++++--
1 file changed, 94 insertions(+), 3 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index b29e64202a8..4596e6b1700 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -878,11 +878,17 @@ namespace Microsoft.FSharp.Collections
abstract ProcessNext : input:'T -> bool
abstract OnComplete : unit -> unit
+ // Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip
+ // and it can only do it at the start of a sequence
+ abstract Skipping : unit -> bool
+
abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U>
abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U>
default __.OnComplete () = ()
+ default __.Skipping () = false
+
default this.CreateMap<'S> (map:'S->'T) = upcast Map<_,_,_> (map, this)
default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this)
@@ -963,6 +969,13 @@ namespace Microsoft.FSharp.Collections
let mutable count = 0
+ override __.Skipping () =
+ if count < skipCount then
+ count <- count + 1
+ true
+ else
+ false
+
override __.ProcessNext (input:'T) : bool =
if count < skipCount then
count <- count + 1
@@ -1192,6 +1205,82 @@ namespace Microsoft.FSharp.Collections
Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next)))
+ // The original implementation of "init" delayed the calculation of Current, and so it was possible
+ // to do MoveNext without it's value being calculated.
+ // I can imagine only two scenerios where that is possibly sane, although a simple solution is readily
+ // at hand in both cases. The first is that of an expensive generator function, where you skip the
+ // first n elements. The simple solution would have just been to have a map ((+) n) as the first operation
+ // instead. The second case would be counting elements, but that is only of use if you're not filtering
+ // or mapping or doing anything else (as that would cause Current to be evaluated!) and
+ // so you already know what the count is!! Anyway, someone thought it was a good idea, so
+ // I have had to add an extra function that is used in Skip to determine if we are touching
+ // Current or not.
+ type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:Result<'U>) =
+ inherit ComposedEnumerator<'U>(signal)
+
+ // we are offset by 1 to allow for values going up to System.Int32.MaxValue
+ // System.Int32.MaxValue is an illegal value for the "infinite" sequence
+ let terminatingIdx =
+ if count.HasValue then
+ count.Value - 1
+ else
+ System.Int32.MaxValue
+
+ let mutable maybeSkipping = true
+ let mutable idx = -1
+
+ let rec moveNext () =
+ if (not signal.Halted) && idx < terminatingIdx then
+ idx <- idx + 1
+
+ if maybeSkipping then
+ // Skip can only is only checked at the start of the sequence, so once
+ // triggered, we stay triggered.
+ maybeSkipping <- t2u.Skipping ()
+
+ if maybeSkipping then
+ moveNext ()
+ elif t2u.ProcessNext (f idx) then
+ true
+ else
+ moveNext ()
+ elif (not signal.Halted) && idx = System.Int32.MaxValue then
+ raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue))
+ else
+ signal.SeqState <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ signal.SeqState <- SeqProcessNextStates.InProcess
+ moveNext ()
+
+ type InitComposingEnumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) =
+ inherit ComposableEnumerable<'U>()
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, current.Create result (Tail result), result))
+
+ override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new InitComposingEnumerable<'T,'V>(count, f, ComposedFactory (current, next)))
+
+
+ type InitEnumerable<'T>(count:Nullable, f:int->'T) =
+ inherit ComposableEnumerable<'T>()
+
+ interface IEnumerable<'T> with
+ member this.GetEnumerator () : IEnumerator<'T> =
+ // we defer back to the original implementation as, as it's quite idiomatic in it's decision
+ // to calculate Current in a lazy fashion. I doubt anyone is really using this functionality
+ // in the way presented, but it's possible.
+ upto (if count.HasValue then Some count.Value else None) f
+
+ override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
+ Helpers.UpcastEnumerable (InitComposingEnumerable<'T,'V>(count, f, next))
+
#if FX_NO_ICLONEABLE
open Microsoft.FSharp.Core.ICloneableExtensions
#else
@@ -1213,12 +1302,14 @@ namespace Microsoft.FSharp.Collections
let empty<'T> = (EmptyEnumerable :> seq<'T>)
[]
- let initInfinite f = mkSeq (fun () -> IEnumerator.upto None f)
+ let initInfinite<'T> (f:int->'T) : IEnumerable<'T> =
+ SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable (), f))
[]
- let init count f =
+ let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> =
if count < 0 then invalidArgInputMustBeNonNegative "count" count
- mkSeq (fun () -> IEnumerator.upto (Some (count-1)) f)
+ elif count = 0 then empty else
+ SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable count, f))
[]
let iter f (source : seq<'T>) =
From 496d637fd371b205f702a81ec85e02f069768d59 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 14:12:59 +1100
Subject: [PATCH 024/327] Bug fix; off by 1...
---
src/fsharp/FSharp.Core/seq.fs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 4596e6b1700..325cfcd3166 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1276,7 +1276,7 @@ namespace Microsoft.FSharp.Collections
// we defer back to the original implementation as, as it's quite idiomatic in it's decision
// to calculate Current in a lazy fashion. I doubt anyone is really using this functionality
// in the way presented, but it's possible.
- upto (if count.HasValue then Some count.Value else None) f
+ upto (if count.HasValue then Some (count.Value-1) else None) f
override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
Helpers.UpcastEnumerable (InitComposingEnumerable<'T,'V>(count, f, next))
From c4e7de4b6d9e8a25f352568afe8cee0f88f5adf6 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 16:29:19 +1100
Subject: [PATCH 025/327] Moved Enumerable/Enumerator pairs into modules
---
src/fsharp/FSharp.Core/seq.fs | 441 +++++++++++++++++-----------------
1 file changed, 223 insertions(+), 218 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 325cfcd3166..270c83fe38e 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1042,244 +1042,249 @@ namespace Microsoft.FSharp.Collections
result.Current <- input
true
- []
- type ComposedEnumerator<'T>(result:Result<'T>) =
- interface IDisposable with
- member __.Dispose() : unit = ()
-
- interface IEnumerator with
- member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current
- member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)"
- member __.Reset () : unit = noReset ()
-
- interface IEnumerator<'T> with
- member __.Current =
- match result.SeqState with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> result.Current
-
- type SeqComposedEnumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit ComposedEnumerator<'U>(result)
-
- let rec moveNext () =
- if (not result.Halted) && source.MoveNext () then
- if t2u.ProcessNext source.Current then
- true
+ module Base =
+ []
+ type Enumerator<'T>(result:Result<'T>) =
+ interface IDisposable with
+ member __.Dispose() : unit = ()
+
+ interface IEnumerator with
+ member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current
+ member __.MoveNext () = failwith "library implementation error: derived class should implement (should be abstract)"
+ member __.Reset () : unit = noReset ()
+
+ interface IEnumerator<'T> with
+ member __.Current =
+ match result.SeqState with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> result.Current
+
+
+ []
+ type Enumerable<'T> () =
+ abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
+
+ interface IEnumerable with
+ member this.GetEnumerator () : IEnumerator =
+ let genericEnumerable = Helpers.UpcastEnumerable this
+ let genericEnumerator = genericEnumerable.GetEnumerator ()
+ Helpers.UpcastEnumeratorNonGeneric genericEnumerator
+
+ interface IEnumerable<'T> with
+ member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
+
+ module Enumerable =
+ type Enumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit Base.Enumerator<'U>(result)
+
+ let rec moveNext () =
+ if (not result.Halted) && source.MoveNext () then
+ if t2u.ProcessNext source.Current then
+ true
+ else
+ moveNext ()
else
+ result.SeqState <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ result.SeqState <- SeqProcessNextStates.InProcess
moveNext ()
- else
- result.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
- false
- interface IEnumerator with
- member __.MoveNext () =
- result.SeqState <- SeqProcessNextStates.InProcess
- moveNext ()
+ interface IDisposable with
+ member __.Dispose() = source.Dispose ()
- interface IDisposable with
- member __.Dispose() = source.Dispose ()
- type ArrayComposedEnumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit ComposedEnumerator<'U>(result)
+ type Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
+ inherit Base.Enumerable<'U>()
- let mutable idx = 0
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new Enumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result))
- let rec moveNext () =
- if (not result.Halted) && idx < array.Length then
- idx <- idx+1
- if t2u.ProcessNext array.[idx-1] then
- true
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory (current, next)))
+
+ // interface ISeqEnumerable<'U> with
+ // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+ //
+ // let enumerator = enumerable.GetEnumerator ()
+ // let result = Result<'U> ()
+ //
+ // let components = current.Create result (Tail result)
+ //
+ // let mutable state = initialState
+ // while (not result.Halted) && enumerator.MoveNext () do
+ // if components.ProcessNext (enumerator.Current) then
+ // state <- folder'.Invoke (state, result.Current)
+ //
+ // state
+
+ module Array =
+ type Enumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit Base.Enumerator<'U>(result)
+
+ let mutable idx = 0
+
+ let rec moveNext () =
+ if (not result.Halted) && idx < array.Length then
+ idx <- idx+1
+ if t2u.ProcessNext array.[idx-1] then
+ true
+ else
+ moveNext ()
else
+ result.SeqState <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ result.SeqState <- SeqProcessNextStates.InProcess
moveNext ()
- else
- result.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
- false
- interface IEnumerator with
- member __.MoveNext () =
- result.SeqState <- SeqProcessNextStates.InProcess
- moveNext ()
+ type Enumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) =
+ inherit Base.Enumerable<'U>()
- type ListComposedEnumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit ComposedEnumerator<'U>(result)
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new Enumerator<'T,'U>(array, current.Create result (Tail result), result))
- let mutable list = alist
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory (current, next)))
- let rec moveNext current =
- match result.Halted, current with
- | false, head::tail ->
- if t2u.ProcessNext head then
- list <- tail
- true
- else
- moveNext tail
- | _ ->
- result.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
- false
+ // interface ISeqEnumerable<'U> with
+ // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+ //
+ // let mutable idx = 0
+ // let result = Result<'U> ()
+ // let components = current.Create result (Tail result)
+ //
+ // let mutable state = initialState
+ // while (not result.Halted) && idx < array.Length do
+ // if components.ProcessNext array.[idx] then
+ // state <- folder'.Invoke(state, result.Current)
+ // idx <- idx + 1
+ //
+ // state
- interface IEnumerator with
- member __.MoveNext () =
- result.SeqState <- SeqProcessNextStates.InProcess
- moveNext list
-
- []
- type ComposableEnumerable<'T> () =
- abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
-
- interface IEnumerable with
- member this.GetEnumerator () : IEnumerator =
- let genericEnumerable = Helpers.UpcastEnumerable this
- let genericEnumerator = genericEnumerable.GetEnumerator ()
- Helpers.UpcastEnumeratorNonGeneric genericEnumerator
-
- interface IEnumerable<'T> with
- member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
-
- type SeqEnumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerable<'U>()
-
- interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new SeqComposedEnumerator<'T,'U>(enumerable.GetEnumerator(), current.Create result (Tail result), result))
-
- override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqEnumerable<'T,'V>(enumerable, ComposedFactory (current, next)))
-
-// interface ISeqEnumerable<'U> with
-// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
-// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
-//
-// let enumerator = enumerable.GetEnumerator ()
-// let result = Result<'U> ()
-//
-// let components = current.Create result (Tail result)
-//
-// let mutable state = initialState
-// while (not result.Halted) && enumerator.MoveNext () do
-// if components.ProcessNext (enumerator.Current) then
-// state <- folder'.Invoke (state, result.Current)
-//
-// state
-
- type SeqArrayEnumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerable<'U>()
-
- interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new ArrayComposedEnumerator<'T,'U>(array, current.Create result (Tail result), result))
-
- override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqArrayEnumerable<'T,'V>(array, ComposedFactory (current, next)))
-
-// interface ISeqEnumerable<'U> with
-// member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
-// let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
-//
-// let mutable idx = 0
-// let result = Result<'U> ()
-// let components = current.Create result (Tail result)
-//
-// let mutable state = initialState
-// while (not result.Halted) && idx < array.Length do
-// if components.ProcessNext array.[idx] then
-// state <- folder'.Invoke(state, result.Current)
-// idx <- idx + 1
-//
-// state
-
- type SeqListEnumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerable<'U>()
-
- interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new ListComposedEnumerator<'T,'U>(alist, current.Create result (Tail result), result))
-
- override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new SeqListEnumerable<'T,'V>(alist, ComposedFactory (current, next)))
-
-
- // The original implementation of "init" delayed the calculation of Current, and so it was possible
- // to do MoveNext without it's value being calculated.
- // I can imagine only two scenerios where that is possibly sane, although a simple solution is readily
- // at hand in both cases. The first is that of an expensive generator function, where you skip the
- // first n elements. The simple solution would have just been to have a map ((+) n) as the first operation
- // instead. The second case would be counting elements, but that is only of use if you're not filtering
- // or mapping or doing anything else (as that would cause Current to be evaluated!) and
- // so you already know what the count is!! Anyway, someone thought it was a good idea, so
- // I have had to add an extra function that is used in Skip to determine if we are touching
- // Current or not.
- type InitComposedEnumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:Result<'U>) =
- inherit ComposedEnumerator<'U>(signal)
-
- // we are offset by 1 to allow for values going up to System.Int32.MaxValue
- // System.Int32.MaxValue is an illegal value for the "infinite" sequence
- let terminatingIdx =
- if count.HasValue then
- count.Value - 1
- else
- System.Int32.MaxValue
+ module List =
+ type Enumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit Base.Enumerator<'U>(result)
- let mutable maybeSkipping = true
- let mutable idx = -1
+ let mutable list = alist
- let rec moveNext () =
- if (not signal.Halted) && idx < terminatingIdx then
- idx <- idx + 1
+ let rec moveNext current =
+ match result.Halted, current with
+ | false, head::tail ->
+ if t2u.ProcessNext head then
+ list <- tail
+ true
+ else
+ moveNext tail
+ | _ ->
+ result.SeqState <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
- if maybeSkipping then
- // Skip can only is only checked at the start of the sequence, so once
- // triggered, we stay triggered.
- maybeSkipping <- t2u.Skipping ()
-
- if maybeSkipping then
- moveNext ()
- elif t2u.ProcessNext (f idx) then
- true
+ interface IEnumerator with
+ member __.MoveNext () =
+ result.SeqState <- SeqProcessNextStates.InProcess
+ moveNext list
+
+ type Enumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) =
+ inherit Base.Enumerable<'U>()
+
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new Enumerator<'T,'U>(alist, current.Create result (Tail result), result))
+
+ override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory (current, next)))
+
+ module Init =
+ // The original implementation of "init" delayed the calculation of Current, and so it was possible
+ // to do MoveNext without it's value being calculated.
+ // I can imagine only two scenerios where that is possibly sane, although a simple solution is readily
+ // at hand in both cases. The first is that of an expensive generator function, where you skip the
+ // first n elements. The simple solution would have just been to have a map ((+) n) as the first operation
+ // instead. The second case would be counting elements, but that is only of use if you're not filtering
+ // or mapping or doing anything else (as that would cause Current to be evaluated!) and
+ // so you already know what the count is!! Anyway, someone thought it was a good idea, so
+ // I have had to add an extra function that is used in Skip to determine if we are touching
+ // Current or not.
+ type Enumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:Result<'U>) =
+ inherit Base.Enumerator<'U>(signal)
+
+ // we are offset by 1 to allow for values going up to System.Int32.MaxValue
+ // System.Int32.MaxValue is an illegal value for the "infinite" sequence
+ let terminatingIdx =
+ if count.HasValue then
+ count.Value - 1
else
- moveNext ()
- elif (not signal.Halted) && idx = System.Int32.MaxValue then
- raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue))
- else
- signal.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
- false
+ System.Int32.MaxValue
- interface IEnumerator with
- member __.MoveNext () =
- signal.SeqState <- SeqProcessNextStates.InProcess
- moveNext ()
+ let mutable maybeSkipping = true
+ let mutable idx = -1
+
+ let rec moveNext () =
+ if (not signal.Halted) && idx < terminatingIdx then
+ idx <- idx + 1
- type InitComposingEnumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) =
- inherit ComposableEnumerable<'U>()
+ if maybeSkipping then
+ // Skip can only is only checked at the start of the sequence, so once
+ // triggered, we stay triggered.
+ maybeSkipping <- t2u.Skipping ()
+
+ if maybeSkipping then
+ moveNext ()
+ elif t2u.ProcessNext (f idx) then
+ true
+ else
+ moveNext ()
+ elif (not signal.Halted) && idx = System.Int32.MaxValue then
+ raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue))
+ else
+ signal.SeqState <- SeqProcessNextStates.Finished
+ t2u.OnComplete ()
+ false
+
+ interface IEnumerator with
+ member __.MoveNext () =
+ signal.SeqState <- SeqProcessNextStates.InProcess
+ moveNext ()
- interface IEnumerable<'U> with
- member this.GetEnumerator () : IEnumerator<'U> =
- let result = Result<'U> ()
- Helpers.UpcastEnumerator (new InitComposedEnumerator<'T,'U>(count, f, current.Create result (Tail result), result))
+ type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) =
+ inherit Base.Enumerable<'U>()
- override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
- Helpers.UpcastEnumerable (new InitComposingEnumerable<'T,'V>(count, f, ComposedFactory (current, next)))
+ interface IEnumerable<'U> with
+ member this.GetEnumerator () : IEnumerator<'U> =
+ let result = Result<'U> ()
+ Helpers.UpcastEnumerator (new Enumerator<'T,'U>(count, f, current.Create result (Tail result), result))
+ override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
+ Helpers.UpcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next)))
- type InitEnumerable<'T>(count:Nullable, f:int->'T) =
- inherit ComposableEnumerable<'T>()
+ type EnumerableDecider<'T>(count:Nullable, f:int->'T) =
+ inherit Base.Enumerable<'T>()
- interface IEnumerable<'T> with
- member this.GetEnumerator () : IEnumerator<'T> =
- // we defer back to the original implementation as, as it's quite idiomatic in it's decision
- // to calculate Current in a lazy fashion. I doubt anyone is really using this functionality
- // in the way presented, but it's possible.
- upto (if count.HasValue then Some (count.Value-1) else None) f
+ interface IEnumerable<'T> with
+ member this.GetEnumerator () : IEnumerator<'T> =
+ // we defer back to the original implementation as, as it's quite idiomatic in it's decision
+ // to calculate Current in a lazy fashion. I doubt anyone is really using this functionality
+ // in the way presented, but it's possible.
+ upto (if count.HasValue then Some (count.Value-1) else None) f
- override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
- Helpers.UpcastEnumerable (InitComposingEnumerable<'T,'V>(count, f, next))
+ override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
+ Helpers.UpcastEnumerable (Enumerable<'T,'V>(count, f, next))
#if FX_NO_ICLONEABLE
open Microsoft.FSharp.Core.ICloneableExtensions
@@ -1303,13 +1308,13 @@ namespace Microsoft.FSharp.Collections
[]
let initInfinite<'T> (f:int->'T) : IEnumerable<'T> =
- SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable (), f))
+ SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable (), f))
[]
let init<'T> (count:int) (f:int->'T) : IEnumerable<'T> =
if count < 0 then invalidArgInputMustBeNonNegative "count" count
elif count = 0 then empty else
- SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.InitEnumerable<'T>(Nullable count, f))
+ SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Init.EnumerableDecider<'T>(Nullable count, f))
[]
let iter f (source : seq<'T>) =
@@ -1405,10 +1410,10 @@ namespace Microsoft.FSharp.Collections
let private seqFactory createSeqComponent (source:seq<'T>) =
checkNonNull "source" source
match source with
- | :? SeqComposer.ComposableEnumerable<'T> as s -> s.Compose createSeqComponent
- | :? array<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqArrayEnumerable<_,_>(a, createSeqComponent))
- | :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqListEnumerable<_,_>(a, createSeqComponent))
- | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.SeqEnumerable<_,_>(source, createSeqComponent))
+ | :? SeqComposer.Base.Enumerable<'T> as s -> s.Compose createSeqComponent
+ | :? array<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Array.Enumerable<_,_>(a, createSeqComponent))
+ | :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.List.Enumerable<_,_>(a, createSeqComponent))
+ | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Enumerable.Enumerable<_,_>(source, createSeqComponent))
[]
let filter<'T> (f:'T->bool) (source:seq<'T>) : seq<'T> =
From 3825fa59de70548aba39d02fded28336a53767dc Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 19:09:42 +1100
Subject: [PATCH 026/327] map2
---
src/fsharp/FSharp.Core/seq.fs | 65 ++++++++++++++++++++++++-----------
1 file changed, 44 insertions(+), 21 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 270c83fe38e..89293b410a1 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -107,25 +107,6 @@ namespace Microsoft.FSharp.Collections
interface System.IDisposable with
member this.Dispose() = this.Dispose()
- let map2 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) : IEnumerator<_>=
- let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
- upcast
- { new MapEnumerator<_>() with
- member this.DoMoveNext curr =
- let n1 = e1.MoveNext()
- let n2 = e2.MoveNext()
- if n1 && n2 then
- curr <- f.Invoke(e1.Current, e2.Current)
- true
- else
- false
- member this.Dispose() =
- try
- e1.Dispose()
- finally
- e2.Dispose()
- }
-
let mapi2 f (e1 : IEnumerator<_>) (e2 : IEnumerator<_>) : IEnumerator<_> =
let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f)
let i = ref (-1)
@@ -850,6 +831,14 @@ namespace Microsoft.FSharp.Collections
inherit SeqComponentFactory<'T,'U> ()
override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = next.CreateMap map
+ and Map2FirstFactory<'First,'Second,'U> (map:'First->'Second->'U, input2:IEnumerable<'Second>) =
+ inherit SeqComponentFactory<'First,'U> ()
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'First,'V> = upcast Map2First (map, input2, result, next)
+
+ and Map2SecondFactory<'First,'Second,'U> (map:'First->'Second->'U, input1:IEnumerable<'First>) =
+ inherit SeqComponentFactory<'Second,'U> ()
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'Second,'V> = upcast Map2Second (map, input1, result, next)
+
and MapiFactory<'T,'U> (mapi:int->'T->'U) =
inherit SeqComponentFactory<'T,'U> ()
override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Mapi (mapi, next)
@@ -928,6 +917,38 @@ namespace Microsoft.FSharp.Collections
override __.ProcessNext (input:'T) : bool =
Helpers.avoidTailCall (next.ProcessNext (map input))
+ and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'First,'V>()
+
+ let input2 = enumerable2.GetEnumerator ()
+ let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map
+
+ override __.ProcessNext (input:'First) : bool =
+ if input2.MoveNext () then
+ Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input, input2.Current)))
+ else
+ result.StopFurtherProcessing ()
+ false
+
+ override __.OnComplete () =
+ input2.Dispose ()
+
+ and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) =
+ inherit SeqComponent<'Second,'V>()
+
+ let input1 = enumerable1.GetEnumerator ()
+ let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map
+
+ override __.ProcessNext (input:'Second) : bool =
+ if input1.MoveNext () then
+ Helpers.avoidTailCall (next.ProcessNext (map'.Invoke (input1.Current, input)))
+ else
+ result.StopFurtherProcessing ()
+ false
+
+ override __.OnComplete () =
+ input1.Dispose ()
+
and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>()
@@ -1437,10 +1458,12 @@ namespace Microsoft.FSharp.Collections
revamp2 (IEnumerator.mapi2 f) source1 source2
[]
- let map2 f source1 source2 =
+ let map2<'T,'U,'V> (f:'T->'U->'V) (source1:seq<'T>) (source2:seq<'U>) : seq<'V> =
checkNonNull "source1" source1
checkNonNull "source2" source2
- revamp2 (IEnumerator.map2 f) source1 source2
+ match source1 with
+ | :? SeqComposer.Base.Enumerable<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2))
+ | _ -> source2 |> seqFactory (SeqComposer.Map2SecondFactory (f, source1))
[]
let map3 f source1 source2 source3 =
From ffc4fd2133318a9a848ddaa8c6819fae01fba178 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Sun, 9 Oct 2016 19:29:55 +1100
Subject: [PATCH 027/327] Fix OnComplete/OnDispose
Hmmm... not 100% happy with this because it requires all links in the
chain to ensure that that follow the protocol, but it isn't too bad I
guess...
---
src/fsharp/FSharp.Core/seq.fs | 125 ++++++++++++++++++++--------------
1 file changed, 73 insertions(+), 52 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 89293b410a1..5ac6d90ceda 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -784,6 +784,10 @@ namespace Microsoft.FSharp.Collections
module SeqComposer =
open IEnumerator
+ type ISeqComponent =
+ abstract OnComplete : unit -> unit
+ abstract OnDispose : unit -> unit
+
module Helpers =
// used for performance reasons; these are not recursive calls, so should be safe
let inline avoidTailCall x =
@@ -796,6 +800,7 @@ namespace Microsoft.FSharp.Collections
let inline UpcastEnumerable (t:#IEnumerable<'T>) : IEnumerable<'T> = (# "" t : IEnumerable<'T> #)
let inline UpcastEnumerator (t:#IEnumerator<'T>) : IEnumerator<'T> = (# "" t : IEnumerator<'T> #)
let inline UpcastEnumeratorNonGeneric (t:#IEnumerator) : IEnumerator = (# "" t : IEnumerator #)
+ let inline UpcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #)
type SeqProcessNextStates =
| NotStarted = 1
@@ -812,6 +817,11 @@ namespace Microsoft.FSharp.Collections
member val Current = Unchecked.defaultof<'T> with get, set
+ let seqComponentTail =
+ { new ISeqComponent with
+ member __.OnComplete() = ()
+ member __.OnDispose() = () }
+
type [] SeqComponentFactory<'T,'U> () =
abstract Create<'V> : Result<'V> -> SeqComponent<'U,'V> -> SeqComponent<'T,'V>
@@ -863,9 +873,8 @@ namespace Microsoft.FSharp.Collections
inherit SeqComponentFactory<'T,'T> ()
override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next)
- and [] SeqComponent<'T,'U> () =
+ and [] SeqComponent<'T,'U> (next:ISeqComponent) =
abstract ProcessNext : input:'T -> bool
- abstract OnComplete : unit -> unit
// Seq.init(Infinite)? lazily uses Current. The only SeqComposer component that can do that is Skip
// and it can only do it at the start of a sequence
@@ -874,7 +883,9 @@ namespace Microsoft.FSharp.Collections
abstract CreateMap<'S> : map:('S->'T) -> SeqComponent<'S,'U>
abstract CreateFilter : filter:('T->bool) -> SeqComponent<'T,'U>
- default __.OnComplete () = ()
+ interface ISeqComponent with
+ member __.OnComplete () = next.OnComplete ()
+ member __.OnDispose () = next.OnDispose ()
default __.Skipping () = false
@@ -882,7 +893,7 @@ namespace Microsoft.FSharp.Collections
default this.CreateFilter (filter:'T->bool) = upcast Filter (filter, this)
and Choose<'T,'U,'V> (choose:'T->option<'U>, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
override __.ProcessNext (input:'T) : bool =
match choose input with
@@ -890,7 +901,7 @@ namespace Microsoft.FSharp.Collections
| None -> false
and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
override this.CreateMap<'S> (map:'S->'T) = upcast MapThenFilter<_,_,_> (map, filter, next)
@@ -901,7 +912,7 @@ namespace Microsoft.FSharp.Collections
false
and FilterThenMap<'T,'U,'V> (filter:'T->bool, map:'T->'U, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
override __.ProcessNext (input:'T) : bool =
if filter input then
@@ -910,7 +921,7 @@ namespace Microsoft.FSharp.Collections
false
and Map<'T,'U,'V> (map:'T->'U, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
override this.CreateFilter (filter:'T->bool) = upcast FilterThenMap (filter, map, next)
@@ -918,7 +929,7 @@ namespace Microsoft.FSharp.Collections
Helpers.avoidTailCall (next.ProcessNext (map input))
and Map2First<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable2:IEnumerable<'Second>, result:Result<'V>, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'First,'V>()
+ inherit SeqComponent<'First,'V>(next)
let input2 = enumerable2.GetEnumerator ()
let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map
@@ -930,11 +941,13 @@ namespace Microsoft.FSharp.Collections
result.StopFurtherProcessing ()
false
- override __.OnComplete () =
- input2.Dispose ()
+ interface ISeqComponent with
+ override __.OnDispose () =
+ input2.Dispose ()
+ (Helpers.UpcastISeqComponent next).OnDispose ()
and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'Second,'V>()
+ inherit SeqComponent<'Second,'V>(next)
let input1 = enumerable1.GetEnumerator ()
let map' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt map
@@ -946,11 +959,13 @@ namespace Microsoft.FSharp.Collections
result.StopFurtherProcessing ()
false
- override __.OnComplete () =
- input1.Dispose ()
+ interface ISeqComponent with
+ override __.OnDispose () =
+ input1.Dispose ()
+ (Helpers.UpcastISeqComponent next).OnDispose ()
and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
override __.ProcessNext (input:'T) : bool =
let u = map input
@@ -960,7 +975,7 @@ namespace Microsoft.FSharp.Collections
false
and Mapi<'T,'U,'V> (mapi:int->'T->'U, next:SeqComponent<'U,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
let mutable idx = 0
let mapi' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt mapi
@@ -970,7 +985,7 @@ namespace Microsoft.FSharp.Collections
Helpers.avoidTailCall (next.ProcessNext (mapi'.Invoke (idx-1, input)))
and Pairwise<'T,'V> (next:SeqComponent<'T*'T,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
let mutable isFirst = true
let mutable lastValue = Unchecked.defaultof<'T>
@@ -986,7 +1001,7 @@ namespace Microsoft.FSharp.Collections
Helpers.avoidTailCall (next.ProcessNext currentPair)
and Skip<'T,'V> (skipCount:int, next:SeqComponent<'T,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
let mutable count = 0
@@ -1004,14 +1019,16 @@ namespace Microsoft.FSharp.Collections
else
Helpers.avoidTailCall (next.ProcessNext input)
- override __.OnComplete () =
- if count < skipCount then
- let x = skipCount - count
- invalidOpFmt "tried to skip {0} {1} past the end of the seq"
- [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+ interface ISeqComponent with
+ override __.OnComplete () =
+ if count < skipCount then
+ let x = skipCount - count
+ invalidOpFmt "tried to skip {0} {1} past the end of the seq"
+ [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+ (Helpers.UpcastISeqComponent next).OnComplete ()
and SkipWhile<'T,'V> (predicate:'T->bool, next:SeqComponent<'T,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
let mutable skip = true
@@ -1026,7 +1043,7 @@ namespace Microsoft.FSharp.Collections
Helpers.avoidTailCall (next.ProcessNext input)
and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
let mutable count = 0
@@ -1040,14 +1057,16 @@ namespace Microsoft.FSharp.Collections
result.StopFurtherProcessing ()
false
- override __.OnComplete () =
- if count < takeCount then
- let x = takeCount - count
- invalidOpFmt "tried to take {0} {1} past the end of the seq"
- [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+ interface ISeqComponent with
+ override __.OnComplete () =
+ if count < takeCount then
+ let x = takeCount - count
+ invalidOpFmt "tried to take {0} {1} past the end of the seq"
+ [|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
+ (Helpers.UpcastISeqComponent next).OnComplete ()
and TakeWhile<'T,'V> (predicate:'T->bool, result:Result<'V>, next:SeqComponent<'T,'V>) =
- inherit SeqComponent<'T,'V>()
+ inherit SeqComponent<'T,'V>(next)
override __.ProcessNext (input:'T) : bool =
if predicate input then
@@ -1057,7 +1076,7 @@ namespace Microsoft.FSharp.Collections
false
and Tail<'T> (result:Result<'T>) =
- inherit SeqComponent<'T,'T>()
+ inherit SeqComponent<'T,'T>(seqComponentTail)
override __.ProcessNext (input:'T) : bool =
result.Current <- input
@@ -1065,9 +1084,10 @@ namespace Microsoft.FSharp.Collections
module Base =
[]
- type Enumerator<'T>(result:Result<'T>) =
+ type Enumerator<'T>(result:Result<'T>, seqComponent:ISeqComponent) =
interface IDisposable with
- member __.Dispose() : unit = ()
+ member __.Dispose() : unit =
+ seqComponent.OnDispose ()
interface IEnumerator with
member this.Current : obj = box ((Helpers.UpcastEnumerator this)).Current
@@ -1096,18 +1116,18 @@ namespace Microsoft.FSharp.Collections
member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
module Enumerable =
- type Enumerator<'T,'U>(source:IEnumerator<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit Base.Enumerator<'U>(result)
+ type Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit Base.Enumerator<'U>(result, seqComponent)
let rec moveNext () =
if (not result.Halted) && source.MoveNext () then
- if t2u.ProcessNext source.Current then
+ if seqComponent.ProcessNext source.Current then
true
else
moveNext ()
else
result.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
+ (Helpers.UpcastISeqComponent seqComponent).OnComplete ()
false
interface IEnumerator with
@@ -1116,8 +1136,9 @@ namespace Microsoft.FSharp.Collections
moveNext ()
interface IDisposable with
- member __.Dispose() = source.Dispose ()
-
+ member __.Dispose() =
+ source.Dispose ()
+ (Helpers.UpcastISeqComponent seqComponent).OnDispose ()
type Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
inherit Base.Enumerable<'U>()
@@ -1147,21 +1168,21 @@ namespace Microsoft.FSharp.Collections
// state
module Array =
- type Enumerator<'T,'U>(array:array<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit Base.Enumerator<'U>(result)
+ type Enumerator<'T,'U>(array:array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit Base.Enumerator<'U>(result, seqComponent)
let mutable idx = 0
let rec moveNext () =
if (not result.Halted) && idx < array.Length then
idx <- idx+1
- if t2u.ProcessNext array.[idx-1] then
+ if seqComponent.ProcessNext array.[idx-1] then
true
else
moveNext ()
else
result.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
+ (Helpers.UpcastISeqComponent seqComponent).OnComplete ()
false
interface IEnumerator with
@@ -1197,22 +1218,22 @@ namespace Microsoft.FSharp.Collections
// state
module List =
- type Enumerator<'T,'U>(alist:list<'T>, t2u:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit Base.Enumerator<'U>(result)
+ type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit Base.Enumerator<'U>(result, seqComponent)
let mutable list = alist
let rec moveNext current =
match result.Halted, current with
| false, head::tail ->
- if t2u.ProcessNext head then
+ if seqComponent.ProcessNext head then
list <- tail
true
else
moveNext tail
| _ ->
result.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
+ (Helpers.UpcastISeqComponent seqComponent).OnComplete ()
false
interface IEnumerator with
@@ -1242,8 +1263,8 @@ namespace Microsoft.FSharp.Collections
// so you already know what the count is!! Anyway, someone thought it was a good idea, so
// I have had to add an extra function that is used in Skip to determine if we are touching
// Current or not.
- type Enumerator<'T,'U>(count:Nullable, f:int->'T, t2u:SeqComponent<'T,'U>, signal:Result<'U>) =
- inherit Base.Enumerator<'U>(signal)
+ type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) =
+ inherit Base.Enumerator<'U>(signal, seqComponent)
// we are offset by 1 to allow for values going up to System.Int32.MaxValue
// System.Int32.MaxValue is an illegal value for the "infinite" sequence
@@ -1263,11 +1284,11 @@ namespace Microsoft.FSharp.Collections
if maybeSkipping then
// Skip can only is only checked at the start of the sequence, so once
// triggered, we stay triggered.
- maybeSkipping <- t2u.Skipping ()
+ maybeSkipping <- seqComponent.Skipping ()
if maybeSkipping then
moveNext ()
- elif t2u.ProcessNext (f idx) then
+ elif seqComponent.ProcessNext (f idx) then
true
else
moveNext ()
@@ -1275,7 +1296,7 @@ namespace Microsoft.FSharp.Collections
raise <| System.InvalidOperationException (SR.GetString(SR.enumerationPastIntMaxValue))
else
signal.SeqState <- SeqProcessNextStates.Finished
- t2u.OnComplete ()
+ (Helpers.UpcastISeqComponent seqComponent).OnComplete ()
false
interface IEnumerator with
From 977083970fc7e216dc634ed99d452f12b43269bd Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Mon, 10 Oct 2016 19:35:48 +1100
Subject: [PATCH 028/327] Seq.append
This implemention performs vastly better than the previous
implementation, which appeared to be more interested in being
theoretically important than actually being a reasonable implementation.
Anyway, the previous version blew up with stack overflow if you appended
too many things, which the new version doesn't.
---
src/fsharp/FSharp.Core/seq.fs | 238 ++++++++++------------------------
1 file changed, 72 insertions(+), 166 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 5ac6d90ceda..0c77bfb9e65 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -317,149 +317,6 @@ namespace Microsoft.FSharp.Collections
f()
}
- // Use generators for some implementations of IEnumerables.
- //
- module Generator =
-
- open System.Collections
- open System.Collections.Generic
-
- []
- type Step<'T> =
- | Stop
- | Yield of 'T
- | Goto of Generator<'T>
-
- and Generator<'T> =
- abstract Apply: (unit -> Step<'T>)
- abstract Disposer: (unit -> unit) option
-
- let disposeG (g:Generator<'T>) =
- match g.Disposer with
- | None -> ()
- | Some f -> f()
-
- let appG (g:Generator<_>) =
- //System.Console.WriteLine("{0}.appG", box g)
- let res = g.Apply()
- match res with
- | Goto(next) ->
- Goto(next)
- | Yield _ ->
- res
- | Stop ->
- //System.Console.WriteLine("appG: Stop")
- disposeG g
- res
-
- // Binding.
- //
- // We use a type definition to apply a local dynamic optimization.
- // We automatically right-associate binding, i.e. push the continuations to the right.
- // That is, bindG (bindG G1 cont1) cont2 --> bindG G1 (cont1 o cont2)
- // This makes constructs such as the following linear rather than quadratic:
- //
- // let rec rwalk n = { if n > 0 then
- // yield! rwalk (n-1)
- // yield n }
-
- type GenerateThen<'T>(g:Generator<'T>, cont : unit -> Generator<'T>) =
- member self.Generator = g
- member self.Cont = cont
- interface Generator<'T> with
- member x.Apply = (fun () ->
- match appG g with
- | Stop ->
- // OK, move onto the generator given by the continuation
- Goto(cont())
-
- | Yield _ as res ->
- res
-
- | Goto next ->
- Goto(GenerateThen<_>.Bind(next,cont)))
- member x.Disposer =
- g.Disposer
-
-
- static member Bind (g:Generator<'T>, cont) =
- match g with
- | :? GenerateThen<'T> as g -> GenerateThen<_>.Bind(g.Generator,(fun () -> GenerateThen<_>.Bind (g.Cont(), cont)))
- | g -> (new GenerateThen<'T>(g, cont) :> Generator<'T>)
-
-
- let bindG g cont = GenerateThen<_>.Bind(g,cont)
-
-
- // Internal type. Drive an underlying generator. Crucially when the generator returns
- // a new generator we simply update our current generator and continue. Thus the enumerator
- // effectively acts as a reference cell holding the current generator. This means that
- // infinite or large generation chains (e.g. caused by long sequences of append's, including
- // possible delay loops) can be referenced via a single enumerator.
- //
- // A classic case where this arises in this sort of sequence expression:
- // let rec data s = { yield s;
- // yield! data (s + random()) }
- //
- // This translates to
- // let rec data s = Seq.delay (fun () -> Seq.append (Seq.singleton s) (Seq.delay (fun () -> data (s+random()))))
- //
- // When you unwind through all the Seq, IEnumerator and Generator objects created,
- // you get (data s).GetEnumerator being an "GenerateFromEnumerator(EnumeratorWrappingLazyGenerator(...))" for the append.
- // After one element is yielded, we move on to the generator for the inner delay, which in turn
- // comes back to be a "GenerateFromEnumerator(EnumeratorWrappingLazyGenerator(...))".
- //
- // Defined as a type so we can optimize Enumerator/Generator chains in enumerateFromLazyGenerator
- // and GenerateFromEnumerator.
-
- []
- type EnumeratorWrappingLazyGenerator<'T>(g:Generator<'T>) =
- let mutable g = g
- let mutable curr = None
- let mutable finished = false
- member e.Generator = g
- interface IEnumerator<'T> with
- member x.Current= match curr with Some(v) -> v | None -> raise <| System.InvalidOperationException (SR.GetString(SR.moveNextNotCalledOrFinished))
- interface System.Collections.IEnumerator with
- member x.Current = box (x :> IEnumerator<_>).Current
- member x.MoveNext() =
- not finished &&
- (match appG g with
- | Stop ->
- curr <- None
- finished <- true
- false
- | Yield(v) ->
- curr <- Some(v)
- true
- | Goto(next) ->
- (g <- next)
- (x :> IEnumerator).MoveNext())
- member x.Reset() = IEnumerator.noReset()
- interface System.IDisposable with
- member x.Dispose() =
- if not finished then disposeG g
-
- // Internal type, used to optimize Enumerator/Generator chains
- type LazyGeneratorWrappingEnumerator<'T>(e:System.Collections.Generic.IEnumerator<'T>) =
- member g.Enumerator = e
- interface Generator<'T> with
- member g.Apply = (fun () ->
- if e.MoveNext() then
- Yield(e.Current)
- else
- Stop)
- member g.Disposer= Some(e.Dispose)
-
- let EnumerateFromGenerator(g:Generator<'T>) =
- match g with
- | :? LazyGeneratorWrappingEnumerator<'T> as g -> g.Enumerator
- | _ -> (new EnumeratorWrappingLazyGenerator<_>(g) :> System.Collections.Generic.IEnumerator<_>)
-
- let GenerateFromEnumerator (e:System.Collections.Generic.IEnumerator<'T>) =
- match e with
- | :? EnumeratorWrappingLazyGenerator<'T> as e -> e.Generator
- | _ -> (new LazyGeneratorWrappingEnumerator<'T>(e) :> Generator<'T>)
namespace Microsoft.FSharp.Core.CompilerServices
@@ -1082,9 +939,9 @@ namespace Microsoft.FSharp.Collections
result.Current <- input
true
- module Base =
+ module Enumerable =
[]
- type Enumerator<'T>(result:Result<'T>, seqComponent:ISeqComponent) =
+ type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) =
interface IDisposable with
member __.Dispose() : unit =
seqComponent.OnDispose ()
@@ -1101,10 +958,11 @@ namespace Microsoft.FSharp.Collections
| SeqProcessNextStates.Finished -> alreadyFinished()
| _ -> result.Current
-
- []
- type Enumerable<'T> () =
+ and [] EnumerableBase<'T> () =
abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
+ abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T>
+
+ default this.Append source = Helpers.UpcastEnumerable (AppendEnumerable [this; source])
interface IEnumerable with
member this.GetEnumerator () : IEnumerator =
@@ -1115,9 +973,8 @@ namespace Microsoft.FSharp.Collections
interface IEnumerable<'T> with
member this.GetEnumerator () : IEnumerator<'T> = failwith "library implementation error: derived class should implement (should be abstract)"
- module Enumerable =
- type Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit Base.Enumerator<'U>(result, seqComponent)
+ and Enumerator<'T,'U>(source:IEnumerator<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
+ inherit EnumeratorBase<'U>(result, seqComponent)
let rec moveNext () =
if (not result.Halted) && source.MoveNext () then
@@ -1140,8 +997,8 @@ namespace Microsoft.FSharp.Collections
source.Dispose ()
(Helpers.UpcastISeqComponent seqComponent).OnDispose ()
- type Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit Base.Enumerable<'U>()
+ and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
+ inherit EnumerableBase<'U>()
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
@@ -1167,9 +1024,59 @@ namespace Microsoft.FSharp.Collections
//
// state
+ and AppendEnumerator<'T> (sources:list>) =
+ let sources = sources |> List.rev
+
+ let mutable state = SeqProcessNextStates.NotStarted
+ let mutable remaining = sources.Tail
+ let mutable active = sources.Head.GetEnumerator ()
+
+ let rec moveNext () =
+ if active.MoveNext () then true
+ else
+ match remaining with
+ | [] -> false
+ | hd :: tl ->
+ active.Dispose ()
+ active <- hd.GetEnumerator ()
+ remaining <- tl
+
+ moveNext ()
+
+ interface IEnumerator<'T> with
+ member __.Current =
+ match state with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> active.Current
+
+ interface IEnumerator with
+ member __.Current = (Helpers.UpcastEnumeratorNonGeneric active).Current
+ member __.MoveNext () =
+ state <- SeqProcessNextStates.InProcess
+ moveNext ()
+ member __.Reset () = noReset ()
+
+ interface IDisposable with
+ member __.Dispose() =
+ active.Dispose ()
+
+ and AppendEnumerable<'T> (sources:list>) =
+ inherit EnumerableBase<'T>()
+
+ interface IEnumerable<'T> with
+ member this.GetEnumerator () : IEnumerator<'T> =
+ Helpers.UpcastEnumerator (new AppendEnumerator<_> (sources))
+
+ override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
+ Helpers.UpcastEnumerable (Enumerable<'T,'V>(this, next))
+
+ override this.Append source =
+ Helpers.UpcastEnumerable (AppendEnumerable (source :: sources))
+
module Array =
type Enumerator<'T,'U>(array:array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit Base.Enumerator<'U>(result, seqComponent)
+ inherit Enumerable.EnumeratorBase<'U>(result, seqComponent)
let mutable idx = 0
@@ -1191,7 +1098,7 @@ namespace Microsoft.FSharp.Collections
moveNext ()
type Enumerable<'T,'U>(array:array<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit Base.Enumerable<'U>()
+ inherit Enumerable.EnumerableBase<'U>()
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
@@ -1219,7 +1126,7 @@ namespace Microsoft.FSharp.Collections
module List =
type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
- inherit Base.Enumerator<'U>(result, seqComponent)
+ inherit Enumerable.EnumeratorBase<'U>(result, seqComponent)
let mutable list = alist
@@ -1242,7 +1149,7 @@ namespace Microsoft.FSharp.Collections
moveNext list
type Enumerable<'T,'U>(alist:list<'T>, current:SeqComponentFactory<'T,'U>) =
- inherit Base.Enumerable<'U>()
+ inherit Enumerable.EnumerableBase<'U>()
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
@@ -1264,7 +1171,7 @@ namespace Microsoft.FSharp.Collections
// I have had to add an extra function that is used in Skip to determine if we are touching
// Current or not.
type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) =
- inherit Base.Enumerator<'U>(signal, seqComponent)
+ inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent)
// we are offset by 1 to allow for values going up to System.Int32.MaxValue
// System.Int32.MaxValue is an illegal value for the "infinite" sequence
@@ -1305,7 +1212,7 @@ namespace Microsoft.FSharp.Collections
moveNext ()
type Enumerable<'T,'U>(count:Nullable, f:int->'T, current:SeqComponentFactory<'T,'U>) =
- inherit Base.Enumerable<'U>()
+ inherit Enumerable.EnumerableBase<'U>()
interface IEnumerable<'U> with
member this.GetEnumerator () : IEnumerator<'U> =
@@ -1316,7 +1223,7 @@ namespace Microsoft.FSharp.Collections
Helpers.UpcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next)))
type EnumerableDecider<'T>(count:Nullable, f:int->'T) =
- inherit Base.Enumerable<'T>()
+ inherit Enumerable.EnumerableBase<'T>()
interface IEnumerable<'T> with
member this.GetEnumerator () : IEnumerator<'T> =
@@ -1452,7 +1359,7 @@ namespace Microsoft.FSharp.Collections
let private seqFactory createSeqComponent (source:seq<'T>) =
checkNonNull "source" source
match source with
- | :? SeqComposer.Base.Enumerable<'T> as s -> s.Compose createSeqComponent
+ | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose createSeqComponent
| :? array<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Array.Enumerable<_,_>(a, createSeqComponent))
| :? list<'T> as a -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.List.Enumerable<_,_>(a, createSeqComponent))
| _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Enumerable.Enumerable<_,_>(source, createSeqComponent))
@@ -1483,7 +1390,7 @@ namespace Microsoft.FSharp.Collections
checkNonNull "source1" source1
checkNonNull "source2" source2
match source1 with
- | :? SeqComposer.Base.Enumerable<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2))
+ | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Compose (SeqComposer.Map2FirstFactory (f, source2))
| _ -> source2 |> seqFactory (SeqComposer.Map2SecondFactory (f, source1))
[]
@@ -1628,9 +1535,6 @@ namespace Microsoft.FSharp.Collections
state <- f.Invoke(state, e.Current)
state
- let fromGenerator f = mkSeq(fun () -> Generator.EnumerateFromGenerator (f()))
- let toGenerator (ie : seq<_>) = Generator.GenerateFromEnumerator (ie.GetEnumerator())
-
[]
let replicate count x =
#if FX_ATLEAST_40
@@ -1645,7 +1549,9 @@ namespace Microsoft.FSharp.Collections
let append (source1: seq<'T>) (source2: seq<'T>) =
checkNonNull "source1" source1
checkNonNull "source2" source2
- fromGenerator(fun () -> Generator.bindG (toGenerator source1) (fun () -> toGenerator source2))
+ match source1 with
+ | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Append source2
+ | _ -> SeqComposer.Helpers.UpcastEnumerable (new SeqComposer.Enumerable.AppendEnumerable<_>([source2; source1]))
[]
From 7e9cb8b3744aec00488b4ead3db465bf5de05790 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Mon, 10 Oct 2016 19:42:40 +1100
Subject: [PATCH 029/327] minor perf; assume "InProcess"
---
src/fsharp/FSharp.Core/seq.fs | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 0c77bfb9e65..a63df1b7719 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -660,9 +660,9 @@ namespace Microsoft.FSharp.Collections
let inline UpcastISeqComponent (t:#ISeqComponent) : ISeqComponent = (# "" t : ISeqComponent #)
type SeqProcessNextStates =
+ | InProcess = 0
| NotStarted = 1
| Finished = 2
- | InProcess = 3
type Result<'T>() =
let mutable halted = false
@@ -953,10 +953,12 @@ namespace Microsoft.FSharp.Collections
interface IEnumerator<'T> with
member __.Current =
- match result.SeqState with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> result.Current
+ if result.SeqState = SeqProcessNextStates.InProcess then result.Current
+ else
+ match result.SeqState with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> failwith "library implementation error: all states should have been handled"
and [] EnumerableBase<'T> () =
abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
@@ -1045,10 +1047,12 @@ namespace Microsoft.FSharp.Collections
interface IEnumerator<'T> with
member __.Current =
- match state with
- | SeqProcessNextStates.NotStarted -> notStarted()
- | SeqProcessNextStates.Finished -> alreadyFinished()
- | _ -> active.Current
+ if state = SeqProcessNextStates.InProcess then active.Current
+ else
+ match state with
+ | SeqProcessNextStates.NotStarted -> notStarted()
+ | SeqProcessNextStates.Finished -> alreadyFinished()
+ | _ -> failwith "library implementation error: all states should have been handled"
interface IEnumerator with
member __.Current = (Helpers.UpcastEnumeratorNonGeneric active).Current
From 026551f71b3979f8f96301463a6737777db182d0 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Mon, 10 Oct 2016 19:46:35 +1100
Subject: [PATCH 030/327] Bug fix; ensure exception protocol is followed
---
src/fsharp/FSharp.Core/seq.fs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index a63df1b7719..60c228b0530 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1055,7 +1055,7 @@ namespace Microsoft.FSharp.Collections
| _ -> failwith "library implementation error: all states should have been handled"
interface IEnumerator with
- member __.Current = (Helpers.UpcastEnumeratorNonGeneric active).Current
+ member this.Current = box ((Helpers.UpcastEnumerator this)).Current
member __.MoveNext () =
state <- SeqProcessNextStates.InProcess
moveNext ()
From 5acb7dffc9edccaac79a5d04bc49eb0bf525d515 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Tue, 11 Oct 2016 19:32:19 +1100
Subject: [PATCH 031/327] Seq.fold
---
src/fsharp/FSharp.Core/seq.fs | 156 ++++++++++++++++++++++++----------
1 file changed, 113 insertions(+), 43 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 60c228b0530..24e42f51c14 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -963,6 +963,7 @@ namespace Microsoft.FSharp.Collections
and [] EnumerableBase<'T> () =
abstract member Compose<'U> : (SeqComponentFactory<'T,'U>) -> IEnumerable<'U>
abstract member Append<'T> : (seq<'T>) -> IEnumerable<'T>
+ abstract member Fold<'State> : folder:('State->'T->'State) -> state:'State -> 'State
default this.Append source = Helpers.UpcastEnumerable (AppendEnumerable [this; source])
@@ -1010,21 +1011,20 @@ namespace Microsoft.FSharp.Collections
override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new Enumerable<'T,'V>(enumerable, ComposedFactory (current, next)))
- // interface ISeqEnumerable<'U> with
- // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
- // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
- //
- // let enumerator = enumerable.GetEnumerator ()
- // let result = Result<'U> ()
- //
- // let components = current.Create result (Tail result)
- //
- // let mutable state = initialState
- // while (not result.Halted) && enumerator.MoveNext () do
- // if components.ProcessNext (enumerator.Current) then
- // state <- folder'.Invoke (state, result.Current)
- //
- // state
+ override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let enumerator = enumerable.GetEnumerator ()
+ let result = Result<'U> ()
+
+ let components = current.Create result (Tail result)
+
+ let mutable state = initialState
+ while (not result.Halted) && (enumerator.MoveNext ()) do
+ if components.ProcessNext (enumerator.Current) then
+ state <- folder'.Invoke (state, result.Current)
+
+ state
and AppendEnumerator<'T> (sources:list>) =
let sources = sources |> List.rev
@@ -1078,6 +1078,18 @@ namespace Microsoft.FSharp.Collections
override this.Append source =
Helpers.UpcastEnumerable (AppendEnumerable (source :: sources))
+ override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let enumerable = Helpers.UpcastEnumerable (AppendEnumerable sources)
+ let enumerator = enumerable.GetEnumerator ()
+
+ let mutable state = initialState
+ while enumerator.MoveNext () do
+ state <- folder'.Invoke (state, enumerator.Current)
+
+ state
+
module Array =
type Enumerator<'T,'U>(array:array<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
inherit Enumerable.EnumeratorBase<'U>(result, seqComponent)
@@ -1112,21 +1124,20 @@ namespace Microsoft.FSharp.Collections
override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new Enumerable<'T,'V>(array, ComposedFactory (current, next)))
- // interface ISeqEnumerable<'U> with
- // member this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
- // let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
- //
- // let mutable idx = 0
- // let result = Result<'U> ()
- // let components = current.Create result (Tail result)
- //
- // let mutable state = initialState
- // while (not result.Halted) && idx < array.Length do
- // if components.ProcessNext array.[idx] then
- // state <- folder'.Invoke(state, result.Current)
- // idx <- idx + 1
- //
- // state
+ override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let mutable idx = 0
+ let result = Result<'U> ()
+ let components = current.Create result (Tail result)
+
+ let mutable state = initialState
+ while (not result.Halted) && (idx < array.Length) do
+ if components.ProcessNext array.[idx] then
+ state <- folder'.Invoke (state, result.Current)
+ idx <- idx + 1
+
+ state
module List =
type Enumerator<'T,'U>(alist:list<'T>, seqComponent:SeqComponent<'T,'U>, result:Result<'U>) =
@@ -1163,6 +1174,24 @@ namespace Microsoft.FSharp.Collections
override __.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new Enumerable<'T,'V>(alist, ComposedFactory (current, next)))
+ override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let result = Result<'U> ()
+ let components = current.Create result (Tail result)
+
+ let rec fold state lst =
+ match result.Halted, lst with
+ | true, _
+ | false, [] -> state
+ | false, hd :: tl ->
+ if components.ProcessNext hd then
+ fold (folder'.Invoke (state, result.Current)) tl
+ else
+ fold state tl
+
+ fold initialState alist
+
module Init =
// The original implementation of "init" delayed the calculation of Current, and so it was possible
// to do MoveNext without it's value being calculated.
@@ -1174,16 +1203,20 @@ namespace Microsoft.FSharp.Collections
// so you already know what the count is!! Anyway, someone thought it was a good idea, so
// I have had to add an extra function that is used in Skip to determine if we are touching
// Current or not.
- type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) =
- inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent)
+ let getTerminatingIdx (count:Nullable) =
// we are offset by 1 to allow for values going up to System.Int32.MaxValue
// System.Int32.MaxValue is an illegal value for the "infinite" sequence
+ if count.HasValue then
+ count.Value - 1
+ else
+ System.Int32.MaxValue
+
+ type Enumerator<'T,'U>(count:Nullable, f:int->'T, seqComponent:SeqComponent<'T,'U>, signal:Result<'U>) =
+ inherit Enumerable.EnumeratorBase<'U>(signal, seqComponent)
+
let terminatingIdx =
- if count.HasValue then
- count.Value - 1
- else
- System.Int32.MaxValue
+ getTerminatingIdx count
let mutable maybeSkipping = true
let mutable idx = -1
@@ -1226,6 +1259,29 @@ namespace Microsoft.FSharp.Collections
override this.Compose (next:SeqComponentFactory<'U,'V>) : IEnumerable<'V> =
Helpers.UpcastEnumerable (new Enumerable<'T,'V>(count, f, ComposedFactory (current, next)))
+ override this.Fold<'State> (folder:'State->'U->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let result = Result<'U> ()
+ let components = current.Create result (Tail result)
+
+ let mutable idx = -1
+ let terminatingIdx = getTerminatingIdx count
+
+ let mutable maybeSkipping = true
+
+ let mutable state = initialState
+ while (not result.Halted) && (idx < terminatingIdx) do
+ if maybeSkipping then
+ maybeSkipping <- components.Skipping ()
+
+ if (not maybeSkipping) && (components.ProcessNext (f (idx+1))) then
+ state <- folder'.Invoke (state, result.Current)
+
+ idx <- idx + 1
+
+ state
+
type EnumerableDecider<'T>(count:Nullable, f:int->'T) =
inherit Enumerable.EnumerableBase<'T>()
@@ -1239,6 +1295,17 @@ namespace Microsoft.FSharp.Collections
override this.Compose (next:SeqComponentFactory<'T,'U>) : IEnumerable<'U> =
Helpers.UpcastEnumerable (Enumerable<'T,'V>(count, f, next))
+ override this.Fold<'State> (folder:'State->'T->'State) (initialState:'State) : 'State =
+ let folder' = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
+
+ let enumerator = (Helpers.UpcastEnumerable this).GetEnumerator ()
+
+ let mutable state = initialState
+ while enumerator.MoveNext () do
+ state <- folder'.Invoke (state, enumerator.Current)
+
+ state
+
#if FX_NO_ICLONEABLE
open Microsoft.FSharp.Core.ICloneableExtensions
#else
@@ -1503,14 +1570,17 @@ namespace Microsoft.FSharp.Collections
state
[]
- let fold<'T,'State> f (x:'State) (source : seq<'T>) =
+ let fold<'T,'State> f (x:'State) (source:seq<'T>) =
checkNonNull "source" source
- use e = source.GetEnumerator()
- let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
- let mutable state = x
- while e.MoveNext() do
- state <- f.Invoke(state, e.Current)
- state
+ match source with
+ | :? SeqComposer.Enumerable.EnumerableBase<'T> as s -> s.Fold f x
+ | _ ->
+ use e = source.GetEnumerator()
+ let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
+ let mutable state = x
+ while e.MoveNext() do
+ state <- f.Invoke(state, e.Current)
+ state
[]
let fold2<'T1,'T2,'State> f (state:'State) (source1: seq<'T1>) (source2: seq<'T2>) =
From 6775b56595c77f3845489ad82433e01f1b248aa4 Mon Sep 17 00:00:00 2001
From: liboz
Date: Tue, 11 Oct 2016 16:28:24 -0400
Subject: [PATCH 032/327] fix typo
---
src/fsharp/FSharp.Core/seq.fs | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 24e42f51c14..7c7c92376f6 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -718,13 +718,13 @@ namespace Microsoft.FSharp.Collections
inherit SeqComponentFactory<'T,'T> ()
override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Skip (count, next)
- and SkipWhileFactory<'T> (perdicate:'T->bool) =
+ and SkipWhileFactory<'T> (predicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (perdicate, next)
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast SkipWhile (predicate, next)
- and TakeWhileFactory<'T> (perdicate:'T->bool) =
+ and TakeWhileFactory<'T> (predicate:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
- override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (perdicate, result, next)
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast TakeWhile (predicate, result, next)
and TakeFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
From 23b72bba48a2b906c92afab4e8e53aed28cdbe1e Mon Sep 17 00:00:00 2001
From: liboz
Date: Tue, 11 Oct 2016 21:16:38 -0400
Subject: [PATCH 033/327] truncate
---
src/fsharp/FSharp.Core/seq.fs | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 7c7c92376f6..f2c5b5c8db0 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -729,6 +729,10 @@ namespace Microsoft.FSharp.Collections
and TakeFactory<'T> (count:int) =
inherit SeqComponentFactory<'T,'T> ()
override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Take (count, result, next)
+
+ and TruncateFactory<'T> (count:int) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Truncate (count, result, next)
and [] SeqComponent<'T,'U> (next:ISeqComponent) =
abstract ProcessNext : input:'T -> bool
@@ -939,6 +943,21 @@ namespace Microsoft.FSharp.Collections
result.Current <- input
true
+ and Truncate<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>(next)
+
+ let mutable count = 0
+
+ override __.ProcessNext (input:'T) : bool =
+ if count < takeCount then
+ count <- count + 1
+ if count = takeCount then
+ result.StopFurtherProcessing ()
+ next.ProcessNext input
+ else
+ result.StopFurtherProcessing ()
+ false
+
module Enumerable =
[]
type EnumeratorBase<'T>(result:Result<'T>, seqComponent:ISeqComponent) =
@@ -1716,12 +1735,7 @@ namespace Microsoft.FSharp.Collections
[]
let truncate n (source: seq<'T>) =
- checkNonNull "source" source
- seq { let i = ref 0
- use ie = source.GetEnumerator()
- while !i < n && ie.MoveNext() do
- i := !i + 1
- yield ie.Current }
+ source |> seqFactory (SeqComposer.TruncateFactory n)
[]
let pairwise<'T> (source:seq<'T>) : seq<'T*'T> =
From 5013d453b8c33f8bbda8c3f58e73e983f3661815 Mon Sep 17 00:00:00 2001
From: liboz
Date: Tue, 11 Oct 2016 22:36:09 -0400
Subject: [PATCH 034/327] using inheritance for take
---
src/fsharp/FSharp.Core/seq.fs | 28 +++++++++-------------------
1 file changed, 9 insertions(+), 19 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index f2c5b5c8db0..e7f40e14e69 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -904,24 +904,12 @@ namespace Microsoft.FSharp.Collections
Helpers.avoidTailCall (next.ProcessNext input)
and Take<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
- inherit SeqComponent<'T,'V>(next)
-
- let mutable count = 0
-
- override __.ProcessNext (input:'T) : bool =
- if count < takeCount then
- count <- count + 1
- if count = takeCount then
- result.StopFurtherProcessing ()
- next.ProcessNext input
- else
- result.StopFurtherProcessing ()
- false
+ inherit Truncate<'T, 'V>(takeCount, result, next)
interface ISeqComponent with
- override __.OnComplete () =
- if count < takeCount then
- let x = takeCount - count
+ override this.OnComplete () =
+ if this.Count < takeCount then
+ let x = takeCount - this.Count
invalidOpFmt "tried to take {0} {1} past the end of the seq"
[|SR.GetString SR.notEnoughElements; x; (if x=1 then "element" else "elements")|]
(Helpers.UpcastISeqComponent next).OnComplete ()
@@ -943,15 +931,17 @@ namespace Microsoft.FSharp.Collections
result.Current <- input
true
- and Truncate<'T,'V> (takeCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
+ and Truncate<'T,'V> (truncateCount:int, result:Result<'V>, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>(next)
let mutable count = 0
+ member __.Count = count
+
override __.ProcessNext (input:'T) : bool =
- if count < takeCount then
+ if count < truncateCount then
count <- count + 1
- if count = takeCount then
+ if count = truncateCount then
result.StopFurtherProcessing ()
next.ProcessNext input
else
From 10130c9d15db0e7c160dbea22cac39c36a6ed965 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Wed, 12 Oct 2016 19:08:05 +1100
Subject: [PATCH 035/327] Carry on disposing under exceptions
---
src/fsharp/FSharp.Core/seq.fs | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index e7f40e14e69..09686d63970 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -804,8 +804,10 @@ namespace Microsoft.FSharp.Collections
interface ISeqComponent with
override __.OnDispose () =
- input2.Dispose ()
- (Helpers.UpcastISeqComponent next).OnDispose ()
+ try
+ input2.Dispose ()
+ finally
+ (Helpers.UpcastISeqComponent next).OnDispose ()
and Map2Second<'First,'Second,'U,'V> (map:'First->'Second->'U, enumerable1:IEnumerable<'First>, result:Result<'V>, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'Second,'V>(next)
@@ -822,8 +824,10 @@ namespace Microsoft.FSharp.Collections
interface ISeqComponent with
override __.OnDispose () =
- input1.Dispose ()
- (Helpers.UpcastISeqComponent next).OnDispose ()
+ try
+ input1.Dispose ()
+ finally
+ (Helpers.UpcastISeqComponent next).OnDispose ()
and MapThenFilter<'T,'U,'V> (map:'T->'U, filter:'U->bool, next:SeqComponent<'U,'V>) =
inherit SeqComponent<'T,'V>(next)
@@ -1006,8 +1010,10 @@ namespace Microsoft.FSharp.Collections
interface IDisposable with
member __.Dispose() =
- source.Dispose ()
- (Helpers.UpcastISeqComponent seqComponent).OnDispose ()
+ try
+ source.Dispose ()
+ finally
+ (Helpers.UpcastISeqComponent seqComponent).OnDispose ()
and Enumerable<'T,'U>(enumerable:IEnumerable<'T>, current:SeqComponentFactory<'T,'U>) =
inherit EnumerableBase<'U>()
From e7d7d059e5b395f89a07c88515ed4e259e0d9fe6 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Wed, 12 Oct 2016 20:23:43 +1100
Subject: [PATCH 036/327] bug fix: "truncate 0" was causing MoveNext on
underlying seq
---
src/fsharp/FSharp.Core/seq.fs | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 09686d63970..4ff4fa947ab 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1731,6 +1731,7 @@ namespace Microsoft.FSharp.Collections
[]
let truncate n (source: seq<'T>) =
+ if n <= 0 then empty else
source |> seqFactory (SeqComposer.TruncateFactory n)
[]
From 9daf01d46a7881706182a01648915371accf353a Mon Sep 17 00:00:00 2001
From: liboz
Date: Wed, 12 Oct 2016 21:46:26 -0400
Subject: [PATCH 037/327] distinct/distinctby
---
src/fsharp/FSharp.Core/seq.fs | 42 ++++++++++++++++++++++++++---------
1 file changed, 32 insertions(+), 10 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 4ff4fa947ab..429525ff527 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -689,6 +689,14 @@ namespace Microsoft.FSharp.Collections
and ChooseFactory<'T,'U> (filter:'T->option<'U>) =
inherit SeqComponentFactory<'T,'U> ()
override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'U,'V>) : SeqComponent<'T,'V> = upcast Choose (filter, next)
+
+ and DistinctFactory<'T when 'T: equality> () =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Distinct (next)
+
+ and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast DistinctBy (keyFunction, next)
and FilterFactory<'T> (filter:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
@@ -761,6 +769,28 @@ namespace Microsoft.FSharp.Collections
| Some value -> Helpers.avoidTailCall (next.ProcessNext value)
| None -> false
+ and Distinct<'T,'V when 'T: equality> (next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>(next)
+
+ let hashSet = HashSet<'T>(HashIdentity.Structural<'T>)
+
+ override __.ProcessNext (input:'T) : bool =
+ if hashSet.Add input then
+ Helpers.avoidTailCall (next.ProcessNext input)
+ else
+ false
+
+ and DistinctBy<'T,'Key,'V when 'Key: equality> (keyFunction: 'T -> 'Key, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>(next)
+
+ let hashSet = HashSet<'Key>(HashIdentity.Structural<'Key>)
+
+ override __.ProcessNext (input:'T) : bool =
+ if hashSet.Add(keyFunction input) then
+ Helpers.avoidTailCall (next.ProcessNext input)
+ else
+ false
+
and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>(next)
@@ -1944,19 +1974,11 @@ namespace Microsoft.FSharp.Collections
[]
let distinct source =
- checkNonNull "source" source
- seq { let hashSet = HashSet<'T>(HashIdentity.Structural<'T>)
- for v in source do
- if hashSet.Add(v) then
- yield v }
+ source |> seqFactory (SeqComposer.DistinctFactory ())
[]
let distinctBy keyf source =
- checkNonNull "source" source
- seq { let hashSet = HashSet<_>(HashIdentity.Structural<_>)
- for v in source do
- if hashSet.Add(keyf v) then
- yield v }
+ source |> seqFactory (SeqComposer.DistinctByFactory keyf)
[]
let sortBy keyf source =
From dc3789d531a844d74f6c9baaddeac3a0238ff795 Mon Sep 17 00:00:00 2001
From: liboz
Date: Thu, 13 Oct 2016 06:19:09 -0400
Subject: [PATCH 038/327] except
---
src/fsharp/FSharp.Core/seq.fs | 27 ++++++++++++++++-----------
1 file changed, 16 insertions(+), 11 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 429525ff527..31c7afea626 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -697,6 +697,10 @@ namespace Microsoft.FSharp.Collections
and DistinctByFactory<'T,'Key when 'Key: equality> (keyFunction:'T-> 'Key) =
inherit SeqComponentFactory<'T,'T> ()
override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast DistinctBy (keyFunction, next)
+
+ and ExceptFactory<'T when 'T: equality> (itemsToExclude: seq<'T>) =
+ inherit SeqComponentFactory<'T,'T> ()
+ override __.Create<'V> (_result:Result<'V>) (next:SeqComponent<'T,'V>) : SeqComponent<'T,'V> = upcast Except (itemsToExclude, next)
and FilterFactory<'T> (filter:'T->bool) =
inherit SeqComponentFactory<'T,'T> ()
@@ -791,6 +795,17 @@ namespace Microsoft.FSharp.Collections
else
false
+ and Except<'T,'V when 'T: equality> (itemsToExclude: seq<'T>, next:SeqComponent<'T,'V>) =
+ inherit SeqComponent<'T,'V>(next)
+
+ let cached = lazy(HashSet(itemsToExclude, HashIdentity.Structural))
+
+ override __.ProcessNext (input:'T) : bool =
+ if cached.Value.Add input then
+ Helpers.avoidTailCall (next.ProcessNext input)
+ else
+ false
+
and Filter<'T,'V> (filter:'T->bool, next:SeqComponent<'T,'V>) =
inherit SeqComponent<'T,'V>(next)
@@ -2311,17 +2326,7 @@ namespace Microsoft.FSharp.Collections
[]
let except (itemsToExclude: seq<'T>) (source: seq<'T>) =
checkNonNull "itemsToExclude" itemsToExclude
- checkNonNull "source" source
-
- seq {
- use e = source.GetEnumerator()
- if e.MoveNext() then
- let cached = HashSet(itemsToExclude, HashIdentity.Structural)
- let next = e.Current
- if (cached.Add next) then yield next
- while e.MoveNext() do
- let next = e.Current
- if (cached.Add next) then yield next }
+ source |> seqFactory (SeqComposer.ExceptFactory itemsToExclude)
[]
let chunkBySize chunkSize (source : seq<_>) =
From aca3d9c06c400d12289e32149e9fc30fd93d4763 Mon Sep 17 00:00:00 2001
From: liboz
Date: Thu, 13 Oct 2016 21:55:52 -0400
Subject: [PATCH 039/327] indexed
---
src/fsharp/FSharp.Core/seq.fs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 31c7afea626..6311a0a09dc 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1537,8 +1537,7 @@ namespace Microsoft.FSharp.Collections
[]
let indexed source =
- checkNonNull "source" source
- mapi (fun i x -> i,x) source
+ source |> seqFactory (SeqComposer.MapiFactory (fun i x -> i,x) )
[]
let zip source1 source2 =
From 928b9e3f0cd999e9fabe9920916836b29b006864 Mon Sep 17 00:00:00 2001
From: liboz
Date: Thu, 13 Oct 2016 22:53:06 -0400
Subject: [PATCH 040/327] zip/zip3
---
src/fsharp/FSharp.Core/seq.fs | 5 -----
1 file changed, 5 deletions(-)
diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs
index 6311a0a09dc..b651c4982c1 100644
--- a/src/fsharp/FSharp.Core/seq.fs
+++ b/src/fsharp/FSharp.Core/seq.fs
@@ -1541,15 +1541,10 @@ namespace Microsoft.FSharp.Collections
[]
let zip source1 source2 =
- checkNonNull "source1" source1
- checkNonNull "source2" source2
map2 (fun x y -> x,y) source1 source2
[