Repository: plaid/sanctuary
Pull request #67 (2015-07-30 18:02:38)

add takeLast and dropLast
Adds functions referred to by #66 to bring Sanctuary up to date with Ramda 0.17.


Patch:
diff --git a/index.js b/index.js
index c3967b2..520c67c 100644
--- a/index.js
+++ b/index.js
@@ -1144,6 +1144,27 @@
     return n < 0 || negativeZero(n) ? Nothing() : slice(0, n, xs);
   });
 
+  //# takeLast :: Number -> [a] -> Maybe [a]
+  //.
+  //. Returns Just the last N elements of the given collection if N is
+  //. greater than or equal to zero and less than or equal to the length
+  //. of the collection; Nothing otherwise. Supports Array, String, and
+  //. any other collection type which provides a `slice` method.
+  //.
+  //. ```javascript
+  //. > S.takeLast(2, ['a', 'b', 'c', 'd', 'e'])
+  //. Just(["d", "e"])
+  //.
+  //. > S.takeLast(4, 'abcdefg')
+  //. Just("defg")
+  //.
+  //. > S.takeLast(4, ['a', 'b', 'c'])
+  //. Nothing()
+  //. ```
+  S.takeLast = def('takeLast', [Number, Accessible], function(n, xs) {
+    return n < 0 || negativeZero(n) ? Nothing() : slice(-n, -0, xs);
+  });
+
   //# drop :: Number -> [a] -> Maybe [a]
   //.
   //. Returns Just all but the first N elements of the given collection
@@ -1165,6 +1186,27 @@
     return n < 0 || negativeZero(n) ? Nothing() : slice(n, -0, xs);
   });
 
+  //# dropLast :: Number -> [a] -> Maybe [a]
+  //.
+  //. Returns Just all but the last N elements of the given collection
+  //. if N is greater than or equal to zero and less than or equal to the
+  //. length of the collection; Nothing otherwise. Supports Array, String,
+  //. and any other collection type which provides a `slice` method.
+  //.
+  //. ```javascript
+  //. > S.dropLast(2, ['a', 'b', 'c', 'd', 'e'])
+  //. Just(["a", "b", "c"])
+  //.
+  //. > S.dropLast(4, 'abcdefg')
+  //. Just("abc")
+  //.
+  //. > S.dropLast(4, 'abc')
+  //. Nothing()
+  //. ```
+  S.dropLast = def('dropLast', [Number, Accessible], function(n, xs) {
+    return n < 0 || negativeZero(n) ? Nothing() : slice(0, -n, xs);
+  });
+
   //# find :: (a -> Boolean) -> [a] -> Maybe a
   //.
   //. Takes a predicate and a list and returns Just the leftmost element of


Test patch:
diff --git a/test/index.js b/test/index.js
index bdc3203..5df8300 100644
--- a/test/index.js
+++ b/test/index.js
@@ -1652,6 +1652,55 @@ describe('list', function() {
 
   });
 
