Tuesday, November 30, 2010

Monday, November 22, 2010

Generate a Version 4 UUID With Javascript

[sourcecode language="javascript"]
function uuid4() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c == "x" ? r : r & 0x3 | 0x8;
return v.toString(16);
});
}
[/sourcecode]

From Mvc2.TaskUI by Jonathan Oliver.

Thursday, November 18, 2010

Roll Your Own Map/Reduce in Javascript

I’ve been working on a very Javascript-heavy UI that allows the user to manipulate collections of objects. To ease the task of manipulation, I created a few methods on Array.prototype, which I rolled into a file I call iterable.js:

[sourcecode language="javascript"]
var Iterable = {
func: {
predicate: {
TRUE: function (x) { return true; }
}
}
};

Array.prototype.forEach = function (fn) {
for (var i = 0; i < this.length; i++)
fn(this[i]);
};

Array.prototype.filter = function (pred) {
var result = [];
this.forEach(function (x) {
if (pred(x))
result.push(x);
});

return result;
};

Array.prototype.distinct = function () {
var result = [];
this.forEach(function (x) {
if (!result.any(function (y) { return y == x; }))
result.push(x);
});

return result;
};

Array.prototype.any = function (pred) {
pred = pred || Iterable.func.predicate.TRUE;

for (var i = 0; i < this.length; i++)
if (pred(this[i]))
return true;

return false;
};

Array.prototype.indexOf = function (expr) {
if (!(expr instanceof Function))
expr = function (x) { return x == expr; };

for (var i = 0; i < this.length; i++)
if (expr(this[i]))
return i;

return -1;
};

Array.prototype.singleOrNull = function (pred) {
var filtered = this.filter(pred);
if (filtered.length == 0)
return null;
if (filtered.length > 1)
throw "More than one element returned.";

return filtered[0];
};

Array.prototype.map = function (fn) {
var mapped = [];
this.forEach(function (x) { mapped.push(fn(x)); });
return mapped;
};

Array.prototype.groupBy = function (sel) {
var groups = [];

this.forEach(function (x) {
var group = groups.singleOrNull(function (y) { return y.key == sel(x); });
if (!group)
groups.push({ key: sel(x), members: [x] });
else
group.members.push(x);
});

return groups;
};
[/sourcecode]

Note that this not particularly complete; for example, you’ll see that there is no implementation of a reduce function. It’s not here because I have not needed it in my project yet, nor am I likely to. But it would be easy to implement:

[sourcecode language="javascript"]
Array.prototype.reduce = function (fn) {
    if (this.length == 1)
        return this[0];
    return fn(this[0], this.slice(1).reduce(fn));
};
[/sourcecode]

Now, I’m aware of Underscore and others, so why did I do this? For two reasons, mainly: I only needed a subset of the functions that those libraries offer, and besides, it was fun.