Skip to content

Instantly share code, notes, and snippets.

@gerardpaapu
Created May 1, 2012 08:52
Show Gist options
  • Save gerardpaapu/2566516 to your computer and use it in GitHub Desktop.
Save gerardpaapu/2566516 to your computer and use it in GitHub Desktop.
;;; OrderedSet
;;; ----------
;;;
;;; A Collection class that wraps an Array.
;;; It maintains immutability, an order, and
;;; does not contain duplicates
;;;
;;; Items of the Ordered Set should implement 'Ord'
(class OrderedSet
(constructor (items, ordered, distinct)
(set this.items (or items #[]))
;; ensure the qualities of the ordered set in this.items
;; call uniquify! unless the items are known to be distinct
;; call sort! unless the items are known to be sorted
(if distinct.isFalse? (this uniquify!)
ordered.isFalse? (this sort!)))
(method (contains? needle)
(this.items contains? needle))
(method (asArray)
;; return a clone so that clients don't
;; mutate our internal array
this.items.cloneArray)
(method (slice a b)
(this.items slice a, b))
(method (nth i)
this.items.[i])
(method (length)
this.items.length)
(method (concat ls)
(let [;; ls can be an OrderedSet or an Array
(items (if (ls isAn OrderedSet) ls.items
(ls isAn Array) ls))
;; items that don't exist in the destination
(new-items (ls filter ^(this contains #0) this))]
;; return the same OrderedSet unless there are new items
(if new-items.isEmpty?
this
(OrderedSet new (this.items concat new-items) true))))
(method (sort!)
;; Ensure that this.items is sorted by the Ord generics
(this.items sort ^(if (#0 > #1) MORE
(#1 < #0) LESS
EQUAL)))
(method (uniqify!)
;; Ensure that this.items is distinct
(set this.items
(this.items reduce ^[out, item] (if (out contains? item)
out
(out concat item))
#[]))))
var _passMessage = require('chitchat').passMessage;
var OrderedSet = function(items, ordered, distinct) {
_passMessage(this, "set", [ "items", items || [] ]);
if (_passMessage(distinct, "isFalse?")) {
_passMessage(this, "uniquify!");
} else {
if (_passMessage(ordered, "isFalse?")) {
_passMessage(this, "sort!");
}
}
};
OrderedSet["prototype"]["contains?"] = function(needle) {
return _passMessage(_passMessage(this, "items"), "contains?", [ needle ]);
};
OrderedSet["prototype"]["asArray"] = function() {
return _passMessage(_passMessage(this, "items"), "cloneArray");
};
OrderedSet["prototype"]["slice"] = function(a, b) {
return _passMessage(_passMessage(this, "items"), "slice", [ a, b ]);
};
OrderedSet["prototype"]["nth"] = function(i) {
return _passMessage(_passMessage(this, "items"), i);
};
OrderedSet["prototype"]["length"] = function() {
return _passMessage(_passMessage(this, "items"), "length");
};
OrderedSet["prototype"]["concat"] = function(ls) {
return function() {
var items, new_minus_items;
items = _passMessage(ls, "isAn", [ OrderedSet ]) ? _passMessage(ls, "items")
: _passMessage(ls, "isAn", [ Array ]) ? ls
: null;
new_minus_items = _passMessage(ls, "filter", [ function() {
return _passMessage(this, "contains", [ arguments[0] ]);
}, this ]);
return _passMessage(new_minus_items, "isEmpty?") ? this
: _passMessage(OrderedSet, "new", [ _passMessage(_passMessage(this, "items"), "concat", [ new_minus_items ]),
true ]);
}["apply"](this, typeof arguments != "undefined" ? arguments : []);
};
OrderedSet["prototype"]["sort!"] = function() {
return _passMessage(_passMessage(this, "items"), "sort", [ function() {
return _passMessage(arguments[0], ">", [ arguments[1] ]) ? MORE
: _passMessage(arguments[1], "<", [ arguments[0] ]) ? LESS
: EQUAL;
} ]);
};
OrderedSet["prototype"]["uniqify!"] = function() {
return _passMessage(this, "set", [ "items", _passMessage(_passMessage(this, "items"), "reduce", [ function(out, item) {
return _passMessage(out, "contains?", [ item ]) ? out
: _passMessage(out, "concat", [ item ]);
}, [] ]) ]);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment