Skip to content

Commit

Permalink
Merge pull request #630 from sanctuary-js/davidchambers/take-drop-last
Browse files Browse the repository at this point in the history
array: generalize S.takeLast and S.dropLast
  • Loading branch information
davidchambers authored Apr 27, 2019
2 parents 52b661a + 164a82a commit 9bace6f
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 28 deletions.
58 changes: 34 additions & 24 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3003,59 +3003,69 @@
impl: drop
};

//# takeLast :: Integer -> Array a -> Maybe (Array a)
//# takeLast :: (Applicative f, Foldable f, Monoid (f a)) => Integer -> f a -> Maybe (f a)
//.
//. Returns Just the last N elements of the given array if N is greater
//. than or equal to zero and less than or equal to the length of the array;
//. Returns Just the last N elements of the given structure if N is
//. non-negative and less than or equal to the size of the structure;
//. Nothing otherwise.
//.
//. ```javascript
//. > S.takeLast (2) (['a', 'b', 'c', 'd', 'e'])
//. Just (['d', 'e'])
//. > S.takeLast (0) (['foo', 'bar'])
//. Just ([])
//.
//. > S.takeLast (5) (['a', 'b', 'c', 'd', 'e'])
//. Just (['a', 'b', 'c', 'd', 'e'])
//. > S.takeLast (1) (['foo', 'bar'])
//. Just (['bar'])
//.
//. > S.takeLast (2) (['foo', 'bar'])
//. Just (['foo', 'bar'])
//.
//. > S.takeLast (6) (['a', 'b', 'c', 'd', 'e'])
//. > S.takeLast (3) (['foo', 'bar'])
//. Nothing
//.
//. > S.takeLast (3) (Cons (1) (Cons (2) (Cons (3) (Cons (4) (Nil)))))
//. Just (Cons (2) (Cons (3) (Cons (4) (Nil))))
//. ```
function takeLast(n) {
return function(xs) {
return n >= 0 && n <= xs.length ? Just (xs.slice (xs.length - n))
: Nothing;
return Z.map (Z.reverse, take (n) (Z.reverse (xs)));
};
}
_.takeLast = {
consts: {},
types: [$.Integer, $.Array (a), $.Maybe ($.Array (a))],
consts: {f: [Z.Applicative, Z.Foldable, Z.Monoid]},
types: [$.Integer, f (a), $.Maybe (f (a))],
impl: takeLast
};

//# dropLast :: Integer -> Array a -> Maybe (Array a)
//# dropLast :: (Applicative f, Foldable f, Monoid (f a)) => Integer -> f a -> Maybe (f a)
//.
//. Returns Just all but the last N elements of the given array if N is
//. greater than or equal to zero and less than or equal to the length of
//. the array; Nothing otherwise.
//. Returns Just all but the last N elements of the given structure if
//. N is non-negative and less than or equal to the size of the structure;
//. Nothing otherwise.
//.
//. ```javascript
//. > S.dropLast (2) (['a', 'b', 'c', 'd', 'e'])
//. Just (['a', 'b', 'c'])
//. > S.dropLast (0) (['foo', 'bar'])
//. Just (['foo', 'bar'])
//.
//. > S.dropLast (1) (['foo', 'bar'])
//. Just (['foo'])
//.
//. > S.dropLast (5) (['a', 'b', 'c', 'd', 'e'])
//. > S.dropLast (2) (['foo', 'bar'])
//. Just ([])
//.
//. > S.dropLast (6) (['a', 'b', 'c', 'd', 'e'])
//. > S.dropLast (3) (['foo', 'bar'])
//. Nothing
//.
//. > S.dropLast (3) (Cons (1) (Cons (2) (Cons (3) (Cons (4) (Nil)))))
//. Just (Cons (1) (Nil))
//. ```
function dropLast(n) {
return function(xs) {
return n >= 0 && n <= xs.length ? Just (xs.slice (0, xs.length - n))
: Nothing;
return Z.map (Z.reverse, drop (n) (Z.reverse (xs)));
};
}
_.dropLast = {
consts: {},
types: [$.Integer, $.Array (a), $.Maybe ($.Array (a))],
consts: {f: [Z.Applicative, Z.Foldable, Z.Monoid]},
types: [$.Integer, f (a), $.Maybe (f (a))],
impl: dropLast
};

Expand Down
13 changes: 11 additions & 2 deletions test/dropLast.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
'use strict';

const S = require ('..');
const S = require ('./internal/sanctuary');

const {Nil, Cons} = require ('./internal/List');
const eq = require ('./internal/eq');


test ('dropLast', () => {

eq (typeof S.dropLast) ('function');
eq (S.dropLast.length) (1);
eq (S.show (S.dropLast)) ('dropLast :: Integer -> Array a -> Maybe (Array a)');
eq (S.show (S.dropLast)) ('dropLast :: (Applicative f, Foldable f, Monoid f) => Integer -> f a -> Maybe (f a)');

eq (S.dropLast (0) ([1, 2, 3, 4, 5])) (S.Just ([1, 2, 3, 4, 5]));
eq (S.dropLast (1) ([1, 2, 3, 4, 5])) (S.Just ([1, 2, 3, 4]));
Expand All @@ -21,4 +22,12 @@ test ('dropLast', () => {

eq (S.dropLast (-1) ([1, 2, 3, 4, 5])) (S.Nothing);

eq (S.dropLast (0) (Cons (1) (Cons (2) (Cons (3) (Nil))))) (S.Just (Cons (1) (Cons (2) (Cons (3) (Nil)))));
eq (S.dropLast (1) (Cons (1) (Cons (2) (Cons (3) (Nil))))) (S.Just (Cons (1) (Cons (2) (Nil))));
eq (S.dropLast (2) (Cons (1) (Cons (2) (Cons (3) (Nil))))) (S.Just (Cons (1) (Nil)));
eq (S.dropLast (3) (Cons (1) (Cons (2) (Cons (3) (Nil))))) (S.Just (Nil));
eq (S.dropLast (4) (Cons (1) (Cons (2) (Cons (3) (Nil))))) (S.Nothing);

eq (S.dropLast (-1) (Cons (1) (Cons (2) (Cons (3) (Nil))))) (S.Nothing);

});
13 changes: 11 additions & 2 deletions test/takeLast.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
'use strict';

const S = require ('..');
const S = require ('./internal/sanctuary');

const {Nil, Cons} = require ('./internal/List');
const eq = require ('./internal/eq');


test ('takeLast', () => {

eq (typeof S.takeLast) ('function');
eq (S.takeLast.length) (1);
eq (S.show (S.takeLast)) ('takeLast :: Integer -> Array a -> Maybe (Array a)');
eq (S.show (S.takeLast)) ('takeLast :: (Applicative f, Foldable f, Monoid f) => Integer -> f a -> Maybe (f a)');

eq (S.takeLast (0) ([1, 2, 3, 4, 5])) (S.Just ([]));
eq (S.takeLast (1) ([1, 2, 3, 4, 5])) (S.Just ([5]));
Expand All @@ -21,4 +22,12 @@ test ('takeLast', () => {

eq (S.takeLast (-1) ([1, 2, 3, 4, 5])) (S.Nothing);

eq (S.takeLast (0) (Cons (1) (Cons (2) (Cons (3) (Nil))))) (S.Just (Nil));
eq (S.takeLast (1) (Cons (1) (Cons (2) (Cons (3) (Nil))))) (S.Just (Cons (3) (Nil)));
eq (S.takeLast (2) (Cons (1) (Cons (2) (Cons (3) (Nil))))) (S.Just (Cons (2) (Cons (3) (Nil))));
eq (S.takeLast (3) (Cons (1) (Cons (2) (Cons (3) (Nil))))) (S.Just (Cons (1) (Cons (2) (Cons (3) (Nil)))));
eq (S.takeLast (4) (Cons (1) (Cons (2) (Cons (3) (Nil))))) (S.Nothing);

eq (S.takeLast (-1) (Cons (1) (Cons (2) (Cons (3) (Nil))))) (S.Nothing);

});

0 comments on commit 9bace6f

Please sign in to comment.