@@ -108,6 +108,20 @@ namespace Microsoft.FSharp.Collections
108
108
member __.GetHashCode o = c.GetHashCode o._ 1
109
109
member __.Equals ( lhs , rhs ) = c.Equals ( lhs._ 1, rhs._ 1) }
110
110
111
+ [<AbstractClass>]
112
+ type PreferGetEnumerator < 'T >() =
113
+ inherit EnumerableBase< 'T>()
114
+
115
+ abstract GetEnumerator: unit -> IEnumerator < 'T >
116
+ abstract GetSeq : unit -> ISeq < 'T >
117
+
118
+ interface IEnumerable< 'T> with
119
+ member this.GetEnumerator () : IEnumerator < 'T > = this.GetEnumerator ()
120
+
121
+ interface ISeq< 'T> with
122
+ member this.PushTransform < 'U > ( next : ITransformFactory < 'T , 'U >) : ISeq < 'U > = ( this.GetSeq()) .PushTransform next
123
+ member this.Fold < 'Result > ( f : PipeIdx -> Folder < 'T , 'Result >) : 'Result = ( this.GetSeq()) .Fold f
124
+
111
125
[<CompiledName " Empty" >]
112
126
let empty < 'T > = Microsoft.FSharp.Collections.SeqComposition.Core.EmptyEnumerable< 'T>. Instance
113
127
@@ -592,17 +606,79 @@ namespace Microsoft.FSharp.Collections
592
606
let concat ( sources : ISeq < #ISeq < 'T >>) : ISeq < 'T > =
593
607
upcast ( ThinConcatEnumerable ( sources, id))
594
608
609
+ (*
610
+ Represents the following seq comprehension, but they don't work at this level
611
+
612
+ seq {
613
+ let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt folder
614
+ let mutable state = initialState
615
+ yield state
616
+ for item in enumerable do
617
+ state <- f.Invoke (state, item)
618
+ yield state }
619
+ *)
620
+ type ScanEnumerator < 'T , 'State >( folder : 'State -> 'T -> 'State , initialState : 'State , enumerable :seq < 'T >) =
621
+ let f = OptimizedClosures.FSharpFunc<_,_,_>. Adapt folder
622
+
623
+ let mutable state = 0 (* Pre-start*)
624
+ let mutable enumerator = Unchecked.defaultof< IEnumerator< 'T>>
625
+ let mutable current = initialState
626
+
627
+ interface IEnumerator< 'State> with
628
+ member this.Current : 'State =
629
+ match state with
630
+ | 0 (* PreStart*) -> notStarted()
631
+ | 1 (* GetEnumerator*) -> current
632
+ | 2 (* MoveNext*) -> current
633
+ | _ (* Finished*) -> alreadyFinished()
634
+
635
+ interface IEnumerator with
636
+ member this.Current : obj =
637
+ box ( this:> IEnumerator< 'State>) .Current
638
+
639
+ member this.MoveNext () : bool =
640
+ match state with
641
+ | 0 (* PreStart*) ->
642
+ state <- 1 (* GetEnumerator*)
643
+ true
644
+ | 1 (* GetEnumerator*) ->
645
+ enumerator <- enumerable.GetEnumerator ()
646
+ state <- 2 (* MoveNext*)
647
+ ( this:> IEnumerator) .MoveNext ()
648
+ | 2 (* MoveNext*) ->
649
+ if enumerator.MoveNext () then
650
+ current <- f.Invoke ( current, enumerator.Current)
651
+ true
652
+ else
653
+ current <- Unchecked.defaultof<_>
654
+ state <- 3 (* Finished*)
655
+ false
656
+ | _ (* Finished*) -> alreadyFinished()
657
+
658
+ member this.Reset () : unit = noReset ()
659
+
660
+ interface IDisposable with
661
+ member this.Dispose (): unit =
662
+ if isNotNull enumerator then
663
+ enumerator.Dispose ()
664
+
595
665
[<CompiledName " Scan" >]
596
- let inline scan ( folder : 'State -> 'T -> 'State ) ( initialState : 'State ) ( source : ISeq < 'T >) : ISeq < 'State > =
597
- let head = singleton initialState
598
- let tail =
599
- source.PushTransform { new ITransformFactory< 'T, 'State> with
600
- override __.Compose _ _ next =
601
- upcast { new Transform< 'T, 'V, 'State>( next, initialState) with
602
- override this.ProcessNext ( input : 'T ) : bool =
603
- this.State <- folder this.State input
604
- TailCall.avoid ( next.ProcessNext this.State) } }
605
- concat ( ofList [ head ; tail ])
666
+ let scan ( folder : 'State -> 'T -> 'State ) ( initialState : 'State ) ( source : ISeq < 'T >) : ISeq < 'State > =
667
+ upcast { new PreferGetEnumerator< 'State>() with
668
+ member this.GetEnumerator () =
669
+ upcast new ScanEnumerator< 'T, 'State>( folder, initialState, source)
670
+
671
+ member this.GetSeq () =
672
+ let head = singleton initialState
673
+ let tail =
674
+ source.PushTransform { new ITransformFactory< 'T, 'State> with
675
+ override __.Compose _ _ next =
676
+ let f = OptimizedClosures.FSharpFunc<_,_,_>. Adapt folder
677
+ upcast { new Transform< 'T, 'V, 'State>( next, initialState) with
678
+ override this.ProcessNext ( input : 'T ) : bool =
679
+ this.State <- f.Invoke ( this.State, input)
680
+ TailCall.avoid ( next.ProcessNext this.State) } }
681
+ concat ( ofList [ head ; tail ]) }
606
682
607
683
[<CompiledName " Skip" >]
608
684
let skip ( skipCount : int ) ( source : ISeq < 'T >) : ISeq < 'T > =
0 commit comments