From c3eeb29940c5b59e369942d9db11e01c240b4ba3 Mon Sep 17 00:00:00 2001 From: Michael Martin-Smucker Date: Thu, 2 Nov 2017 13:26:25 -0600 Subject: [PATCH 1/2] Avoid infinite loop possibility with takeEnd --- src/Data/List.purs | 2 +- test/Test/Data/List.purs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Data/List.purs b/src/Data/List.purs index d575c84..1b0b300 100644 --- a/src/Data/List.purs +++ b/src/Data/List.purs @@ -541,7 +541,7 @@ takeWhile p = go Nil -- | -- | Running time: `O(n)` where `n` is the number of elements to drop. drop :: forall a. Int -> List a -> List a -drop 0 xs = xs +drop n xs | n < 1 = xs drop _ Nil = Nil drop n (x : xs) = drop (n - 1) xs diff --git a/test/Test/Data/List.purs b/test/Test/Data/List.purs index f476dc3..e584dab 100644 --- a/test/Test/Data/List.purs +++ b/test/Test/Data/List.purs @@ -230,16 +230,18 @@ testList = do assert $ (takeEnd 1 (l [1, 2, 3])) == l [3] assert $ (takeEnd 2 (l [1, 2, 3])) == l [2, 3] assert $ (takeEnd 1 nil) == nil + assert $ (takeEnd 2 (l [1])) == l [1] log "takeWhile should keep all values that match a predicate from the front of an list" assert $ (takeWhile (_ /= 2) (l [1, 2, 3])) == l [1] assert $ (takeWhile (_ /= 3) (l [1, 2, 3])) == l [1, 2] assert $ (takeWhile (_ /= 1) nil) == nil - log "dropE should remove the specified number of items from the front of an list" + log "drop should remove the specified number of items from the front of an list" assert $ (drop 1 (l [1, 2, 3])) == l [2, 3] assert $ (drop 2 (l [1, 2, 3])) == l [3] assert $ (drop 1 nil) == nil + assert $ (drop (-1) (l [1, 2, 3])) == l [1, 2, 3] log "dropEnd should remove the specified number of items from the end of an list" assert $ (dropEnd 1 (l [1, 2, 3])) == l [1, 2] From c26dc1d2cf067659f263b63a37f693e5bf74c583 Mon Sep 17 00:00:00 2001 From: Michael Martin-Smucker Date: Thu, 2 Nov 2017 17:29:22 -0600 Subject: [PATCH 2/2] Protect `take` against infinite recursion --- src/Data/List.purs | 2 +- test/Test/Data/List.purs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Data/List.purs b/src/Data/List.purs index 1b0b300..afc2160 100644 --- a/src/Data/List.purs +++ b/src/Data/List.purs @@ -517,7 +517,7 @@ slice start end xs = take (end - start) (drop start xs) take :: forall a. Int -> List a -> List a take = go Nil where - go acc 0 _ = reverse acc + go acc n _ | n < 1 = reverse acc go acc _ Nil = reverse acc go acc n (x : xs) = go (x : acc) (n - 1) xs diff --git a/test/Test/Data/List.purs b/test/Test/Data/List.purs index e584dab..42d84c4 100644 --- a/test/Test/Data/List.purs +++ b/test/Test/Data/List.purs @@ -225,6 +225,8 @@ testList = do assert $ (take 1 (l [1, 2, 3])) == l [1] assert $ (take 2 (l [1, 2, 3])) == l [1, 2] assert $ (take 1 nil) == nil + assert $ (take 0 (l [1, 2])) == l [] + assert $ (take (-1) (l [1, 2])) == l [] log "takeEnd should keep the specified number of items from the end of an list, discarding the rest" assert $ (takeEnd 1 (l [1, 2, 3])) == l [3]