Skip to content
Browse files

Equality method used by Set is equals(), not equal(). Set#add() retur…

…ns a boolean. Some documentation for Set.
  • Loading branch information...
1 parent f564ef1 commit aa49d37a0d5a5658e54adc685b0c7dfbc49630ab @jcoglan jcoglan committed Aug 4, 2008
Showing with 150 additions and 11 deletions.
  1. +2 −0 site/src/layouts/application.haml
  2. +136 −0 site/src/pages/set.haml
  3. +5 −4 source/set.js
  4. +7 −7 test/test.html
View
2 site/src/layouts/application.haml
@@ -63,6 +63,8 @@
%li
=link 'Proxies'
%li
+ =link 'Set'
+ %li
=link 'StackTrace'
%li
=link 'State'
View
136 site/src/pages/set.haml
@@ -0,0 +1,136 @@
+:textile
+ h3. @JS.Set@
+
+ The @JS.Set@ class can be used to model collections of unique objects. A set makes sure
+ that there are no duplicates among its members, and it allows you to use custom equality
+ methods for comparison as well as JavaScript's @===@ operator.
+
+ As well as @JS.Set@, an additional class called @JS.SortedSet@ is provided. This class
+ keeps all its members in sort order as long as they are mutually comparable, either using
+ JavaScript's @<@, @<=@, @==@, @>@, @>=@ operators or using the "@Comparable@":/comparable.html
+ module. Sorting the elements allows this class to guarantee iteration order, and gives the
+ class a performance benefit over the regular @JS.Set@ class, especially on larger data sets.
+ @SortedSet@ is a subclass of @Set@; its API is identical, only its storage mechanism is
+ different.
+
+ If you try to add an object that has an @equals()@ method to a set, that method will be used to compare
+ the object to the set's members. @equals()@ should accept one argument and return a boolean
+ to indicate whether the two objects are to be considered equal. If no @equals()@ method
+ exists on the object, the @===@ operator is used instead. An example class might look like:
+
+ <pre class="prettyprint">
+ Widget = new JS.Class({
+ initialize: function(name) {
+ this.name = name;
+ },
+ equals: function(object) {
+ return (object instanceof this.klass)
+ && object.name == this.name;
+ }
+ });</pre>
+
+ Bear in mind that uniqueness (and sort order for @SortedSet@) is only maintained when new
+ objects are added to the set. Objects can be changed such that two objects that are
+ unequal can be made to be equal; if those two objects are members of a set the set is
+ then corrupted. To get around this, all sets have a @rebuild()@ method that throws out
+ any duplicates and fixes sort order.
+
+ Creating a set is simple: simply pass an array (or some other enumerable object) with the
+ data to put in the set:
+
+ <pre class="prettyprint">
+ var evensUnderTen = new JS.Set([2,4,6,8]);</pre>
+
+ @Set@ and @SortedSet@ include the "@Enumerable@":/enumerable.html module as long as you
+ load said module before the @Set@ file. The iteration order for @Set@ is arbitrary and is
+ not guaranteed, whereas for @SortedSet@ iteration takes place in sort order. The rest of
+ the API is as follows:
+
+ h3. @add(item)@
+
+ Adds a new item to the set as long as the set does not already contain the item. If
+ @item@ has an @equals()@ method, @item.equals()@ is used for comparison to other set
+ members (see above). Returns a boolean to indicate whether or not the item was added.
+
+ <pre class="prettyprint">
+ var evensUnderTen = new JS.Set([2,4,6,8]);
+ evensUnderTen.add(6) // -> false
+ evensUnderTen.add(0) // -> true</pre>
+
+ h3. @classify(block, context)@
+
+ Splits the set into several sets based on the return value of @block@ for each member.
+
+ <pre class="prettyprint">
+ // Classify by remainder when divided by 3
+
+ var s = new JS.Set([1,2,3,4,5,6,7,8,9]);
+ var c = s.classify(function(x) {
+ return x % 3;
+ });
+
+ // c[0] == Set{3,6,9}
+ // c[1] == Set{1,4,7}
+ // c[2] == Set{2,5,8}</pre>
+
+ h3. @clear()@
+
+ Removes all members from the set.
+
+ h3. @contains(item)@
+
+ Returns @true@ iff the set contains @item@.
+
+ h3. @difference(other)@
+
+ Returns a new set containing all the members of the receiver that are not in the set
+ @other@.
+
+ <pre class="prettyprint">
+ var a = new JS.Set([1,2,3,4,5,6,7,8,9]);
+ var b = new JS.Set([2,4,6,8]);
+
+ a.difference(b)
+ // -> Set{1,3,5,7,9}</pre>
+
+ h3. @divide(block, context)@
+
+ Similar to @classify(block, context)@ except that the result is given as a set of sets,
+ rather than as key/value pairs.
+
+ <pre class="prettyprint">
+ // Classify by remainder when divided by 3
+
+ var s = new JS.Set([1,2,3,4,5,6,7,8,9]);
+ var c = s.divide(function(x) {
+ return x % 3;
+ });
+
+ // c == Set { Set{3,6,9}, Set{1,4,7}, Set{2,5,8} }</pre>
+
+ h3. @equals(set)@
+
+ Returns @true@ iff @set@ is a @Set@ or a @SortedSet@ with the same members as the receiver.
+
+ h3. @flatten()@
+
+ Flattens the set in place, such any sets nested within the receiver are merged and their
+ members become the receiver's members.
+
+ <pre class="prettyprint">
+ var s = new JS.Set([ new JS.Set([3,9,4]),
+ new JS.Set([1,7,3,5]), 3, 7 ]);
+
+ // s == Set{ Set{3,9,4}, Set{1,7,3,5}, 3, 7}
+
+ s.flatten();
+
+ // s == Set{3,9,4,1,7,5}</pre>
+
+ h3. @intersection(set)@
+
+ Returns a new set containing members common to both @set@ and the receiver.
+
+ h3. @isEmpty()@
+
+ Returns @true@ iff the receiver has no members.
View
9 source/set.js
@@ -8,8 +8,8 @@ JS.Set = new JS.Class({
},
areEqual: function(one, another) {
- return one.equal
- ? one.equal(another)
+ return one.equals
+ ? one.equals(another)
: (one === another);
}
},
@@ -29,9 +29,10 @@ JS.Set = new JS.Class({
},
add: function(item) {
- if (this.contains(item)) return;
+ if (this.contains(item)) return false;
this._members.push(item);
this.length = this.size = this._members.length;
+ return true;
},
classify: function(block, context) {
@@ -68,7 +69,7 @@ JS.Set = new JS.Class({
return sets;
},
- equal: function(other) {
+ equals: function(other) {
if (this.length != other.length || !(other instanceof JS.Set)) return false;
var i = this._members.length;
while (i--) {
View
14 test/test.html
@@ -1237,23 +1237,23 @@
assert(new JS.SortedSet().isSubset(new JS.Set([1,2,3])));
sets.replace([0,3,8,2]);
- assert(sets.equal(new JS.SortedSet([3,0,2,8])));
+ assert(sets.equals(new JS.SortedSet([3,0,2,8])));
c = new JS.Set([8,2,6,5,7]);
c.remove(2);
- assert(c.equal(new JS.Set([5,6,7,8])));
+ assert(c.equals(new JS.Set([5,6,7,8])));
c.removeIf(function(x) { return x%2 == 0 });
- assert(c.equal(new JS.Set([5,7])));
+ assert(c.equals(new JS.Set([5,7])));
c = new JS.Set([8,2,6,5,7]);
c.subtract([7,6]);
- assert(c.equal(new JS.Set([5,8,2])));
+ assert(c.equals(new JS.Set([5,8,2])));
var xa = new JS.Set([2,9,3,7,5]), xb = new JS.Set([8,1,5,2,6]);
var x = xa.xor(xb);
- assert(x.equal(new JS.Set([9,3,7,8,1,6])));
- assert(xa.equal(new JS.Set([2,9,3,7,5])));
- assert(xb.equal(new JS.Set([8,1,5,6,2])));
+ assert(x.equals(new JS.Set([9,3,7,8,1,6])));
+ assert(xa.equals(new JS.Set([2,9,3,7,5])));
+ assert(xb.equals(new JS.Set([8,1,5,6,2])));
var s, ary, i, n = 10;

0 comments on commit aa49d37

Please sign in to comment.
Something went wrong with that request. Please try again.