函数式编程术语解析

开发 前端
一个纯函数需要满足两个条件,第一是函数的返回值只能由输入值(函数接收的参数)决定,也就是说纯函数接收相同的参数会返回相同的值;第二是纯函数不会对自身作用域之外的运环境产生副作用(side effects)。

[[174906]]

Arity

指函数的参数数量,由 -ary 和 -ity 这两个英文后缀拼接而成:

  1. const sum = (a, b) => a + b; 
  2. const Arity = sum.length; 
  3. console.log(Arity); 
  4. // 输出结果为 2  

Higher-Order Functions

高阶函数,此类函数可以接收其他函数作为参数,也可以返回一个函数作为返回值:

  1. const filter = (predFunc, list) => { 
  2.   const results = []; 
  3.   list.forEach((listItem) => { 
  4.     if (predFunc(listItem)) { 
  5.       results.push(listItem); 
  6.     } 
  7.   }); 
  8.   return results; 
  9. // filter 这个函数就是将一个函数作为参数传入 
  10. // 但这都么有什么,主要是后面is函数返回一个函数 
  11.  
  12. const is = (type) => (x) => Object(x) instanceof type; 
  13. // is这个函数就是将一个函数作为返回值返回到下面的调用之中 
  14.  
  15. filter(is(Number), [0, '1', 2, null]); 
  16. // 上面函数调用的结果是 [0, 2]  

Partial Application

偏函数,在原函数的基础上预填充(pre-filling)部分参数并返回的新函数:

  1. // 下面是一个创建偏函数的辅助函数,下面函数将一个函数和这个函数所需要 
  2. // 的除了***一个参数的参数传入,返回一个新的函数,这个新的函数的参数为原 
  3. // 函数的***一个参数 
  4. const partial = (func, ...args) => (...moreArgs) => func(...args, ...moreArgs); 
  5. // 写一个将三个数字相加的函数 
  6. const add3 = (a, b, c) => a + b + c; 
  7. // 预填充 (add3, 2, 3) 三个参数,空置***一个参数,返回一个新的函数,重点是返回一个新的函数 
  8. const fivePlus = partial(add3, 2, 3); // (c) => 2 + 3 + c 
  9. fivePlus(4); 
  10. // => 9  

Currying

柯里化,将一个接收多个参数的函数转化为单参数函数的方式,转化后的函数每次只接收一个参数,然后返回一个新函数,新函数可以继续接收参数,直到接收到所有的参数:

  1. const sum = (a, b) => a + b; 
  2. sum(2, 3); 
  3. // => 6 
  4. const curriedSum = (a) => (b) => a + b; 
  5. curriedSum(40)(2); 
  6. // => 42. 
  7. const add2 = curriedSum(2); 
  8. // (b) => 2 + b 
  9. add2(10); 
  10. // => 12  

Function Composition

函数合成,接收多个函数作为参数并返回一个新函数的方式,新函数按照传入的参数顺序,从右往左依次执行,前一个函数的返回值是后一个函数的输入值:

  1. const compose = (f, g) => (a) => f(g(a)); 
  2. const floorAndToString = compose((val) => val.toString(), Math.floor); 
  3. floorAndToString(121.212121); 
  4. // => "121"  

Purity

一个纯函数需要满足两个条件,***是函数的返回值只能由输入值(函数接收的参数)决定,也就是说纯函数接收相同的参数会返回相同的值;第二是纯函数不会对自身作用域之外的运环境产生副作用(side effects),比如说不会改变外部环境中变量的值,这会被认为是不安全的行为:纯函数示例:

  1. const greet = (name) => "Hi, " + name ; 
  2. greet("Brianne"
  3. // => "Hi, Brianne"  

Side effects

如果函数或表达式与其自身作用域之外的可变数据(mutable data)发生了读写操作,那么此时函数和表达式就产生了副作用:

  1. let greeting; 
  2. const greet = () => greeting = "Hi, " + window.name
  3. // greet() 执行时更改了外部环境的变量 
  4. greet(); 
  5. // => "Hi, Brianne" 
  6. // new Date() 是可变数据 
  7. const differentEveryTime = new Date();  

Point-Free Style

point-free style 是一种不显式向函数传递参数的代码风格,通常需要柯里化和高阶函数来实现:

  1. const map = (fn) => (list) => list.map(fn); 
  2. const add = (a) => (b) => a + b; 
  3. // Not points-free 
  4. // numbers 是一个显式传递的参数 
  5. const incrementAll = (numbers) => map(add(1))(numbers); 
  6. // Points-free 
  7. // add(1) 的返回值隐式传递给了 map,作为 map 的 list 参数 
  8. const incrementAll2 = map(add(1));  

Predicate

断言,一个返回布尔值的函数:

  1. const predicate = (a) => a > 2; 
  2. [1, 2, 3, 4].filter(predicate); 
  3. // => [3, 4]  

Constant

常量,初始化后不能再次执行赋值操作的数据类型:

  1. const five = 5; 
  2. const john = { name'John', age: 30 }; 
  3. // 因为常量不可变,所以下面表达式一定为 true 
  4. john.age + five === ({ name'John', age: 30 }).age + (5);  

常量具有 referentially transparent 的特性,也就是说将程序中出现的常量替换为它们实际的值,并不会影响程序的结果。译者话外:实际上在 JavaScript 中的 const 所声明的常量并不是完全稳定的,使用 Immutable.js 演示更加恰当:

  1. // 这里的fromJS(), get()函数都是immutable.js所提供的方法 
  2. const five = fromJS(5); 
  3. const john = fromJS({name'John', age: 30}); 
  4. john.get('age') + five === ({ name'John', age: 30 }).age + (5);  

Functor

functor 都拥有 map 函数,并且在执行 map 之后会返回一个新的 functor:

  1. object.map(x => x) === object; 
  2.  
  3. object.map(x => f(g(x))) === object.map(g).map(f);  

JavaScript 中最常见的 functor 就是数组类型的实例:

  1. [1, 2, 3].map(x => x); 
  2. // => [1, 2, 3] 
  3. const f = x => x + 1; 
  4. const g = x => x * 2; 
  5. [1, 2, 3].map(x => f(g(x))); 
  6. // => [3, 5, 7] 
  7. [1, 2, 3].map(g).map(f);      
  8. // => [3, 5, 7]  

Lift

lift 发生在你将值放入 functor 的时候,如果你将函数 lift 进了 Applicative Functor,那么就可以使用这个函数处理传递给这个 functor 的值。某些 lift 的实现拥有 lift 或 liftA2 函数,便于在 functor 上执行相关的函数:

  1. const mult = (a, b) => a * b; 
  2. const liftedMult = lift(mult); 
  3. // => this function now works on functors like array 
  4. liftedMult([1, 2], [3]); 
  5. // => [3, 6] 
  6. lift((a, b) => a + b)([1, 2], [3, 4]); 
  7. // => [4, 5, 5, 6]  

lift 一个单参数的函数非常类似于 map 操作:

  1. const increment = (x) => x + 1; 
  2. lift(increment)([2]); 
  3. // => [3] 
  4. [2].map(increment); 
  5. // => [3]  
责任编辑:庞桂玉 来源: segmentfault
相关推荐

2013-09-09 09:41:34

2011-08-24 09:13:40

编程

2023-12-14 15:31:43

函数式编程python编程

2022-09-22 08:19:26

WebFlux函数式编程

2011-03-08 15:47:32

函数式编程

2020-09-24 10:57:12

编程函数式前端

2017-06-08 14:25:46

Kotlin函数

2010-11-25 09:06:37

Web开发函数式编程

2009-11-19 13:15:09

UPS专业术语

2020-09-22 11:00:11

Java技术开发

2016-08-11 10:11:07

JavaScript函数编程

2016-08-11 10:34:37

Javascript函数编程

2020-09-23 07:50:45

Java函数式编程

2010-03-11 10:34:22

Scala

2012-09-21 09:21:44

函数式编程函数式语言编程

2022-07-07 09:03:36

Python返回函数匿名函数

2019-09-09 11:40:18

编程函数开发

2021-10-09 11:17:54

前端函数编程

2017-03-22 11:22:04

JavaScript函数式编程

2011-10-19 15:47:13

点赞
收藏

51CTO技术栈公众号