@@ -12,24 +12,31 @@ module SR =
1212 let listsHadDifferentLengths = " The lists had different lengths."
1313 let notEnoughElements = " The input sequence has an insufficient number of elements."
1414
15+ [<Emit( " new Array($0)" ) >]
16+ let private allocate ( i : int ): ResizeArray < 'T > = jsNative
17+
1518// [<Struct>]
16- [<CustomEquality; CustomComparison>]
19+ // [<CustomEquality; CustomComparison>]
1720// [<CompiledName("FSharpList`1")>]
18- type ResizeList < 'T > =
19- { Count: int ; Values: ResizeArray < 'T > }
21+ type ResizeList < 'T >( count , values ) =
22+ member _.Count : int = count
23+ member _.Values : ResizeArray < 'T > = values
2024
21- member inline internal xs.Add ( x : 'T ) =
25+ member internal xs.Add ( x : 'T ) =
2226 let values =
2327 if xs.Count = xs.Values.Count
2428 then xs.Values
2529 else xs.Values.GetRange( 0 , xs.Count)
2630 values.Add( x)
27- { Count = values.Count ; Values = values }
31+ ResizeList < 'T >. NewList ( values)
2832
29- member inline internal xs.Reverse () =
30- let values = xs.Values.GetRange( 0 , xs.Count)
31- values.Reverse()
32- { Count = values.Count; Values = values }
33+ member internal xs.Reverse () =
34+ let values = allocate xs.Count
35+ let mutable j = 0
36+ for i = xs.Count - 1 downto 0 do
37+ values.[ j] <- xs.Values.[ i]
38+ j <- j + 1
39+ ResizeList< 'T>. NewList( values)
3340
3441 // This is a destructive internal optimization that
3542 // can only be performed on newly constructed lists.
@@ -38,30 +45,31 @@ type ResizeList<'T> =
3845 xs
3946
4047 static member inline Singleton ( x : 'T ) =
41- let values = ResizeArray< 'T>()
42- values.Add( x)
43- { Count = 1 ; Values = values }
48+ ResizeList< 'T>. NewList( ResizeArray [| x|])
4449
4550 static member inline NewList ( values : ResizeArray < 'T >) =
46- { Count = values.Count; Values = values }
51+ ResizeList ( values.Count, values)
4752
48- static member inline Empty =
49- { Count = 0 ; Values = ResizeArray< 'T>() }
53+ static member inline NewList ( count , values ) =
54+ ResizeList( count, values)
55+
56+ static member inline Empty : ResizeList < 'T > =
57+ ResizeList< 'T>. NewList( ResizeArray())
5058
5159 static member inline Cons ( x : 'T , xs : 'T list ) = xs.Add( x)
5260
5361 member inline xs.IsEmpty = xs.Count <= 0
5462
5563 member inline xs.Length = xs.Count
5664
57- member inline xs.Head =
65+ member xs.Head =
5866 if xs.Count > 0
5967 then xs.Values.[ xs.Count - 1 ]
6068 else invalidArg " list" SR.inputListWasEmpty
6169
62- member inline xs.Tail =
70+ member xs.Tail =
6371 if xs.Count > 0
64- then { Count = xs.Count - 1 ; Values = xs.Values }
72+ then ResizeList < 'T >. NewList ( xs.Count - 1 , xs.Values)
6573 else invalidArg " list" SR.inputListWasEmpty
6674
6775 member inline xs.Item with get ( index : int ) =
@@ -117,7 +125,7 @@ and 'T list = ResizeList<'T>
117125
118126let inline indexNotFound () = raise ( System.Collections.Generic.KeyNotFoundException( SR.keyNotFoundAlt))
119127
120- let newList values = ResizeList.NewList ( values)
128+ let newList values = ResizeList< 'T > . NewList ( values)
121129
122130let empty () = ResizeList.Empty
123131
@@ -170,22 +178,24 @@ let foldBack (folder: 'T -> 'acc -> 'acc) (xs: 'T list) (state: 'acc) =
170178let reverse ( xs : 'a list ) =
171179 xs.Reverse()
172180
173- let inline reverseInPlace ( xs : 'a list ) =
174- xs.ReverseInPlace()
181+ let ofResizeArrayInPlace ( xs : ResizeArray < 'a >) =
182+ xs.Reverse()
183+ ResizeList.NewList xs
175184
176185let toSeq ( xs : 'a list ): 'a seq =
177186 xs :> System.Collections.Generic.IEnumerable< 'a>
178187
179188let ofSeq ( xs : 'a seq ): 'a list =
180189 // Seq.fold (fun acc x -> cons x acc) ResizeList.Empty xs
181- // |> reverseInPlace
190+ // |> ofResizeArrayInPlace
182191 let values = ResizeArray( xs)
183192 values.Reverse()
184193 values |> newList
185194
186195let concat ( lists : seq < 'a list >) =
187- Seq.fold ( fold ( fun acc x -> cons x acc)) ResizeList.Empty lists
188- |> reverseInPlace
196+ ( ResizeArray(), lists)
197+ ||> Seq.fold ( fold ( fun acc x -> acc.Add( x); acc))
198+ |> ofResizeArrayInPlace
189199
190200let fold2 f ( state : 'acc ) ( xs : 'a list ) ( ys : 'b list ) =
191201 Seq.fold2 f state xs ys
@@ -196,9 +206,9 @@ let foldBack2 f (xs: 'a list) (ys: 'b list) (state: 'acc) =
196206let unfold ( gen : 'acc -> ( 'T * 'acc ) option ) ( state : 'acc ) =
197207 let rec loop st acc =
198208 match gen st with
199- | None -> reverseInPlace acc
200- | Some ( x, st) -> loop st ( cons x acc)
201- loop state ResizeList.Empty
209+ | None -> ofResizeArrayInPlace acc
210+ | Some ( x, st) -> acc.Add ( x ); loop st acc
211+ loop state ( ResizeArray ())
202212
203213let scan f ( state : 'acc ) ( xs : 'a list ) =
204214 Seq.scan f state xs |> ofSeq
@@ -207,21 +217,24 @@ let scanBack f (xs: 'a list) (state: 'acc) =
207217 Seq.scanBack f xs state |> ofSeq
208218
209219let append ( xs : 'a list ) ( ys : 'a list ) =
210- // foldBack cons xs ys
211- let mutable acc = ys
212- for i = xs.Length - 1 downto 0 do
213- acc <- cons xs.[ i] acc
214- acc
220+ let ylen = ys.Count
221+ let values = allocate ( xs.Count + ys.Count)
222+ for i = xs.Count - 1 downto 0 do
223+ values.[ i + ylen] <- xs.Values.[ i]
224+ for i = ys.Count - 1 downto 0 do
225+ values.[ i] <- ys.Values.[ i]
226+ ResizeList< 'a>. NewList( values)
215227
216228let collect ( f : 'a -> 'b list ) ( xs : 'a list ) =
217229 Seq.collect f xs |> ofSeq
218230
219231let mapIndexed ( f : int -> 'a -> 'b ) ( xs : 'a list ) =
220- let rec loop i acc =
221- if i < xs.Length
222- then loop ( i + 1 ) ( cons ( f i xs.[ i]) acc)
223- else reverseInPlace acc
224- loop 0 ResizeList.Empty
232+ let values = allocate xs.Count
233+ let mutable j = 0
234+ for i = xs.Count - 1 downto 0 do
235+ values.[ i] <- f j xs.Values.[ i]
236+ j <- j + 1
237+ ResizeList< 'b>. NewList( values)
225238
226239let map ( f : 'a -> 'b ) ( xs : 'a list ) =
227240 mapIndexed ( fun _i x -> f x) xs
@@ -239,11 +252,12 @@ let map3 f xs ys zs =
239252 Seq.map3 f xs ys zs |> ofSeq
240253
241254let mapFold ( f : 'S -> 'T -> 'R * 'S ) s xs =
242- let folder ( nxs , fs ) x =
255+ let folder ( nxs : ResizeArray < _ > , fs ) x =
243256 let nx , fs = f fs x
244- cons nx nxs, fs
245- let nxs , s = fold folder ( ResizeList.Empty, s) xs
246- reverseInPlace nxs, s
257+ nxs.Add( nx)
258+ nxs, fs
259+ let nxs , s = fold folder ( ResizeArray(), s) xs
260+ ofResizeArrayInPlace nxs, s
247261
248262let mapFoldBack ( f : 'T -> 'S -> 'R * 'S ) xs s =
249263 mapFold ( fun s v -> f v s) s ( reverse xs)
@@ -261,10 +275,10 @@ let iterateIndexed2 f xs ys =
261275 fold2 ( fun i x y -> f i x y; i + 1 ) 0 xs ys |> ignore
262276
263277let ofArrayWithTail ( xs : 'T []) ( tail : 'T list ) =
264- let mutable res = tail
278+ let values = tail.Values
265279 for i = xs.Length - 1 downto 0 do
266- res <- cons xs.[ i] res
267- res
280+ values.Add ( xs.[ i])
281+ newList values
268282
269283// let ofArray (xs: 'T[]) =
270284// ofArrayWithTail xs ResizeList.Empty
@@ -359,23 +373,26 @@ let tryItem index (xs: 'a list) =
359373 else None
360374
361375let filter f xs =
362- fold ( fun acc x ->
376+ ( ResizeArray(), xs)
377+ ||> fold ( fun acc x ->
363378 if f x
364- then cons x acc
365- else acc) ResizeList.Empty xs
366- |> reverseInPlace
379+ then acc.Add ( x ); acc
380+ else acc)
381+ |> ofResizeArrayInPlace
367382
383+ // TODO: Optimize this
368384let partition f xs =
369385 fold ( fun ( lacc , racc ) x ->
370386 if f x then cons x lacc, racc
371387 else lacc, cons x racc) ( ResizeList.Empty, ResizeList.Empty) ( reverse xs)
372388
373389let choose f xs =
374- fold ( fun acc x ->
390+ ( ResizeArray(), xs)
391+ ||> fold ( fun acc x ->
375392 match f x with
376- | Some y -> cons y acc
377- | None -> acc) ResizeList.Empty xs
378- |> reverseInPlace
393+ | Some y -> acc.Add ( y ); acc
394+ | None -> acc)
395+ |> ofResizeArrayInPlace
379396
380397let contains ( value : 'T ) ( xs : 'T list ) ( [<Inject>] eq : System.Collections.Generic.IEqualityComparer < 'T >) =
381398 tryFindIndex ( fun v -> eq.Equals ( value, v)) xs |> Option.isSome
@@ -387,10 +404,12 @@ let except (itemsToExclude: seq<'t>) (xs: 't list) ([<Inject>] eq: System.Collec
387404 xs |> filter cached.Add
388405
389406let initialize n f =
390- let mutable res = ResizeList.Empty
391- for i = 0 to n - 1 do
392- res <- cons ( f i) res
393- res |> reverseInPlace
407+ let mutable j = 0
408+ let values = allocate n
409+ for i = n - 1 downto 0 do
410+ values.[ i] <- f j
411+ j <- j + 1
412+ values |> newList
394413
395414let replicate n x =
396415 initialize n ( fun _ -> x)
@@ -418,6 +437,7 @@ let rec exists2 f xs ys =
418437 | x, y when x = y -> f ( head xs) ( head ys) || exists2 f ( tail xs) ( tail ys)
419438 | _ -> invalidArg " list2" SR.listsHadDifferentLengths
420439
440+ // TODO: Optimize this
421441let unzip xs =
422442 foldBack ( fun ( x , y ) ( lacc , racc ) -> cons x lacc, cons y racc) xs ( ResizeList.Empty, ResizeList.Empty)
423443
@@ -433,7 +453,7 @@ let zip3 xs ys zs =
433453let sortWith ( comparison : 'T -> 'T -> int ) ( xs : 'T list ): 'T list =
434454 let values = ResizeArray( xs)
435455 values.Sort( System.Comparison<_>( comparison)) // should be a stable sort in JS
436- values |> newList |> reverseInPlace
456+ values |> ofResizeArrayInPlace
437457
438458let sort ( xs : 'T list ) ( [<Inject>] comparer : System.Collections.Generic.IComparer < 'T >): 'T list =
439459 sortWith ( fun x y -> comparer.Compare( x, y)) xs
@@ -505,8 +525,11 @@ let getSlice (startIndex: int option) (endIndex: int option) (xs: 'T list) =
505525 let startIndex = if startIndex < 0 then 0 else startIndex
506526 let endIndex = if endIndex >= xs.Length then xs.Length - 1 else endIndex
507527 // take (endIndex - startIndex + 1) (skip startIndex xs)
508- let values = ResizeArray( endIndex - startIndex + 1 )
509- for i = endIndex downto startIndex do values.Add( xs.[ i])
528+ let values = allocate ( endIndex - startIndex + 1 )
529+ let mutable j = 0
530+ for i = endIndex downto startIndex do
531+ values.[ j] <- xs.[ i]
532+ j <- j + 1
510533 values |> newList
511534
512535let splitAt index ( xs : 'T list ) =
@@ -527,6 +550,7 @@ let exactlyOne (xs: 'T list) =
527550 | 0 -> invalidArg " list" SR.inputSequenceEmpty
528551 | _ -> invalidArg " list" SR.inputSequenceTooLong
529552
553+ // TODO: Optimize this
530554let groupBy ( projection : 'T -> 'Key ) ( xs : 'T list )( [<Inject>] eq : System.Collections.Generic.IEqualityComparer < 'Key >): ( 'Key * 'T list ) list =
531555 let dict = System.Collections.Generic.Dictionary< 'Key, 'T list>( eq)
532556 let mutable keys = ResizeList.Empty
@@ -539,7 +563,7 @@ let groupBy (projection: 'T -> 'Key) (xs: 'T list)([<Inject>] eq: System.Collect
539563 dict.Add( key, cons v ResizeList.Empty)
540564 keys <- cons key keys )
541565 let mutable result = ResizeList.Empty
542- keys |> iterate ( fun key -> result <- cons ( key, reverseInPlace dict.[ key]) result)
566+ keys |> iterate ( fun key -> result <- cons ( key, dict.[ key]. ReverseInPlace () ) result)
543567 result
544568
545569let countBy ( projection : 'T -> 'Key ) ( xs : 'T list )( [<Inject>] eq : System.Collections.Generic.IEqualityComparer < 'Key >) =
0 commit comments