JS 之函数式编程术语总结
大家好,我是你们的导师,我每天都会在这里给大家分享一些干货内容(当然了,周末也要允许老师休息一下哈)。上次老师跟大家分享了JS 之工具函数的知识,今天跟大家分享下JS 之函数式编程术语总结的知识。
参考文献:http://www.fly63.com/article/detial/2097
const filter = (predicate, xs) => xs.filter(predicate)const is = (type) => (x) => Object(x) instanceof typefilter(is(Number), [0, '1', 2, null]) // [0, 2]
函数的元 Arity
const sum = (a, b) => a + bconst arity = sum.lengthconsole.log(arity) // 2// The arity of sum is 2
惰性求值 Lazy evaluation
// 设置一个随机数,需要时,才会计算,每次计算都是一个不同的值const rand = function*() {while (1 < 2) {yield Math.random()}}const randIter = rand()randIter.next() // 每个执行都给出一个随机值,表达式按需求值。
偏函数 Partial Application
function add(a, b,c) {return a + b+c;}//也可以var addOne = add.bind(null, 1,2);console.log(addOne(2));//也可以var addTwo = add.bind(null, 1);console.log(addTwo(3,4));
柯里化 Currying
const sum = (a, b) => a + bconst curriedSum = (a) => (b) => a + bcurriedSum(40)(2) // 42.const add2 = curriedSum(2) // (b) => 2 + badd2(10) // 12
自动柯里化 Auto Currying
const add = (x, y) => x + yconst curriedAdd = _.curry(add)curriedAdd(1, 2) // 3curriedAdd(1) // (y) => 1 + ycurriedAdd(1)(2) // 3
compose 组合函数
var compose = function(fun1,fun2){return function(val){return fun1(fun2(val));}}var add = function(val){return val + "111";}var upperCase = function(val){return val.toUpperCase();}var double = function(val){return val += val;}// 无限组合,才是compose的威力所在var upperCaseThenAdd = compose(add,upperCase);var doubleThenAdd = compose(double,add);var addThenAdd = compose(add,add);var addThenAddThenUpperCase = compose(upperCase,addThenAdd);//注意这个函数,以组合函数addThenAdd作为其参数,很强大,有没有!console.log(upperCaseThenAdd("china"));//CHINA111console.log(doubleThenAdd("china"));//china111china111console.log(addThenAdd("china"));//china111111console.log(addThenAddThenUpperCase("china"));//CHINA111111//改进compose,支持2个以上参数var compose1 = function(){var args = arguments;return function(initVal){var val = initVal;for(key in args){val = args[key](val);}return val;}}var doubleThenUpperCaseThenAddThenAdd = compose1(double,upperCase,add,add);console.log(doubleThenUpperCaseThenAddThenAdd("china"));//CHINACHINA111111
Continuation
//continueFun函数就称为一个Continuationvar addOneAndContinue = function(val,continueFun){var val = val + 1;return continueFun(val);}var mutiply = function(val){return val * 5;}console.log(addOneAndContinue(100,mutiply));//505
纯函数 Purity
const greet = (name) => `Hi, ${name}`greet('Brianne') // 'Hi, Brianne'
window.name = 'Brianne'const greet = () => `Hi, ${window.name}`greet() // "Hi, Brianne"
let greetingconst greet = (name) => {greeting = `Hi, ${name}`}greet('Brianne')greeting // "Hi, Brianne"
副作用 Side effects
const differentEveryTime = new Date()console.log('IO is a side effect!')
幂等性 Idempotent
GET /pageX HTTP/1.1是幂等的。连续调用多次,客户端接收到的结果都是一样的:GET /pageX HTTP/1.1GET /pageX HTTP/1.1GET /pageX HTTP/1.1GET /pageX HTTP/1.1POST /add_row HTTP/1.1不是幂等的。如果调用多次,就会增加多行记录:POST /add_row HTTP/1.1POST /add_row HTTP/1.1 -> Adds a 2nd rowPOST /add_row HTTP/1.1 -> Adds a 3rd rowDELETE /idX/delete HTTP/1.1是幂等的,即便是不同请求之间接收到的状态码不一样:DELETE /idX/delete HTTP/1.1 -> Returns 200 if idX existsDELETE /idX/delete HTTP/1.1 -> Returns 404 as it just got deletedDELETE /idX/delete HTTP/1.1 -> Returns 404
//虽然是一个面向对象的例子,但是可以说明问题var Student = function(name,age){this.name = name;this.age = age;};Student.prototype.delName = function(){var response = this.name ? this.name + "已被删除":"name不存在";this.name = null;return response;}//对内部的影响是一样的,但是返回值可以不同var lilei = new Student("lilei",19);console.log(lilei.delName());//lilei已被删除console.log(lilei.delName());//name不存在console.log(lilei.delName());//name不存在
Point-Free 风格
// 给定const map = (fn) => (list) => list.map(fn)const add = (a) => (b) => a + b// 然后// 非 points-free - `numbers` 是一个明确的参数const incrementAll = (numbers) => map(add(1))(numbers)// Points-free - `list` 显式地标识const incrementAll2 = map(add(1))
断言函数 Predicate
const morethenTwo = (a) => a > 2;;[1, 2, 3, 4].filter(morethenTwo);
契约 Contracts
const contract = (input) => {if (typeof input === 'number') return truethrow new Error('Contract Violated: expected int -> int')}const addOne = (num) => contract(num) && num + 1addOne(2)addOne('hello') // Error
范畴 Category
态射 morphism
函子 functor(范畴学的内容)
//一致性object.map(x => x) ? object//组合性var fun1 = function(x){return x+1;}var fun2 = function(x){return x*x;}var res1 = [1,2,3].map(fun1).map(fun2);var res2 = [1,2,3].map(function(x){return fun2(fun1(x));});console.log(res1,res2);
Pointed Functor
Array.of(1) // [1]
引用透明性 Referential Transparency
等式推理 Equational Reasoning
不可变性
Object.freeze({name: 'John', age: 30}) // `freeze` 强制实现不可变性。const name="haha"
匿名函数 Lambda
;(function (a) {return a + 1});(a) => a + 1
;[1, 2].map((a) => a + 1) // [2, 3]
const add1 = (a) => a + 1
Monad 对象
//of
Array.of(1,2,3);//[ 1, 2, 3 ]
//chain方法的实现
Array.prototype.chain = function (f) {
return this.reduce((acc, it) => acc.concat(f(it)), [])
};
Array.of('cat,dog', 'fish,bird').chain(s => s.split(','));//[ "cat", "dog", "fish", "bird" ]
Comonad 对象
const CoIdentity = (v) => ({val: v,extract () {return this.val},extend (f) {return CoIdentity(f(this))}})
CoIdentity(1).extract() // 1
CoIdentity(1).extend((co) => co.extract() + 1) // CoIdentity(2)
自同态 Endomorphism
// uppercase :: String -> Stringconst uppercase = (str) => str.toUpperCase()// decrement :: Number -> Numberconst decrement = (x) => x - 1
Applicative Functor
// 实现Array.prototype.ap = function (xs) {return this.reduce((acc, f) => acc.concat(xs.map(f)), [])}// 使用示例;[(a) => a + 1].ap([1]) // [2]
// 你想合成的数组const arg1 = [1, 3]const arg2 = [4, 5]// 合成函数 - 必须为此 curried 柯里化 才能工作const add = (x) => (y) => x + yconst partiallyAppliedAdds = [add].ap(arg1) // [(y) => 1 + y, (y) => 3 + y]
partiallyAppliedAdds.ap(arg2) // [5, 6, 7, 8]
同构 Isomorphism
// 提供函数在两种类型间互相转换const pairToCoords = (pair) => ({x: pair[0], y: pair[1]})const coordsToPair = (coords) => [coords.x, coords.y]console.log(pairToCoords([1, 2]));//{ "x": 1, "y": 2 }console.log(coordsToPair({x: 1, y: 2}));//[ 1, 2 ]
Setoid 对象
Array.prototype.equals = function (arr) {const len = this.lengthif (len !== arr.length) {return false}for (let i = 0; i < len; i++) {if (this[i] !== arr[i]) {return false}}return true};[1, 2].equals([1, 2]) // true;[1, 2].equals([3, 4]) // false
半群 Semigroup
;[1].concat([2]) // [1, 2]
Foldable 对象
var sum = [1,2,3,4].reduce(function(total,val){return total += val;})console.log(sum);
类型签名 Type Signatures
//通常 js 会在注释中指出参数与返回值的类型// functionName :: firstArgType -> secondArgType -> returnType// add :: Number -> Number -> Numberconst add = (x) => (y) => x + y// increment :: Number -> Numberconst increment = (x) => x + 1//如果函数的参数也是函数,那么这个函数需要用括号括起来。// call :: (a -> b) -> a -> bconst call = (f) => (x) => f(x)//字符 a, b, c, d 表明参数可以是任意类型。以下版本的 map 的参数 f,把一种类型 a 的数组转化为另一种类型 b 的数组。// map :: (a -> b) -> [a] -> [b]const map = (f) => (list) => list.map(f)
代数数据类型 Algebraic data type
联合类型(对象) Union Type
// add :: (NumOrString, NumOrString) -> NumOrStringconst add = (a, b) => a + badd(1, 2) // Returns number 3add('Foo', 2) // Returns string "Foo2"add('Foo', 'Bar') // Returns string "FooBar"
Product type
// point :: (Number, Number) -> {x: Number, y: Number}const point = (x, y) => ({x: x, y: y})
Sum 类型(有时称为联合类型 )
// 想象一下,在这里我们不能设置只能具有这些值的类型const bools = new Set([true, false])const halfTrue = new Set(['half-true'])// 弱逻辑类型包含 bools 和 halfTrue 值的总和const weakLogicValues = new Set([...bools, ...halfTrue])
Option | maybe
闭包 Closure
const addTo = x => y => x + yvar addToFive = addTo(5)addToFive(3) // returns 8
