Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
splat.js
// see http://blog.aijoona.com/2012/05/16/splat-operator-en-javascript/
function splat(fn) {
var _ = function(target) {
if(typeof target == 'undefined') {
return _.byIndex(-1);
}
if(typeof target == 'number') {
return _.byIndex(target);
}
return _.byName(target);
};
_.rest = function(index) {
return fn.length - index;
};
// from Prototype.js (https://github.com/sstephenson/prototype/blob/master/src/prototype/lang/function.js#L38)
_.argumentNames = function() {
var names = fn.toString()
.match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
.replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
.replace(/\s+/g, '').split(',');
return names.length == 1 && !names[0] ? [] : names;
};
_.byIndex = function(index) {
return function __splatted() {
var args, splat, elements;
args = [].slice.call(arguments);
if(index < 0) {
index = fn.length + index;
}
to = args.length - fn.length + index + 1;
splat = args.slice(0, index);
splat = splat.concat([args.slice(index, to)]);
splat = splat.concat(args.slice(to));
return fn.apply(this, splat);
}
};
_.byName = function(name) {
return _.byIndex(_.argumentNames().indexOf(name));
};
return _;
};
// Sugar
Function.prototype.splat = function(target) {
return splat(this)(target);
};
// Examples
(function(winner, runners, me) {
console.log(winner, ', ', runners, ', ', me);
}).splat(0)(1, 2, 3, 4, 5);
(function(winner, runners, me) {
console.log(winner, ', ', runners, ', ', me);
}).splat('winner')(1, 2, 3, 4, 5);
(function(winner, runners, me) {
console.log(winner, ', ', runners, ', ', me);
}).splat(-2)(1, 2, 3, 4, 5);
var f0 = function() {
return [];
};
var f1 = function(a) {
return [a];
};
var f2 = function(a, b) {
return [a, b];
};
var f3 = function(a, b, c) {
return [a, b, c];
};
var f4 = function(a, b, c, d) {
return [a, b, c, d];
};
var f5 = function(a, b, c, d, e) {
return [a, b, c, d, e];
};
var f6 = function(a, b, c, d, e, f) {
return [a, b, c, d, e, f];
};
test('default (index argument: -1)', function() {
deepEqual(
f0.splat()(1, 2, 3),
[]
);
deepEqual(
f1.splat()(1, 2, 3),
[[1, 2, 3]]
);
deepEqual(
f2.splat()(1, 2, 3),
[1, [2, 3]]
);
deepEqual(
f3.splat()(1, 2, 3),
[1, 2, [3]]
);
deepEqual(
f4.splat()(1, 2, 3),
[1, 2, 3, []]
);
});
test('index argument: 0', function() {
deepEqual(
f0.splat(0)(1, 2, 3),
[]
);
deepEqual(
f1.splat(0)(1, 2, 3),
[[1, 2, 3]]
);
deepEqual(
f2.splat(0)(1, 2, 3),
[[1, 2], 3]
);
deepEqual(
f3.splat(0)(1, 2, 3),
[[1], 2, 3]
);
deepEqual(
f4.splat(0)(1, 2, 3),
[[], 1, 2, 3]
);
});
test('index argument: a', function() {
raises(
function() {
return f0.splat('a')(1, 2, 3);
}
);
deepEqual(
f1.splat('a')(1, 2, 3),
[[1, 2, 3]]
);
deepEqual(
f2.splat('a')(1, 2, 3),
[[1, 2], 3]
);
deepEqual(
f3.splat('a')(1, 2, 3),
[[1], 2, 3]
);
deepEqual(
f4.splat('a')(1, 2, 3),
[[], 1, 2, 3]
);
});
test('named argument: c', function() {
raises(
function() {
f0.splat('c')(1, 2, 3);
}
);
raises(
function() {
f1.splat('c')(1, 2, 3);
}
);
raises(
function() {
f2.splat('c')(1, 2, 3);
}
);
deepEqual(
f3.splat('c')(1, 2, 3),
[1, 2, [3]]
);
deepEqual(
f4.splat('c')(1, 2, 3),
[1, 2, [], 3]
);
});
test('index argument: -1', function() {
deepEqual(
f0.splat(-1)(1, 2, 3),
[]
);
deepEqual(
f1.splat(-1)(1, 2, 3),
[[1, 2, 3]]
);
deepEqual(
f2.splat(-1)(1, 2, 3),
[1, [2, 3]]
);
deepEqual(
f3.splat(-1)(1, 2, 3),
[1, 2, [3]]
);
deepEqual(
f4.splat(-1)(1, 2, 3),
[1, 2, 3, []]
);
});
test('index argument: -2', function() {
deepEqual(
f0.splat(-2)(1, 2, 3),
[]
);
deepEqual(
f1.splat(-2)(1, 2, 3),
[1]
);
deepEqual(
f2.splat(-2)(1, 2, 3),
[[1, 2], 3]
);
deepEqual(
f3.splat(-2)(1, 2, 3),
[1, [2], 3]
);
deepEqual(
f4.splat(-2)(1, 2, 3),
[1, 2, [], 3]
);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment