函數式編程術語
高階函數 Higher-Order Functions
以函數爲參數的函數
返回一個函數的函數
函數的元 Arity
比如,一個帶有兩個參數的函數被稱爲二元函數
惰性求值 Lazy evaluation
是一種按需求值機制,它會延遲對表達式的求值,直到其需要爲止
// 設置一個隨機數,需要時,纔會計算,每次計算都是一個不同的值
const rand = function*() {
while (1 < 2) {
yield Math.random()
}
}
const randIter = rand()
randIter.next() // 每個執行都給出一個隨機值,表達式按需求值。
偏函數 Partial Application
即【降元】,將一個 n 元函數轉換成一個 n - x 元函數
或者這樣理解,通過對【複雜的函數】填充一部分數據來構成一個【簡單的函數】
柯里化就是通過偏應用函數來實現
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
將一個多參數函數轉換成多個單參數函數
也就是將一個 n 元函數轉換成 n 個一元函數
const sum = (a, b) => a + b
const curriedSum = (a) => (b) => a + b
curriedSum(40)(2) // 42.
const add2 = curriedSum(2) // (b) => 2 + b
add2(10) // 12
自動柯里化 Auto Currying
將多個參數的函數轉換爲單參數的函數
如果,給定的參數數量少於正確的參數,則返回一個函數,該函數將獲得其餘的參數
如果,函數得到正確數量的參數時,它就會被求值
示例,lodash 和 Ramda 都有一個 curry 函數,但 underscore 沒有
const add = (x, y) => x + y
const curriedAdd = _.curry(add)
curriedAdd(1, 2) // 3
curriedAdd(1) // (y) => 1 + y
curriedAdd(1)(2) // 3
compose 組合函數
概念:它將需要嵌套執行的函數平鋪。嵌套執行指的是,一個函數的返回值將作爲另一個函數的參數
作用:實現函數式編程中的 pointfree 風格(無參數),使我們專注於【轉換】而不是【數據】
實現:接收多個函數作爲參數,從右到左,一個函數的輸入爲另一個函數的輸出
意義:編程更精練、算法更清晰、無參數干擾
威力:==【任意組合】==
缺點:不能直觀的看到參數
示例
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"));//CHINA111
console.log(doubleThenAdd("china"));//china111china111
console.log(addThenAdd("china"));//china111111
console.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
概念:在一個程序執行的任意時刻,尚未執行的代碼稱爲 Continuation
作用:異步請求回調、異步監聽回調等
示例
//continueFun函數就稱爲一個Continuation
var 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
輸出僅由輸入決定,不依賴也不修改外部狀態,即不產生副作用
副作用 Side effects
如果函數與外部可變狀態進行交互,則它是有副作用的
冪等性 Idempotent
數學中的冪等性
foo(x) 將產生與 foo(foo(x))、foo(foo(foo(x))) 等相同的輸出
[二元運算],它需要三個元素:二元運算符以及該運算符作用的兩個變量。如四則運算的加、減、乘、除均屬於二元運算。乘法下唯一兩個冪等實數爲0和1
[一元運算],例如 ++ ,正+,負-。比如[高斯符號],它是一個數學符號,形式爲方括號[x],表示不大於x的最大整數,高斯符號是冪等的
接口的冪等性
對接口而言,冪等性實際上就是接口可重複調用,在調用方多次調用的情況下,接口最終得到的結果是一致的。比如,在App中下訂單的時候,點擊確認之後,沒反應,就又點擊了幾次。在這種情況下,如果無法保證該接口的冪等性,那麼將會出現重複下單問題
[http方法的冪等],指的是同樣的請求被執行一次與連續執行多次的效果是一樣的,服務器的狀態也是一樣的(注意,只是服務器狀態,和服務器返回狀態無關)
舉例
GET /pageX HTTP/1.1是冪等的。連續調用多次,客戶端接收到的結果都是一樣的:
GET /pageX HTTP/1.1
GET /pageX HTTP/1.1
GET /pageX HTTP/1.1
GET /pageX HTTP/1.1
POST /add_row HTTP/1.1不是冪等的。如果調用多次,就會增加多行記錄:
POST /add_row HTTP/1.1
POST /add_row HTTP/1.1 -> Adds a 2nd row
POST /add_row HTTP/1.1 -> Adds a 3rd row
DELETE /idX/delete HTTP/1.1是冪等的,即便是不同請求之間接收到的狀態碼不一樣:
DELETE /idX/delete HTTP/1.1 -> Returns 200 if idX exists
DELETE /idX/delete HTTP/1.1 -> Returns 404 as it just got deleted
DELETE /idX/delete HTTP/1.1 -> Returns 404
程序的冪等性
概念:一個函數執行多次皆返回相同的結果
作用:一個函數被調用多次時,保證內部狀態的一致性
對比:和純函數相比,冪等主要強調多次調用,對內部的狀態的影響是一樣的(但多次調用返回值可能不同)。而純函數,主要強調相同的輸入,多次調用,輸出也相同且無副作用。==純函數一定是冪等的==
意義:在任何可能的情況下通過冪等的操作限制副作用要比不做限制的更新要好得多。確保操作是冪等的,可避免意外的發生 鄭州婦科醫院:https://yyk.familydoctor.com.cn/21206/鄭州人流醫院×××:https://yyk.familydoctor.com.cn/21206/鄭州看婦科那家好:https://yyk.familydoctor.com.cn/21206/鄭州同濟婦科醫院:https://yyk.familydoctor.com.cn/21206/