Skip to content

Instantly share code, notes, and snippets.

@javascripter
Created January 29, 2009 11:03
Show Gist options
  • Save javascripter/54503 to your computer and use it in GitHub Desktop.
Save javascripter/54503 to your computer and use it in GitHub Desktop.
var q;
(function () {
function forEach(object, fun, self) {
for (var k in object) fun.call(self, object[k], k, object);
}
function generic(source, dest) {
// If it isn't generic, transfer to parent(e.g. Array#toString).
try {'' + dest;} catch (error) {
dest.toString = function () {
return source.toString.apply(source, arguments);
};
}
return dest;
};
function clone(object) {
return generic(object, {__proto__: object});
}
function extend(source, properties) {
forEach(properties, function (v, k) {source[k] = v;});
return source;
}
function create(source, properties) {
properties.__proto__ = source;
properties.parent = source;
return generic(source, properties);
}
q = create(
Object.prototype, {toString: function () {return '[object q]';}});
q.object = create(
Object, {clone: clone, extend: extend, create: create, forEach: forEach});
})();
q.fun = q.object.create(Function, {
invoke: function (method_name, args) {
if (!args) args = [];
return function (self) {
return self[method_name].apply(self, args);
};
},
bind: function (fun, self, args) {
if (!args) args = [];
return function () {
return fun.apply(self, args.concat(q.array.slice(arguments)));
};
},
applied: function (fun, self, args) {
if (!args) args = [];
return function () {return fun.apply(self, args);};
},
compose: function () {
var args = arguments;
return function (initial) {
return q.array.reduceRight(
args, function (value, fun) {return fun(value);}, initial);
};
}
});
q.array = q.object.create(Array, {
append: function (array, object) {
return this.concat([], array, this.concat([], object));
},
include: function (array, object) {
return this.indexOf(array, object) !== -1;
},
uniq: function (array) {
return this.reduce(array, q.fun.bind(
function (unique, object) {
if (this.include(unique, object)) return unique;
return this.append(unique, object);
}, this), []);
},
flatten: function (array) {
return this.reduce(array, q.fun.bind(
function (a, b) {
return this.concat(a, b);
}, this), []);
},
last: function (array) {
if (array.length === 0) return undefined;
return array[array.length - 1];
}
});
q.string = q.object.create(String, {
fill: function (format, object) {
function injector(m, name) {return object[name];}
return format.replace(/{(.*?)}/g, injector);
},
gensym: function () {
var counter = 0;
return function () {return 'gensym_' + (counter++).toString(16);};
}(),
w: q.fun.invoke('split', [/\s*/]),
escapeHTML: q.fun.compose(
q.fun.invoke('replace', [/"/g, '"']),
q.fun.invoke('replace', [/</g, '&lt;']),
q.fun.invoke('replace', [/>/g, '&gt;']),
q.fun.invoke('replace', [/&/g, '&amp;']))
});
(function () {
function assert(fun) {
var value;
try {
value = fun();
} catch (ex) {
console.error(fun.name, ex, fun.toSource());
return;
}
if (value) {
console.log(fun.name);
} else {
console.error(fun.name, fun.toSource());
}
}
assert(function genericToString() {
var a = q.object.clone([]);
return a.toString() === "" && q.object.toString();
});
assert(function basicClone() {
var o = q.object.clone({a: 2, b: 1});
return o.a === 2 && !o.hasOwnProperty("b");
});
assert(function basicExtend() {
var o = {a: 1, b: 2};
var p = {a: 2, c: 1};
return q.object.extend(o, p) === o && o.a === 2 && !p.b;
});
assert(function basicCreate() {
var o = {a: 1};
var p = {};
return q.object.create(o, p) === p && o.a === 1 && p.parent === o;
});
assert(function genericToStringWithCreate() {
return q.object.create({}, {toString: function () {throw new Error()}}) + "";
});
assert(function basicInvoke() {
return q.fun.invoke("toString")(q.object) === q.object.toString();
});
assert(function argsInvoke() {
var a = ["a"];
return q.fun.invoke("test", a)(/a/) && q.fun.invoke("test", a)(/a/);
});
assert(function basicBind() {
var a = [];
var f = q.fun.bind(Array.prototype.push, a ,[1]);
return f(2, 3) === a.length && a.shift() === 1;
});
assert(function basicApplied() {
var a = [];
q.fun.applied(Array.prototype.push, a, [1]).call(null, 2, 3);
return a.length === 1 && a[0] === 1;
});
assert(function basicCompose() {
var val = q.fun.compose(
function (a) {
return a + 1;
},
function (a) {
return a + "x";
}
)(0);
return val === "0x1";
});
assert(function initialCompose() {
return q.fun.compose(function (x) {return x;})() === undefined;
});
assert(function inheritedArray() {
return q.array.push === Array.push;
});
assert(function basicInclude() {
return q.array.include([1, 2, 3], 2) && !q.array.include([], undefined) &&
!q.array.include([new Number(1), null], 1);
});
assert(function strictInclude() {
var falsy = [undefined, null, false, 0, ""];
return q.array.include(falsy) && !q.array.include(falsy, true) &&
!q.array.include(falsy, falsy.toString);
});
assert(function basicUniq() {
var a = [1, 2, 3, 1, 2];
var u = q.array.uniq(a)
return u !== a && u[1] === 2;
});
assert(function strictUniq() {
var a = [new Number(1), new String("a"), null, false, undefined, 0, 1, "a"];
return q.array.uniq(a).length === a.length;
});
assert(function basicFlatten() {
var a = [[], [1,2], [[1, 2]], 3];
return q.array.flatten(a).length === 4 && !q.array.flatten([]).length &&
q.array.flatten(a) !== a;
});
assert(function basicLast() {
return q.array.last([]) === undefined && q.array.last([1, 2]) === 2;
});
assert(function basicFill() {
return q.string.fill("") === "" && q.string.fill("{0}", ["a"]) == "a" &&
q.string.fill("{{}}", {"{":1});
});
assert(function basicGensym() {
return typeof q.string.gensym() === "string" &&
q.string.gensym() !== q.string.gensym();
});
assert(function basicW() {
var a = q.string.w("a b c");
return q.string.w("").length === 0 && a[1] === "b" && a.length === 3;
});
assert(function escapeHTML() {
return q.string.escapeHTML("") === "" &&
q.string.escapeHTML('&"<>&amp;') === "&amp;&quot;&lt;&gt;&amp;amp;";
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment