一些常用到的函数式编程术语及讲解
Arity 函数的参数数量
指函数的参数数量,由 -ary 和 -ity 这两个英文后缀拼接而成:
js
const sum = (a, b) => a + b
const arity = sum.length
// arity -> 2Higher-Order Functions 高阶函数
此类函数可以接收其他函数作为参数,也可以返回一个函数作为返回值:
js
const filter = (pred, xs) => {
const result = []
for (let idx = 0; idx < xs.length; idx++) {
if (pred(xs[idx])) {
result.push(xs[idx])
}
}
return result
}
const is = (type) => (x) => Object(x) instanceof typePartial Application 偏函数
在原函数的基础上预填充(pre-filling)部分参数并返回的新函数:
js
const partial =
(f, ...args) =>
(...moreArgs) =>
f(...args, ...moreArgs)
const add3 = (a, b, c) => a + b + c
// 预填充 (add3, 2, 3) 三个参数,空置最后一个参数,返回一个新的函数
const fivePlus = partial(add3, 2, 3) // (c) => 2+3+cCurrying 柯里化
将一个接收多个参数的函数转化为单参数函数的方式,转化后的函数每次只接收一个参数,然后返回一个新函数,新函数可以继续接收参数,直到接收到所有的参数:
js
const sum = (a, b) => a + b
sum(2, 3)
const curriedSum = (a) => (b) => a + b
curriedSum(4)(5) // 9
const add2 = curriedSum(9)
add2(1) // 10Function Composition 函数合成
接收多个函数作为参数并返回一个新函数的方式,新函数按照传入的参数顺序,从右往左依次执行,前一个函数的返回值是后一个函数的输入值:
js
const compose = (f, g) => (a) => f(g(a))
const floorAndToString = compose((val) => val.toString(), Math.floor)Purity 纯函数
一个纯函数需要满足两个条件,第一是函数的返回值只能由输入值(函数接收的参数)决定,也就是说纯函数接收相同的参数会返回相同的值;第二是纯函数不会对自身作用域之外的运行环境产生副作用(side effects),比如说不会改变外部环境中变量的值,这会被认为是不安全的行为:
js
let greeting
const greet = () => (greeting = `Hi, ${window.name}`)
// greet(); 执行更改了外部环境变量
// 纯函数示例:
const greet = (name) => `Hi, ${name}`
greet('fri')Side effects 副作用
如果函数或表达式与其自身作用域之外的可变数据(mutable data)发生了读写操作,那么此时函数和表达式就产生了副作用:
js
let greeting
const greet = () => (greeting = `Hi, ${window.name}`)
// greet(); 执行更改了外部环境的变量
// new Date() 是可变数据
const differentEveryTime = new Date()
// 则合理表示系统接收到的输入值是不确定的,是一种可变数据
console.log('IO is a side effect!')Idempotent 幂等
同一个函数使用相同的参数嵌套执行多次的结果与执行一次的结果相同:
js
Math.abs(Math.abs(10))
sort(sort([2, 1]))Point-Free Style
point-free style 是一种不显式向函数传递参数的代码风格,通常需要柯里化和高阶函数来实现:
js
const map = (fn) => (list) => list.map(fn)
const add = (a) => (b) => a + b
// Not Points-free
// numbers是一个显示传递的参数
const incrementAll = (numbers) => map(add(1))(numbers)
// Points-free
// add(1)的返回值隐式地传递给了map, 作为map的list参数
const incrementAll2 = map(add(1))point-free style 的函数看起来就像是一个赋值表达式,没有使用我们常见的 function 或 => 等来声明其接收的参数。
Categories
内部都绑定了具体的函数用于约束或执行特定的逻辑
Value
任何可以赋值给变量的值都可以成为 value
Constant
常量,初始化后不能再次执行赋值操作的数据类型
常量具有 referentially transparent 的特性,也就是说将程序中出现的常量替换为它们实际的值,并不会影响程序的结果。
