The problem with OO languages is they’ve got all this implicit environment that they carry around with them.
You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.
function logger(name, message){
console.info(name + ' says:', message)
}
var namedLogger = R.curry(logger)
var monsterLogger = namedLogger('Cookie monster')
monsterLogger('OM NOM NOM')
monsterLogger('ALL YOUR COOKIES ARE BELONG TO US!')
// >> 'Cookie monster says: OM NOM NOM'
// >> 'Cookie monster says: ALL YOUR COOKIES ARE
// >> BELONG TO US!'
var billLogger = namedLogger('Bill'),
billMessages = ['Bill can curry', 'Be like Bill']
R.forEach(billLogger, billMessages) // side effect
// >> 'Bill says: Bill can curry'
// >> 'Bill says: Be like Bill'
function converter(toUnit, factor, offset, input){
offset = offset || 0
return (offset+input)*factor).toFixed(2) + toUnit
}
var convert = R.curry(converter)
var milesToKm = convert('km', 1.609, null),
poundsToKg = convert('kg', 0.454, null),
farenheitToCelsius = convert('°C', 0.5556, -32)
milesToKm(10)
// >> "16.09km"
poundsToKg(2.5)
// >> "1.14kg"
farenheitToCelsius(98)
// >> "36.67°C"
var DEFAULTS = {
filename: 'webpack-[name].js',
path: '//static.90min.com/assets/',
}
// DEFAULTS are shared and overridable
var CONFS_BY_ENV = {
dev: { path: '//dev.90min.com:8080/assets' },
qa: { filename: 'WEBPACK-[name].QA.js' },
prod: {}, // matches DEFAULTS
}
// auto-currying: R.merge(DEFAULTS) returns a fn,
// which expects a second argument: a specific env
// conf object to override DEFAULTS with. It then
// returns a new object, leaving originals intact.
var CONFS = R.map(R.merge(DEFAULTS), CONFS_BY_ENV)
{
dev: {
filename: 'webpack-[name].js',
path: '//dev.90min.com:8080/assets',
},
qa: {
filename: 'WEBPACK-[name].QA.js',
path: '//static.90min.com/assets/',
},
prod: {
filename: 'webpack-[name].js',
path: '//static.90min.com/assets/',
},
}
var listOfWords = ['foo', 'bar', 'baz'],
first = list => list[0]
first(listOfWords)
// >> 'foo'
var reverse = list => list.reverse()
reverse(listOfWords)
// >> ['baz', 'bar', 'foo']
var last = R.compose(first, reverse)
last(listOfWords)
// >> 'baz'
var lastLeftToRight = R.pipe(reverse, first)
lastLeftToRight(listOfWords)
// >> 'baz'
var first = list => list[0],
reverse = list => list.reverse(),
last = R.compose(first, reverse)
var words = 'foo bar baz'
last(words)
// >> Uncaught TypeError: list.reverse is not
// >> a function
// Because 'list' in reverse() is a String,
// which doesn't have a 'reverse' method on
// it's prototype.
var first = list => list[0],
reverse = list => list.reverse(),
last = R.compose(first, reverse)
var listOfWords = ['foo', 'bar', 'baz']
function lastArg(){ return last(arguments) }
lastArg.apply(null, listOfWords)
// >> Uncaught TypeError: list.reverse is not
// >> a function
// Because 'list' in reverse() is an Arguments
// object, which is an 'Array like' object. It
// lacks Array.prototype's methods (it has
// numeric keys, length and a few other
// properties).
var first = list => R.head(list),
reverse = list => R.reverse(list),
last = R.compose(first, reverse)
function lastArg(){ return last(arguments) }
var listOfWords = ['foo', 'bar', 'baz']
lastArg.apply(null, listOfWords)
// >> 'baz'
var words = R.join(listOfWords, ' ') // 'foo bar baz'
last(words)
// >> 'z'
// Oops, while it works, it's not quite what we meant...
var isntSpace = char => char !== ' ' // <== predicate
// this is the essence of functional composition!
var lastWord = R.pipe(R.takeLastWhile(isntSpace), R.join(''))
lastWord(words)
// >> 'baz'
var responseSample = {
result: "SUCCESS",
tasks: [
{ id: 104,
complete: false, priority: "high",
dueDate: "2013-11-29", username: "Scott",
title: "Do something", created: "9/22/2013"},
{ id: 105,
complete: false, priority: "medium",
dueDate: "2013-11-22", username: "Lena",
title: "Have fun", created: "9/22/2013"},
{ id: 107,
complete: true, priority: "high",
dueDate: "2013-11-22", username: "Mike",
title: "Fix the bug", created: "9/22/2013"},
// , ...
]
}
getIncompleteTaskSummaries("Scott").then(log);
// Will log:
[
{
id: 110,
title: "Rename everything",
dueDate: "2013-11-15",
priority: "medium"
},
{
id: 104,
title: "Do something",
dueDate: "2013-11-29",
priority: "high"
}
]
function getIncompleteTaskSummaries(membername){
return fetchData()
.then(function(data){ return data.tasks })
.then(function(tasks){
var results = [];
for (var i = 0, len = tasks.length; i < len; i++) {
if (tasks[i].username == membername) {
results.push(tasks[i]);
}
}
return results;
})
.then(function(tasks){
var results = [];
for (var i = 0, len = tasks.length; i < len; i++) {
if (!tasks[i].complete) {
results.push(tasks[i]);
}
}
return results;
})
.then(function(tasks){
var results = [], task;
for (var i = 0, len = tasks.length; i < len; i++) {
task = tasks[i];
results.push({
id: task.id,
dueDate: task.dueDate,
title: task.title,
priority: task.priority
})
}
return results;
})
.then(function(tasks) {
tasks.sort(function(first, second) {
var a = first.dueDate, b = second.dueDate;
return a < b ? -1 : a > b ? 1 : 0;
});
return tasks;
});
}
var getIncompleteTaskSummaries = R.pipeP(
fetchData(),
R.prop('tasks'),
R.filter(R.propEq('username', username)),
R.reject(R.propEq('complete', true))
R.map(
R.pick(
['id', 'dueDate', 'title', 'priority']
)
),
R.sortBy(R.get('dueDate')),
)
getIncompleteTaskSummaries("Scott").then(log)