diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs index 6047215fbb004dab39f0ce8df12221e570ab98cb..c7683abb5dfe68134efa2ca89854b0904f3ec9e7 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs @@ -199,6 +199,19 @@ type ArrayModule() = CheckThrowsInvalidOperationExn (fun () -> Array.take 5 [|"str1";"str2";"str3";"str4"|] |> ignore) CheckThrowsArgumentNullException (fun () -> Array.take 5 null |> ignore) + [] + member this.takeWhile() = + Assert.AreEqual([||],Array.takeWhile (fun x -> failwith "should not be used") [||]) + Assert.AreEqual([|1;2;4;5|],Array.takeWhile (fun x -> x < 6) [|1;2;4;5;6;7|]) + Assert.AreEqual([|"a"; "ab"; "abc"|],Array.takeWhile (fun (x:string) -> x.Length < 4) [|"a"; "ab"; "abc"; "abcd"; "abcde"|]) + Assert.AreEqual([|"a"; "ab"; "abc"; "abcd"; "abcde"|],Array.takeWhile (fun _ -> true) [|"a"; "ab"; "abc"; "abcd"; "abcde"|]) + Assert.AreEqual([||],Array.takeWhile (fun _ -> false) [|"a"; "ab"; "abc"; "abcd"; "abcde"|]) + Assert.AreEqual([||],Array.takeWhile (fun _ -> false) [|"a"|]) + Assert.AreEqual([|"a"|],Array.takeWhile (fun _ -> true) [|"a"|]) + Assert.AreEqual([|"a"|],Array.takeWhile (fun x -> x <> "ab") [|"a"; "ab"; "abc"; "abcd"; "abcde"|]) + + CheckThrowsArgumentNullException (fun () -> Array.takeWhile (fun _ -> failwith "should not be used") null |> ignore) + [] member this.Blit() = // int array diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs index 45aacd0899330120bbcfb9672f365e8e706a8752..7c3cc03c08d33e0a22aee7c068a095024667475c 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs @@ -180,7 +180,6 @@ type ListModule() = let emptyChosen = List.choose funcInt emptySrc Assert.AreEqual(emptySrc, emptyChosen) - () [] @@ -203,6 +202,17 @@ type ListModule() = Assert.AreEqual(0,List.compareWith (fun x y -> 0) ["1";"2"] ["1";"3"]) Assert.AreEqual(1,List.compareWith (fun x y -> 1) ["1";"2"] ["1";"3"]) Assert.AreEqual(-1,List.compareWith (fun x y -> -1) ["1";"2"] ["1";"3"]) + + [] + member this.takeWhile() = + Assert.AreEqual([],List.takeWhile (fun x -> failwith "should not be used") []) + Assert.AreEqual([1;2;4;5],List.takeWhile (fun x -> x < 6) [1;2;4;5;6;7]) + Assert.AreEqual(["a"; "ab"; "abc"],List.takeWhile (fun (x:string) -> x.Length < 4) ["a"; "ab"; "abc"; "abcd"; "abcde"]) + Assert.AreEqual(["a"; "ab"; "abc"; "abcd"; "abcde"],List.takeWhile (fun _ -> true) ["a"; "ab"; "abc"; "abcd"; "abcde"]) + Assert.AreEqual([],List.takeWhile (fun _ -> false) ["a"; "ab"; "abc"; "abcd"; "abcde"]) + Assert.AreEqual([],List.takeWhile (fun _ -> false) ["a"]) + Assert.AreEqual(["a"],List.takeWhile (fun _ -> true) ["a"]) + Assert.AreEqual(["a"],List.takeWhile (fun x -> x <> "ab") ["a"; "ab"; "abc"; "abcd"; "abcde"]) [] member this.Concat() = diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.4.0.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.4.0.fs index 28bc044ff619f9032b152e7158404f90ec427734..eeed925887f075568ef84d8c7b710a5f1a532b5c 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.4.0.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.4.0.fs @@ -163,6 +163,7 @@ Microsoft.FSharp.Collections.ArrayModule: T[] Singleton[T](T) Microsoft.FSharp.Collections.ArrayModule: T[] SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[]) Microsoft.FSharp.Collections.ArrayModule: T[] SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], T[]) Microsoft.FSharp.Collections.ArrayModule: T[] Sort[T](T[]) +Microsoft.FSharp.Collections.ArrayModule: T[] TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) Microsoft.FSharp.Collections.ArrayModule: T[] Take[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: T[] Where[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) Microsoft.FSharp.Collections.ArrayModule: T[] ZeroCreate[T](Int32) @@ -306,6 +307,7 @@ Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Sort[T](Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Tail[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Take[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Where[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T]) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.Portable.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.Portable.fs index 47b5fb73f96e53de602f411e80756f4384e0fa33..9565ca6a779e75c25791907e8a75f564fbb98171 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.Portable.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.Portable.fs @@ -157,6 +157,7 @@ Microsoft.FSharp.Collections.ArrayModule: T[] Singleton[T](T) Microsoft.FSharp.Collections.ArrayModule: T[] SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[]) Microsoft.FSharp.Collections.ArrayModule: T[] SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], T[]) Microsoft.FSharp.Collections.ArrayModule: T[] Sort[T](T[]) +Microsoft.FSharp.Collections.ArrayModule: T[] TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) Microsoft.FSharp.Collections.ArrayModule: T[] Take[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: T[] Where[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) Microsoft.FSharp.Collections.ArrayModule: T[] ZeroCreate[T](Int32) @@ -300,6 +301,7 @@ Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Sort[T](Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Tail[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Take[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Where[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T]) diff --git a/src/fsharp/FSharp.Core/array.fs b/src/fsharp/FSharp.Core/array.fs index c967977d20235666125a10a96576a8521e042a09..cfadbc2c99ff98f02dcc2692ddb9bef71f7c8232 100644 --- a/src/fsharp/FSharp.Core/array.fs +++ b/src/fsharp/FSharp.Core/array.fs @@ -120,6 +120,19 @@ namespace Microsoft.FSharp.Collections Array.Copy(array, 0, res, 0, count) res + [] + let takeWhile predicate (array: 'T[]) = + checkNonNull "array" array + if array.Length = 0 then empty else + let mutable count = 0 + while count < array.Length && predicate array.[count] do + count <- count + 1 + + let res : 'T[] = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked count + + Array.Copy(array, 0, res, 0, count) + res + [] let append (array1:'T[]) (array2:'T[]) = checkNonNull "array1" array1 diff --git a/src/fsharp/FSharp.Core/array.fsi b/src/fsharp/FSharp.Core/array.fsi index c11d2bcc3d215d4736db95187d88e5a7925ab25e..2bb426ce47c1dd7cbee7ecfc3f02df8fae66f2a0 100644 --- a/src/fsharp/FSharp.Core/array.fsi +++ b/src/fsharp/FSharp.Core/array.fsi @@ -657,6 +657,18 @@ namespace Microsoft.FSharp.Collections [] val take: count:int -> array:'T[] -> 'T[] + /// Returns an array that contains all elements of the original array while the + /// given predicate returns true, and then returns no further elements. + /// + /// A function that evaluates to false when no more items should be returned. + /// The input array. + /// + /// The result array. + /// + /// Thrown when the input array is null. + [] + val takeWhile: predicate:('T -> bool) -> array:'T[] -> 'T[] + /// Builds a list from the given array. /// The input array. /// The list of array elements. diff --git a/src/fsharp/FSharp.Core/list.fs b/src/fsharp/FSharp.Core/list.fs index f7b11c935173c2ceb58471c2eb77148b1edb7b78..488943445db206f5cbc326abdbaa589ee35a5e4b 100644 --- a/src/fsharp/FSharp.Core/list.fs +++ b/src/fsharp/FSharp.Core/list.fs @@ -90,6 +90,9 @@ namespace Microsoft.FSharp.Collections [] let take count (list : 'T list) = Microsoft.FSharp.Primitives.Basics.List.take count list + [] + let takeWhile p (list: 'T list) = Microsoft.FSharp.Primitives.Basics.List.takeWhile p list + [] let iteri f list = Microsoft.FSharp.Primitives.Basics.List.iteri f list diff --git a/src/fsharp/FSharp.Core/list.fsi b/src/fsharp/FSharp.Core/list.fsi index cd62769b49025610487d63dd0d5a60f1b6f455a3..f9e8eecc70ba8279ef4d815998bd20432cabe04d 100644 --- a/src/fsharp/FSharp.Core/list.fsi +++ b/src/fsharp/FSharp.Core/list.fsi @@ -587,6 +587,16 @@ namespace Microsoft.FSharp.Collections [] val take: count:int -> list:'T list -> 'T list + /// Returns a list that contains all elements of the original list while the + /// given predicate returns true, and then returns no further elements. + /// + /// A function that evaluates to false when no more items should be returned. + /// The input list. + /// + /// The result list. + [] + val takeWhile: predicate:('T -> bool) -> list:'T list -> 'T list + /// Builds an array from the given list. /// The input list. /// The array containing the elements of the list. diff --git a/src/fsharp/FSharp.Core/local.fs b/src/fsharp/FSharp.Core/local.fs index 7cec850f12266a77a38431dafeab381505bbf9c0..1a9dbc46519295e8b1bfdde45fa5beeec30bef43 100644 --- a/src/fsharp/FSharp.Core/local.fs +++ b/src/fsharp/FSharp.Core/local.fs @@ -466,6 +466,27 @@ module internal List = res <- arr.[i] :: res res + let rec takeWhileFreshConsTail cons p l = + match l with + | [] -> setFreshConsTail cons [] + | x::xs -> + if p x then + let cons2 = freshConsNoTail x + setFreshConsTail cons cons2 + takeWhileFreshConsTail cons2 p xs + else + setFreshConsTail cons [] + + let takeWhile p (l: 'T list) = + match l with + | [] -> l + | x :: ([] as nil) -> if p x then l else nil + | x::xs -> + if not (p x) then [] else + let cons = freshConsNoTail x + takeWhileFreshConsTail cons p xs + cons + // NOTE: This implementation is now only used for List.sortWith. We should change that to use the stable sort via arrays // below, and remove this implementation. module StableSortImplementation = diff --git a/src/fsharp/FSharp.Core/local.fsi b/src/fsharp/FSharp.Core/local.fsi index 1a4261e9fbaa708d2331d6b1b3b9460b19f40849..c34ded83ba61f603ea1a9603269f3197832ee584 100644 --- a/src/fsharp/FSharp.Core/local.fsi +++ b/src/fsharp/FSharp.Core/local.fsi @@ -28,6 +28,7 @@ module internal List = val zip3 : 'T1 list -> 'T2 list -> 'T3 list -> ('T1 * 'T2 * 'T3) list val ofArray : 'T[] -> 'T list val take : int -> 'T list -> 'T list + val takeWhile : ('T -> bool) -> 'T list -> 'T list val toArray : 'T list -> 'T[] val sortWith : ('T -> 'T -> int) -> 'T list -> 'T list