Repository: sanctuary-js/sanctuary (js)

Issue:
Add S.reverse function
Create a typesafe version of [R.reverse](http://ramdajs.com/docs/#reverse).

Pull request description:
Add S.reverse
Fixes #196 

Patch:
diff --git a/index.js b/index.js
index a39c3cd..dc5b14c 100644
--- a/index.js
+++ b/index.js
@@ -471,8 +471,8 @@
   //. function.
   //.
   //. ```javascript
-  //. > S.A(S.inc, 42)
-  //. 43
+  //. > S.A(S.inc, 1)
+  //. 2
   //.
   //. > R.map(S.A(R.__, 100), [S.inc, Math.sqrt])
   //. [101, 10]
@@ -483,25 +483,6 @@
       [$.Function, a, b],
       function(f, x) { return f(x); });
 
-  //# T :: a -> (a -> b) -> b
-  //.
-  //. The T ([thrush][]) combinator. Takes a value and a function, and returns
-  //. the result of applying the function to the value. Equivalent to Haskell's
-  //. `(&)` function.
-  //.
-  //. ```javascript
-  //. > S.T(42, S.inc)
-  //. 43
-  //.
-  //. > R.map(S.T(100), [S.inc, Math.sqrt])
-  //. [101, 10]
-  //. ```
-  S.T =
-  def('T',
-      {},
-      [a, $.Function, b],
-      function(x, f) { return f(x); });
-
   //# C :: (a -> b -> c) -> b -> a -> c
   //.
   //. The C combinator. Takes a curried binary function and two values, and
@@ -2460,6 +2441,28 @@
         return n < 0 || negativeZero(n) ? Nothing() : slice(0, -n, xs);
       });
 
+  //# reverse :: [a] -> [a]
+  //.
+  //. Returns the elements of the given list in reverse order.
+  //.
+  //. ```javascript
+  //. > S.reverse([1, 2, 3])
+  //. [3, 2, 1]
+  //.
+  //. > S.reverse('abc')
+  //. 'cba'
+  //. ```
+  S.reverse =
+  def('reverse',
+      {},
+      [List(a), List(a)],
+      function reverse(xs) {
+        if (_type(xs) === 'String') return reverse(xs.split('')).join('');
+        var result = [];
+        for (var idx = xs.length - 1; idx >= 0; idx -= 1) result.push(xs[idx]);
+        return result;
+      });
+
   //  ArrayLike :: TypeClass
   var ArrayLike = $.TypeClass(
     'ArrayLike',
@@ -3451,4 +3454,3 @@
 //. [UnaryType]:      https://github.com/sanctuary-js/sanctuary-def#unarytype
 //. [parseInt]:       https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
 //. [sanctuary-def]:  https://github.com/sanctuary-js/sanctuary-def
-//. [thrush]:         https://github.com/raganwald-deprecated/homoiconic/blob/master/2008-10-30/thrush.markdown


Test patch:
diff --git a/test/T.js b/test/T.js
deleted file mode 100644
index f140b95..0000000
--- a/test/T.js
+++ /dev/null
@@ -1,26 +0,0 @@
-'use strict';
-
-var R = require('ramda');
-
-var eq = require('./utils').eq;
-var S = require('..');
-
-
-describe('T', function() {
-
-  it('is a binary function', function() {
-    eq(typeof S.T, 'function');
-    eq(S.T.length, 2);
-  });
-
-  it('T(x, f) is equivalent to f(x)', function() {
-    eq(S.T(42, S.inc), 43);
-    eq(R.map(S.T(100), [S.inc, Math.sqrt]), [101, 10]);
-  });
-
-  it('is curried', function() {
-    eq(S.T(42).length, 1);
-    eq(S.T(42)(S.inc), 43);
-  });
-
-});
diff --git a/test/reverse.js b/test/reverse.js
new file mode 100644
index 0000000..96a9cb3
--- /dev/null
+++ b/test/reverse.js
@@ -0,0 +1,43 @@
+'use strict';
+
+var throws = require('assert').throws;
+
+var eq = require('./utils').eq;
+var errorEq = require('./utils').errorEq;
+var S = require('..');
+
+
+describe('reverse', function() {
+
+  it('is a unary function', function() {
+    eq(typeof S.reverse, 'function');
+    eq(S.reverse.length, 1);
+  });
+
+  it('type checks its arguments', function() {
+    throws(function() { S.reverse({answer: 42}); },
+           errorEq(TypeError,
+                   'Invalid value\n' +
+                   '\n' +
+                   'reverse :: List a -> List a\n' +
+                   '           ^^^^^^\n' +
+                   '             1\n' +
+                   '\n' +
+                   '1)  {"answer": 42} :: Object, StrMap Number, StrMap FiniteNumber, StrMap NonZeroFiniteNumber, StrMap Integer, StrMap ValidNumber\n' +
+                   '\n' +
+                   'The value at position 1 is not a member of ‘List a’.\n'));
+
+  });
+
+  it('reverses arrays', function() {
+    eq(S.reverse([]), []);
+    eq(S.reverse([1, 2, 3]), [3, 2, 1]);
+    eq(S.reverse(['1', '2', '3']), ['3', '2', '1']);
+  });
+
+  it('reverses strings', function() {
+    eq(S.reverse(''), '');
+    eq(S.reverse('123'), '321');
+  });
+
+});