@@ -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" ) >]
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)
52+
53+ static member inline NewList ( count , values ) =
54+ ResizeList( count, values)
4755
48- static member inline Empty =
49- { Count = 0 ; Values = ResizeArray < 'T>() }
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 ) =
@@ -121,7 +129,7 @@ and 'T list = ResizeList<'T>
121129
122130let inline indexNotFound () = raise ( System.Collections.Generic.KeyNotFoundException( SR.keyNotFoundAlt))
123131
124- let newList values = ResizeList.NewList ( values)
132+ let newList values = ResizeList< 'T > . NewList ( values)
125133
126134let empty () = ResizeList.Empty
127135
@@ -174,22 +182,24 @@ let foldBack (folder: 'T -> 'acc -> 'acc) (xs: 'T list) (state: 'acc) =
174182let reverse ( xs : 'a list ) =
175183 xs.Reverse()
176184
177- let inline reverseInPlace ( xs : 'a list ) =
178- xs.ReverseInPlace()
185+ let ofResizeArrayInPlace ( xs : ResizeArray < 'a >) =
186+ xs.Reverse()
187+ ResizeList.NewList xs
179188
180189let toSeq ( xs : 'a list ): 'a seq =
181190 xs :> System.Collections.Generic.IEnumerable< 'a>
182191
183192let ofSeq ( xs : 'a seq ): 'a list =
184193 // Seq.fold (fun acc x -> cons x acc) ResizeList.Empty xs
185- // |> reverseInPlace
194+ // |> ofResizeArrayInPlace
186195 let values = ResizeArray( xs)
187196 values.Reverse()
188197 values |> newList
189198
190199let concat ( lists : seq < 'a list >) =
191- Seq.fold ( fold ( fun acc x -> cons x acc)) ResizeList.Empty lists
192- |> reverseInPlace
200+ ( ResizeArray(), lists)
201+ ||> Seq.fold ( fold ( fun acc x -> acc.Add( x); acc))
202+ |> ofResizeArrayInPlace
193203
194204let fold2 f ( state : 'acc ) ( xs : 'a list ) ( ys : 'b list ) =
195205 Seq.fold2 f state xs ys
@@ -200,9 +210,9 @@ let foldBack2 f (xs: 'a list) (ys: 'b list) (state: 'acc) =
200210let unfold ( gen : 'acc -> ( 'T * 'acc ) option ) ( state : 'acc ) =
201211 let rec loop st acc =
202212 match gen st with
203- | None -> reverseInPlace acc
204- | Some ( x, st) -> loop st ( cons x acc)
205- loop state ResizeList.Empty
213+ | None -> ofResizeArrayInPlace acc
214+ | Some ( x, st) -> acc.Add ( x ); loop st acc
215+ loop state ( ResizeArray ())
206216
207217let scan f ( state : 'acc ) ( xs : 'a list ) =
208218 Seq.scan f state xs |> ofSeq
@@ -211,21 +221,24 @@ let scanBack f (xs: 'a list) (state: 'acc) =
211221 Seq.scanBack f xs state |> ofSeq
212222
213223let append ( xs : 'a list ) ( ys : 'a list ) =
214- // foldBack cons xs ys
215- let mutable acc = ys
216- for i = xs.Length - 1 downto 0 do
217- acc <- cons xs.[ i] acc
218- acc
224+ let ylen = ys.Count
225+ let values = allocate ( xs.Count + ys.Count)
226+ for i = xs.Count - 1 downto 0 do
227+ values.[ i + ylen] <- xs.Values.[ i]
228+ for i = ys.Count - 1 downto 0 do
229+ values.[ i] <- ys.Values.[ i]
230+ ResizeList< 'a>. NewList( values)
219231
220232let collect ( f : 'a -> 'b list ) ( xs : 'a list ) =
221233 Seq.collect f xs |> ofSeq
222234
223235let mapIndexed ( f : int -> 'a -> 'b ) ( xs : 'a list ) =
224- let rec loop i acc =
225- if i < xs.Length
226- then loop ( i + 1 ) ( cons ( f i xs.[ i]) acc)
227- else reverseInPlace acc
228- loop 0 ResizeList.Empty
236+ let values = allocate xs.Count
237+ let mutable j = 0
238+ for i = xs.Count - 1 downto 0 do
239+ values.[ i] <- f j xs.Values.[ i]
240+ j <- j + 1
241+ ResizeList< 'b>. NewList( values)
229242
230243let map ( f : 'a -> 'b ) ( xs : 'a list ) =
231244 mapIndexed ( fun _i x -> f x) xs
@@ -243,11 +256,12 @@ let map3 f xs ys zs =
243256 Seq.map3 f xs ys zs |> ofSeq
244257
245258let mapFold ( f : 'S -> 'T -> 'R * 'S ) s xs =
246- let folder ( nxs , fs ) x =
259+ let folder ( nxs : ResizeArray < _ > , fs ) x =
247260 let nx , fs = f fs x
248- cons nx nxs, fs
249- let nxs , s = fold folder ( ResizeList.Empty, s) xs
250- reverseInPlace nxs, s
261+ nxs.Add( nx)
262+ nxs, fs
263+ let nxs , s = fold folder ( ResizeArray(), s) xs
264+ ofResizeArrayInPlace nxs, s
251265
252266let mapFoldBack ( f : 'T -> 'S -> 'R * 'S ) xs s =
253267 mapFold ( fun s v -> f v s) s ( reverse xs)
@@ -265,10 +279,10 @@ let iterateIndexed2 f xs ys =
265279 fold2 ( fun i x y -> f i x y; i + 1 ) 0 xs ys |> ignore
266280
267281let ofArrayWithTail ( xs : 'T []) ( tail : 'T list ) =
268- let mutable res = tail
282+ let values = tail.Values
269283 for i = xs.Length - 1 downto 0 do
270- res <- cons xs.[ i] res
271- res
284+ values.Add ( xs.[ i])
285+ newList values
272286
273287// let ofArray (xs: 'T[]) =
274288// ofArrayWithTail xs ResizeList.Empty
@@ -369,53 +383,26 @@ let tryItem index (xs: 'a list) =
369383 else None
370384
371385let filter f xs =
372- fold ( fun acc x ->
386+ ( ResizeArray(), xs)
387+ ||> fold ( fun acc x ->
373388 if f x
374- then cons x acc
375- else acc) ResizeList.Empty xs
376- |> reverseInPlace
389+ then acc.Add ( x ); acc
390+ else acc)
391+ |> ofResizeArrayInPlace
377392
393+ // TODO: Optimize this
378394let partition f xs =
379395 fold ( fun ( lacc , racc ) x ->
380396 if f x then cons x lacc, racc
381397 else lacc, cons x racc) ( ResizeList.Empty, ResizeList.Empty) ( reverse xs)
382398
383- let tryItem n ( xs : 'T list ) =
384- let rec loop i ( xs : 'T list ) =
385- if xs.IsEmpty then None
386- else
387- if i = n then Some xs.Head
388- else loop ( i + 1 ) xs.Tail
389- loop 0 xs
390-
391- let item n ( xs : 'T list ) = xs.Item( n)
392-
393- let filter f ( xs : 'T list ) =
394- let root = List.Empty
395- let folder ( acc : 'T list ) x =
396- if f x then acc.AppendConsNoTail x else acc
397- let node = fold folder root xs
398- node.SetConsTail List.Empty
399- root.Tail
400-
401- let partition f ( xs : 'T list ) =
402- let root1 , root2 = List.Empty, List.Empty
403- let folder ( lacc : 'T list , racc : 'T list ) x =
404- if f x
405- then lacc.AppendConsNoTail x, racc
406- else lacc, racc.AppendConsNoTail x
407- let node1 , node2 = fold folder ( root1, root2) xs
408- node1.SetConsTail List.Empty
409- node2.SetConsTail List.Empty
410- root1.Tail, root2.Tail
411-
412- let choose f ( xs : 'T list ) =
413- let root = List.Empty
414- let folder ( acc : 'T list ) x =
399+ let choose f xs =
400+ ( ResizeArray(), xs)
401+ ||> fold ( fun acc x ->
415402 match f x with
416- | Some y -> cons y acc
417- | None -> acc) ResizeList.Empty xs
418- |> reverseInPlace
403+ | Some y -> acc.Add ( y ); acc
404+ | None -> acc)
405+ |> ofResizeArrayInPlace
419406
420407let contains ( value : 'T ) ( xs : 'T list ) ( [<Inject>] eq : System.Collections.Generic.IEqualityComparer < 'T >) =
421408 tryFindIndex ( fun v -> eq.Equals ( value, v)) xs |> Option.isSome
@@ -427,10 +414,12 @@ let except (itemsToExclude: seq<'t>) (xs: 't list) ([<Inject>] eq: System.Collec
427414 xs |> filter cached.Add
428415
429416let initialize n f =
430- let mutable res = ResizeList.Empty
431- for i = 0 to n - 1 do
432- res <- cons ( f i) res
433- res |> reverseInPlace
417+ let mutable j = 0
418+ let values = allocate n
419+ for i = n - 1 downto 0 do
420+ values.[ i] <- f j
421+ j <- j + 1
422+ values |> newList
434423
435424let replicate n x =
436425 initialize n ( fun _ -> x)
@@ -458,6 +447,7 @@ let rec exists2 f xs ys =
458447 | x, y when x = y -> f ( head xs) ( head ys) || exists2 f ( tail xs) ( tail ys)
459448 | _ -> invalidArg " list2" SR.listsHadDifferentLengths
460449
450+ // TODO: Optimize this
461451let unzip xs =
462452 foldBack ( fun ( x , y ) ( lacc , racc ) -> cons x lacc, cons y racc) xs ( ResizeList.Empty, ResizeList.Empty)
463453
@@ -473,7 +463,7 @@ let zip3 xs ys zs =
473463let sortWith ( comparison : 'T -> 'T -> int ) ( xs : 'T list ): 'T list =
474464 let values = ResizeArray( xs)
475465 values.Sort( System.Comparison<_>( comparison)) // should be a stable sort in JS
476- values |> newList |> reverseInPlace
466+ values |> ofResizeArrayInPlace
477467
478468let sort ( xs : 'T list ) ( [<Inject>] comparer : System.Collections.Generic.IComparer < 'T >): 'T list =
479469 sortWith ( fun x y -> comparer.Compare( x, y)) xs
@@ -545,8 +535,11 @@ let getSlice (startIndex: int option) (endIndex: int option) (xs: 'T list) =
545535 let startIndex = if startIndex < 0 then 0 else startIndex
546536 let endIndex = if endIndex >= xs.Length then xs.Length - 1 else endIndex
547537 // take (endIndex - startIndex + 1) (skip startIndex xs)
548- let values = ResizeArray( endIndex - startIndex + 1 )
549- for i = endIndex downto startIndex do values.Add( xs.[ i])
538+ let values = allocate ( endIndex - startIndex + 1 )
539+ let mutable j = 0
540+ for i = endIndex downto startIndex do
541+ values.[ j] <- xs.[ i]
542+ j <- j + 1
550543 values |> newList
551544
552545let splitAt index ( xs : 'T list ) =
@@ -567,6 +560,7 @@ let exactlyOne (xs: 'T list) =
567560 | 0 -> invalidArg " list" SR.inputSequenceEmpty
568561 | _ -> invalidArg " list" SR.inputSequenceTooLong
569562
563+ // TODO: Optimize this
570564let groupBy ( projection : 'T -> 'Key ) ( xs : 'T list )( [<Inject>] eq : System.Collections.Generic.IEqualityComparer < 'Key >): ( 'Key * 'T list ) list =
571565 let dict = System.Collections.Generic.Dictionary< 'Key, 'T list>( eq)
572566 let mutable keys = ResizeList.Empty
@@ -579,7 +573,7 @@ let groupBy (projection: 'T -> 'Key) (xs: 'T list)([<Inject>] eq: System.Collect
579573 dict.Add( key, cons v ResizeList.Empty)
580574 keys <- cons key keys )
581575 let mutable result = ResizeList.Empty
582- keys |> iterate ( fun key -> result <- cons ( key, reverseInPlace dict.[ key]) result)
576+ keys |> iterate ( fun key -> result <- cons ( key, dict.[ key]. ReverseInPlace () ) result)
583577 result
584578
585579let countBy ( projection : 'T -> 'Key ) ( xs : 'T list )( [<Inject>] eq : System.Collections.Generic.IEqualityComparer < 'Key >) =
0 commit comments