Review by Scott Sauyet
Functional JavaScript
Michael Fogus
O'Reilly, 2013
987-1-449-36072-6
I was very excited when I heard this book was coming out. I'd enjoyed
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"/> | |
<title>String#includes vs. String#indexOf vs. RegExp</title> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/1.0.0/benchmark.min.js"></script> | |
<script src="./suite.js"></script> | |
</head> | |
<body> | |
<h1>Open the console to view the results</h1> |
const R = require('ramda'); | |
const permutations = (tokens, subperms = [[]]) => | |
R.isEmpty(tokens) ? | |
subperms : | |
R.addIndex(R.chain)((token, idx) => permutations( | |
R.remove(idx, 1, tokens), | |
R.map(R.append(token), subperms) | |
), tokens); |
const R = require('ramda'); | |
const mapIndexed = R.addIndex(R.map); | |
// transpose :: [[a]] -> [[a]] -- (row, col) becomes (col, row) | |
const transpose = function(matrix) { | |
return mapIndexed(function (_, col) { | |
return R.reject(R.isNil, R.map(R.prop(col), matrix)); | |
}, R.head(matrix)); | |
}; |
var R = require('./ramda'); | |
// Discussion at https://github.com/ramda/ramda/issues/1258 | |
var namedCurry = function(fn, argNames) { | |
// TODO: what if fn.length != argNames.length? | |
var f = R.curryN(fn.length, function() { | |
return fn.apply(this, arguments); | |
}); | |
f['secret-sauce'] = { |
This came out of the recent JS Promises debate. @ForbesLindesay was confused by liftA2, so I thought I’d try to explain it.
Let me explain liftA2. I’ll tweak @pufuwozu’s examples so that they return values.
// Promises (called when both succeed)
liftA2(readFIle('hello.txt'), readFile('world.txt'), function(hello, world) {
return hello + ' ' + world;
});
// Optional values (only inserted into database when both exist)
liftA2(optionalUsername, optionalPassword, function(username, password) {
var transform = function(n) {return 3 * n + 2;} | |
var log = function(n, idx, arr) { | |
return 'n: ' + n + ', idx: ' + idx + ', arr: ' + arr; | |
} | |
console.log('----------------------------------------'); | |
var Fk = require('fkit'); | |
console.log('fkit'); | |
console.log(Fk.compose(Fk.map(log), Fk.map(transform))([0, 1, 2]).join('\n')); |
var transform = function(n) {return 3 * n + 2;}; | |
var log = function(n, idx, obj) { | |
return 'n: ' + n + ', idx: ' + idx + ', obj: ' + obj; | |
}; | |
var Lazy = require('lazy.js'); | |
console.log("lazy.js") | |
console.log(Lazy.range(3).map(transform).map(log).toArray().join('\n')); | |
console.log("----------------------------------------"); |
function lens(get, set) { | |
var f = function (a) { return get(a); }; | |
f.set = set; | |
f.mod = function (f, a) { return set(a, f(get(a))); }; | |
return f; | |
} | |
var first = lens( | |
function (a) { return a[0]; }, | |
function (a, b) { return [b].concat(a.slice(1)); } |
var where = curry(function where(matchThis, testObj) { | |
return ramda.all(function (key) { | |
var val = matchThis[key]; | |
return typeof val == "function" ? val(testObj[key], testObj) : | |
(testObj[key] === matchThis[key]); | |
}, Object.keys(matchThis)); | |
}); | |
x1y2 = where({x: 1, y: 2}); | |
x1y2({x: 1}); //=> false |