+  describe('takeLast', function() {
+
+    it('is a binary function', function() {
+      eq(typeof S.takeLast, 'function');
+      eq(S.takeLast.length, 2);
+    });
+
+    it('type checks its arguments', function() {
+      assert.throws(function() { S.takeLast([1, 2, 3]); },
+                    errorEq(TypeError,
+                            '‘takeLast’ requires a value of type Number ' +
+                            'as its first argument; received [1, 2, 3]'));
+
+      assert.throws(function() { S.takeLast(0, null); },
+                    errorEq(TypeError,
+                            'The second argument to ‘takeLast’ ' +
+                            'cannot be null or undefined'));
+    });
+
+    it('returns a Nothing if n is negative', function() {
+      eq(S.takeLast(-0, ['a', 'b', 'c', 'd', 'e']), S.Nothing());
+      eq(S.takeLast(-1, ['a', 'b', 'c', 'd', 'e']), S.Nothing());
+      eq(S.takeLast(-0, 'abcde'), S.Nothing());
+      eq(S.takeLast(-1, 'abcde'), S.Nothing());
+      // jshint -W053
+      eq(S.takeLast(new Number(-0), ['a', 'b', 'c', 'd', 'e']), S.Nothing());
+      // jshint +W053
+    });
+
+    it('returns a Just with the last n elements for valid n; Nothing otherwise', function() {
+      eq(S.takeLast(4, ['a', 'b', 'c']), S.Nothing());
+      eq(S.takeLast(3, ['a', 'b', 'c']), S.Just(['a', 'b', 'c']));
+      eq(S.takeLast(2, ['a', 'b', 'c']), S.Just(['b', 'c']));
+      eq(S.takeLast(1, ['a', 'b', 'c']), S.Just(['c']));
+      eq(S.takeLast(0, ['a', 'b', 'c']), S.Just([]));
+      eq(S.takeLast(4, 'abc'), S.Nothing());
+      eq(S.takeLast(3, 'abc'), S.Just('abc'));
+      eq(S.takeLast(2, 'abc'), S.Just('bc'));
+      eq(S.takeLast(1, 'abc'), S.Just('c'));
+      eq(S.takeLast(0, 'abc'), S.Just(''));
+    });
+
+    it('is curried', function() {
+      eq(S.takeLast(3).length, 1);
+      eq(S.takeLast(3)(['a', 'b', 'c', 'd', 'e']), S.Just(['c', 'd', 'e']));
+    });
+
+  });
+
   describe('drop', function() {
 
     it('is a binary function', function() {
@@ -1708,6 +1757,55 @@ describe('list', function() {
 
   });
 
+  describe('dropLast', function() {
+
+    it('is a binary function', function() {
+      eq(typeof S.dropLast, 'function');
+      eq(S.dropLast.length, 2);
+    });
+
+    it('type checks its arguments', function() {
+      assert.throws(function() { S.dropLast([1, 2, 3]); },
+                    errorEq(TypeError,
+                            '‘dropLast’ requires a value of type Number ' +
+                            'as its first argument; received [1, 2, 3]'));
+
+      assert.throws(function() { S.dropLast(0, null); },
+                    errorEq(TypeError,
+                            'The second argument to ‘dropLast’ ' +
+                            'cannot be null or undefined'));
+    });
+
+    it('returns a Nothing if n is negative', function() {
+      eq(S.dropLast(-3, ['a', 'b', 'c', 'd', 'e']), S.Nothing());
+      eq(S.dropLast(-0, ['a', 'b', 'c', 'd', 'e']), S.Nothing());
+      eq(S.dropLast(-3, 'abcde'), S.Nothing());
+      eq(S.dropLast(-0, 'abcde'), S.Nothing());
+      // jshint -W053
+      eq(S.dropLast(new Number(-0), ['a', 'b', 'c', 'd', 'e']), S.Nothing());
+      // jshint +W053
+    });
+
+    it('returns a Just dropping the last n items for valid n; Nothing otherwise', function() {
+      eq(S.dropLast(4, ['a', 'b', 'c']), S.Nothing());
+      eq(S.dropLast(3, ['a', 'b', 'c']), S.Just([]));
+      eq(S.dropLast(2, ['a', 'b', 'c']), S.Just(['a']));
+      eq(S.dropLast(1, ['a', 'b', 'c']), S.Just(['a', 'b']));
+      eq(S.dropLast(0, ['a', 'b', 'c']), S.Just(['a', 'b', 'c']));
+      eq(S.dropLast(4, 'abc'), S.Nothing());
+      eq(S.dropLast(3, 'abc'), S.Just(''));
+      eq(S.dropLast(2, 'abc'), S.Just('a'));
+      eq(S.dropLast(1, 'abc'), S.Just('ab'));
+      eq(S.dropLast(0, 'abc'), S.Just('abc'));
+    });
+
+    it('is curried', function() {
+      eq(S.dropLast(3).length, 1);
+      eq(S.dropLast(3)(['a', 'b', 'c', 'd', 'e']), S.Just(['a', 'b']));
+    });
+
+  });
+
   describe('find', function() {
 
     it('is a binary function', function() {