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 |