Created
April 8, 2013 10:44
-
-
Save jboulhous/5335884 to your computer and use it in GitHub Desktop.
a try to get some functional helpers from allong.es
most of this code is copied from from https://github.com/raganwald/allong.es
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// a try to get some functional helpers from allong.es | |
// most of this code is copied from from https://github.com/raganwald/allong.es | |
// helpers | |
var slice = Array.prototype.slice; | |
// to_function | |
function to_function (str) { | |
var expr, leftSection, params, rightSection, sections, v, vars, _i, _len; | |
params = []; | |
expr = str; | |
sections = expr.split(/\s*->\s*/m); | |
if (sections.length > 1) { | |
while (sections.length) { | |
expr = sections.pop(); | |
params = sections.pop().split(/\s*,\s*|\s+/m); | |
sections.length && sections.push('(function(' + params + '){return (' + expr + ')})'); | |
} | |
} else if (expr.match(/\b_\b/)) { | |
params = '_'; | |
} else { | |
leftSection = expr.match(/^\s*(?:[+*\/%&|\^\.=<>]|!=)/m); | |
rightSection = expr.match(/[+\-*\/%&|\^\.=<>!]\s*$/m); | |
if (leftSection || rightSection) { | |
if (leftSection) { | |
params.push('$1'); | |
expr = '$1' + expr; | |
} | |
if (rightSection) { | |
params.push('$2'); | |
expr = expr + '$2'; | |
} | |
} else { | |
vars = str.replace(/(?:\b[A-Z]|\.[a-zA-Z_$])[a-zA-Z_$\d]*|[a-zA-Z_$][a-zA-Z_$\d]*\s*:|this|arguments|'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/g, '').match(/([a-z_$][a-z_$\d]*)/gi) || []; | |
for (_i = 0, _len = vars.length; _i < _len; _i++) { | |
v = vars[_i]; | |
params.indexOf(v) >= 0 || params.push(v); | |
} | |
} | |
} | |
return new Function(params, 'return (' + expr + ')'); | |
}; | |
// functionalize | |
function functionalize (fn) { | |
if (typeof fn === 'function') { | |
return fn; | |
} else if (typeof fn === 'string' && /^[_a-zA-Z]\w*$/.test(fn)) { | |
return function() { | |
var args, receiver, _ref; | |
receiver = arguments[0]; | |
args = 2 <= arguments.length ? slice.call(arguments, 1) : []; | |
return (_ref = receiver[fn]).call.apply(_ref, [receiver].concat(slice.call(args))); | |
}; | |
} else if (typeof fn === 'string') { | |
return to_function(fn); | |
} else if (typeof fn.lambda === 'function') { | |
return fn.lambda(); | |
} else if (typeof fn.toFunction === 'function') { | |
return fn.toFunction(); | |
} | |
} | |
// extend | |
function extend () { | |
var consumer = arguments[0], | |
providers = slice.call(arguments, 1), | |
key, | |
i, | |
provider, | |
except; | |
for (i = 0; i < providers.length; ++i) { | |
provider = providers[i]; | |
except = provider['except'] || []; | |
except.push('except'); | |
for (key in provider) { | |
if (except.indexOf(key) < 0 && provider.hasOwnProperty(key)) { | |
consumer[key] = provider[key]; | |
} | |
} | |
} | |
return consumer; | |
} | |
/* | |
function Todo (name) { | |
var self = this instanceof Todo ? this : new Todo(); | |
self.name = name || 'Untitled'; | |
self.done = false; | |
}; | |
Todo.prototype.do = fluent( function () { this.done = true; }); | |
Todo.prototype.undo = fluent( function () { this.done = false; }); | |
*/ | |
function fluent (fn) { | |
fn = functionalize(fn); | |
return function () { | |
fn.apply(this, arguments); | |
return this | |
} | |
} | |
/* | |
var AddLocation = mixin({ | |
setLocation: fluent( function (location) { | |
this.location = location; | |
}), | |
getLocation: function () { return this.location; } | |
}); | |
AddLocation.call(Todo.prototype); | |
// Or use AddLocation(Todo.prototype) | |
new Todo("Vacuum").setLocation('Home'); | |
//=> { name: 'Vacuum', | |
// done: false, | |
// location: 'Home' } | |
*/ | |
function mixin (decoration) { | |
return function decorator () { | |
if (arguments[0] !== void 0) { | |
return decorator.call(arguments[0]); | |
} | |
else { | |
extend(this, decoration); | |
return this; | |
} | |
}; | |
}; | |
/* | |
var AndColourCoded = classDecorator({ | |
setColourRGB: fluent( function (r, g, b) { | |
this.colourCode = { r: r, g: g, b: b }; | |
}), | |
getColourRGB: function () { | |
return this.colourCode; | |
} | |
}); | |
var ColourTodo = AndColourCoded(Todo); | |
new ColourTodo('Use More Decorators').setColourRGB(0, 255, 0); | |
*/ | |
function classDecorator (decoration) { | |
return function (clazz) { | |
function Decorated () { | |
var self = this instanceof Decorated ? this : new Decorated(); | |
return clazz.apply(self, arguments); | |
} | |
Decorated.prototype = extend(new clazz(), decoration); | |
return Decorated; | |
} | |
} | |
function Model (attr) { | |
var self = this instanceof Model ? this : new Model(); | |
self.attr = attr || {}; | |
if(_.isFunction(this.initialize)) | |
this.initialize(attr); | |
}; | |
var TodoIt = classDecorator({ | |
constructor : function(attr){ | |
this.attr = attr || {done:false}; | |
}, | |
do: function () { | |
this.attr.done = true ; | |
}, | |
undo: function () { | |
this.attr.done = false ; | |
}, | |
status : function () { | |
return this.attr.done; | |
} | |
}); | |
var Todo = TodoIt(Model) | |
todo = new Todo({done:false}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment