Skip to content

Commit

Permalink
Underscore 0.4.5, with first/rest, head/tail, and all Array functions…
Browse files Browse the repository at this point in the history
… guaranteed to work on 'arguments' objects. Many method implementations reworked to use _.rest()
  • Loading branch information
jashkenas committed Nov 19, 2009
1 parent b5f111e commit ae968a6
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 90 deletions.
43 changes: 35 additions & 8 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,11 @@ <h2>Downloads <i style="padding-left: 12px; font-size:12px;">(Right-click, and u
<p>
<table>
<tr>
<td><a href="underscore.js">Development Version (0.4.4)</a></td>
<td><a href="underscore.js">Development Version (0.4.5)</a></td>
<td><i>18kb, Uncompressed with Comments</i></td>
</tr>
<tr>
<td><a href="underscore-min.js">Production Version (0.4.4)</a></td>
<td><a href="underscore-min.js">Production Version (0.4.5)</a></td>
<td><i>2kb, Packed and Gzipped</i></td>
</tr>
</table>
Expand Down Expand Up @@ -183,7 +183,7 @@ <h2>Table of Contents</h2>
<p>
<b>Arrays</b>
<br />
<span class="methods"><a href="#first">first</a>, <a href="#last">last</a>,
<span class="methods"><a href="#first">first</a>, <a href="#rest">rest</a>, <a href="#last">last</a>,
<a href="#compact">compact</a>, <a href="#flatten">flatten</a>, <a href="#without">without</a>, <a href="#uniq">uniq</a>,
<a href="#intersect">intersect</a>, <a href="#zip">zip</a>, <a href="#indexOf">indexOf</a></span>,
<a href="#lastIndexOf">lastIndexOf</a></span>
Expand Down Expand Up @@ -454,15 +454,33 @@ <h2>Collection Functions (Arrays or Objects)</h2>
</pre>

<h2>Array Functions</h2>

<p>
<i>Note: All array functions will also work on the <b>arguments</b> object.</i>
</p>

<p id="first">
<b class="header">first</b><code>_.first(array)</code>
<b class="header">first</b><code>_.first(array, [n])</code>
<span class="alias">Alias: <b>head</b></span>
<br />
Convenience to return the first element of an <b>array</b> (identical to <tt>array[0]</tt>).
Returns the first element of an <b>array</b>. Passing <b>n</b> will
return the first <b>n</b> elements of the array.
</p>
<pre>
_.first([3, 2, 1]);
=&gt; 3
_.first([5, 4, 3, 2, 1]);
=&gt; 5
</pre>

<p id="rest">
<b class="header">rest</b><code>_.rest(array, [index])</code>
<span class="alias">Alias: <b>tail</b></span>
<br />
Returns the <b>rest</b> of the elements in an array. Pass an <b>index</b>
to return the values of the array from that index onward.
</p>
<pre>
_.rest([5, 4, 3, 2, 1]);
=&gt; [4, 3, 2, 1]
</pre>

<p id="last">
Expand All @@ -471,7 +489,7 @@ <h2>Array Functions</h2>
Returns the last element of an <b>array</b>.
</p>
<pre>
_.last([3, 2, 1]);
_.last([5, 4, 3, 2, 1]);
=&gt; 1
</pre>

Expand Down Expand Up @@ -912,6 +930,15 @@ <h2>Chaining</h2>

<h2>Change Log</h2>

<p>
<b class="header">0.4.5</b><br />
Added <tt>rest</tt> for Arrays and arguments objects, and aliased
<tt>first</tt> as <tt>head</tt>, and <tt>rest</tt> as <tt>tail</tt>,
thanks to <a href="http://github.com/lukesutton/">Luke Sutton</a>'s patches.
Added tests ensuring that all Underscore Array functions also work on
<i>arguments</i> objects.
</p>

<p>
<b class="header">0.4.4</b><br />
Added <tt>isString</tt>, and <tt>isNumber</tt>, for consistency. Fixed
Expand Down
69 changes: 41 additions & 28 deletions test/arrays.js
Original file line number Diff line number Diff line change
@@ -1,76 +1,89 @@
$(document).ready(function() {

module("Array-only functions (last, compact, uniq, and so on...)");

test("arrays: first", function() {
equals(_.first([1,2,3]), 1, 'can pull out the first element of an array');
equals(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"');
equals(_.first([1,2,3], 2).join(', '), '1, 2', 'can pass an index to first');
var result = (function(){ return _.first(arguments); })(4, 3, 2, 1);
equals(result, 4, 'works on an arguments object.');
});


test("arrays: rest", function() {
var numbers = [1, 2, 3, 4];
equals(_.rest(numbers).join(", "), "2, 3, 4", 'working rest()');
equals(_.rest(numbers, 2).join(', '), '3, 4', 'rest can take an index');
var result = (function(){ return _(arguments).tail(); })(1, 2, 3, 4);
equals(result.join(', '), '2, 3, 4', 'aliased as tail and works on arguments object');
});

test("arrays: last", function() {
equals(_.last([1,2,3]), 3, 'can pull out the last element of an array');
var result = (function(){ return _(arguments).last(); })(1, 2, 3, 4);
equals(result, 4, 'works on an arguments object');
});

test("arrays: compact", function() {
equals(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values');
var result = (function(){ return _(arguments).compact().length; })(0, 1, false, 2, false, 3);
equals(result, 3, 'works on an arguments object');
});

test("arrays: flatten", function() {
var list = [1, [2], [3, [[[4]]]]];
equals(_.flatten(list).join(', '), '1, 2, 3, 4', 'can flatten nested arrays');
var result = (function(){ return _.flatten(arguments); })(1, [2], [3, [[[4]]]]);
equals(result.join(', '), '1, 2, 3, 4', 'works on an arguments object');
});

test("arrays: without", function() {
var list = [1, 2, 1, 0, 3, 1, 4];
equals(_.without(list, 0, 1).join(', '), '2, 3, 4', 'can remove all instances of an object');
var result = (function(){ return _.without(arguments, 0, 1); })(1, 2, 1, 0, 3, 1, 4);
equals(result.join(', '), '2, 3, 4', 'works on an arguments object');
});

test("arrays: uniq", function() {
var list = [1, 2, 1, 3, 1, 4];
equals(_.uniq(list).join(', '), '1, 2, 3, 4', 'can find the unique values of an unsorted array');

var list = [1, 1, 1, 2, 2, 3];
equals(_.uniq(list, true).join(', '), '1, 2, 3', 'can find the unique values of a sorted array faster');

var result = (function(){ return _.uniq(arguments); })(1, 2, 1, 3, 1, 4);
equals(result.join(', '), '1, 2, 3, 4', 'works on an arguments object');
});

test("arrays: intersect", function() {
var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho'];
equals(_.intersect(stooges, leaders).join(''), 'moe', 'can take the set intersection of two arrays');
equals(_(stooges).intersect(leaders).join(''), 'moe', 'can perform an OO-style intersection');
var result = (function(){ return _.intersect(arguments, leaders); })('moe', 'curly', 'larry');
equals(result.join(''), 'moe', 'works an an arguments object');
});

test('arrays: zip', function() {
var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true];
var stooges = _.zip(names, ages, leaders);
equals(String(stooges), 'moe,30,true,larry,40,,curly,50,', 'zipped together arrays of different lengths');
});

test("arrays: indexOf", function() {
var numbers = [1, 2, 3];
numbers.indexOf = null;
equals(_.indexOf(numbers, 2), 1, 'can compute indexOf, even without the native function');
var result = (function(){ return _.indexOf(arguments, 2); })(1, 2, 3);
equals(result, 1, 'works on an arguments object');
});

test("arrays: lastIndexOf", function() {
var numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0];
numbers.lastIndexOf = null;
equals(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');
equals(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element');
var result = (function(){ return _.lastIndexOf(arguments, 1); })(1, 0, 1, 0, 0, 1, 0, 0, 0);
equals(result, 5, 'works on an arguments object');
});

test("arrays: tail", function() {
var numbers = [1, 2, 3, 4];
equals(_.tail(numbers).join(", "), "2, 3, 4");
});

test("arrays: init", function() {
var numbers = [1, 2, 3, 4];
equals(_.init(numbers).join(", "), "1, 2, 3");
});

test("arrays: reverse", function() {
var numbers = [1, 2, 4, 6];
equals(_.reverse(numbers).join(", "), "6, 4, 2, 1");
});


});
6 changes: 3 additions & 3 deletions test/utility.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ $(document).ready(function() {
});

test("utility: functions", function() {
var expected = ["all", "any", "bind", "bindAll", "breakLoop", "clone", "compact",
var expected = ["all", "any", "bind", "bindAll", "breakLoop", "clone", "compact",
"compose","defer", "delay", "detect", "each", "every", "extend", "filter", "first",
"flatten", "foldl", "foldr", "forEach", "functions", "head", "identity", "include",
"indexOf", "init", "inject", "intersect", "invoke", "isArray", "isElement", "isEmpty", "isEqual",
"indexOf", "inject", "intersect", "invoke", "isArray", "isElement", "isEmpty", "isEqual",
"isFunction", "isNumber", "isString", "isUndefined", "keys", "last", "lastIndexOf", "map", "max",
"methods", "min", "pluck", "reduce", "reduceRight", "reject", "reverse", "select",
"methods", "min", "pluck", "reduce", "reduceRight", "reject", "rest", "select",
"size", "some", "sortBy", "sortedIndex", "tail", "template", "toArray", "uniq",
"uniqueId", "values", "without", "wrap", "zip"];
ok(_(expected).isEqual(_.methods()), 'provides a sorted list of functions');
Expand Down
Loading

0 comments on commit ae968a6

Please sign in to comment.