js函數式編程術語總結 - 持續更新

来源:https://www.cnblogs.com/zk995/archive/2019/02/19/10400555.html
-Advertisement-
Play Games

程式的冪等性,概念:一個函數執行多次皆返回相同的結果。作用:一個函數被調用多次時,保證內部狀態的一致性 ...


參考文檔1

參考文檔2

函數式編程術語


高階函數 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

程式的冪等性

  • 概念:一個函數執行多次皆返回相同的結果
  • 作用:一個函數被調用多次時,保證內部狀態的一致性
  • 對比:和純函數相比,冪等主要強調多次調用,對內部的狀態的影響是一樣的(但多次調用返回值可能不同)。而純函數,主要強調相同的輸入,多次調用,輸出也相同且無副作用。==純函數一定是冪等的==
  • 意義:在任何可能的情況下通過冪等的操作限制副作用要比不做限制的更新要好得多。確保操作是冪等的,可避免意外的發生
//雖然是一個面向對象的例子,但是可以說明問題
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 風格

  • 定義函數時,不顯式地指出函數所帶參數。這種風格通常需要柯里化或者高階函數。也叫 Tacit programming

斷言函數 Predicate

  • 根據輸入返回 true 或 false。通常用在 Array.prototype.filter 的回調函數中。
const morethenTwo = (a) => a > 2;
;[1, 2, 3, 4].filter(morethenTwo);

契約 Contracts

  • 契約保證了函數或者表達式在運行時的行為。當違反契約時,將拋出一個錯誤
  • 比如數據類型檢測
const contract = (input) => {
  if (typeof input === 'number') return true
  throw new Error('Contract Violated: expected int -> int')
}

const addOne = (num) => contract(num) && num + 1

addOne(2)
addOne('hello') // Error

範疇 Category

【不好理解】

  • 範疇是指,對象(object)及它們之間的態射(箭頭,箭頭可以組合)
  • 在程式中,數據類型作為對象,函數作為態射

【一個範疇遵從三個原則】

  • 必有一個態射(函數),使得 map 一個對象是它自身
  • 態射(函數)必是可組合的
  • 合成滿足結合律。f ? (g ? h) 與 (f ? g) ? h 是等價的

態射 morphism

  • 某一範疇中,對象之前的變換關係(一個變形的函數)

函子 functor(範疇學的內容)

  • 一個實現 map 函數的對象
  • 在 javascript 中一個常見的函子是 Array,因為它遵守因數的兩個準則
  • 一致性 Preserves identity,即範疇的第一個原則
  • 組合性 Composable
  • 示例
//一致性
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

  • 一個具有 of 函數的對象,它將 任何 單獨的值放入其中
  • ES6增加了 Array.of ,使數組成為一個 Pointed Functor
Array.of(1) // [1]

引用透明性 Referential Transparency

  • 定義:一個表達式在程式中可以被它等價的值替換,而不影響結果
  • 對函數而言:如果函數的返回值只依賴於其輸入值,這種特性就稱為引用透明性
  • ==純函數具有引用透明性==
等式推理 Equational Reasoning
  • 指當應用程式由表達式組成,並且沒有副作用時,關於系統的真值可以從各個部分推導出來
  • 純函數式語言的優點之一是易於進行等式推理,通過引用透明度實現,並且能夠在所有上下文中用等號替換equals

不可變性

  • 比如es6中的 const 常量設計

匿名函數 Lambda

  • 匿名函數往往被視作一個值
  • 匿名函數通常作為高階函數的參數
  • 可以把 Lambda 賦值給一個變數

Monad 對象

  • 擁有 of 和 chain 函數的對象。chain 很像 map, 除了用來鋪平嵌套數據
  • 示例,以數組來實現
//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 對象

  • 擁有 extract 與 extend 函數的對象

自同態 Endomorphism

  • 輸入輸出是相同類型的函數
  • 示例:
// uppercase :: String -> String
const uppercase = (str) => str.toUpperCase()
// decrement :: Number -> Number
const decrement = (x) => x - 1

Applicative Functor

  • 一個擁有 ap 函數的對象

同構 Isomorphism

  • 不用類型對象的變形,保持結構並且不丟失數據
  • 例如,一個二維坐標既可以表示為數組 [2, 3],也可以表示為對象 {x: 2, y: 3}
// 提供函數在兩種類型間互相轉換
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 對象

  • 定義:擁有 equals 函數的對象。equals 可以用來和其它對象比較。
Array.prototype.equals = function (arr) {
  const len = this.length
  if (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

  • 定義:一個擁有 concat 函數的對象。concat 可以連接相同類型的兩個對象
  • 示例:比如 Array具有concat方法

Foldable 對象

  • 定義:一個擁有 reduce 函數的對象,reduce 可以把一種類型的對象轉化為另一種類型
  • 示例:將一個list轉為number
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 -> Number
const add = (x) => (y) => x + y
// increment :: Number -> Number
const increment = (x) => x + 1

//如果函數的參數也是函數,那麼這個函數需要用括弧括起來。
// call :: (a -> b) -> a -> b
const 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

  • 由其他類型組合在一起的複合類型。兩種常見的代數類型是 sum 和 product

聯合類型(對象) Union Type

  • 定義:連接不同的數據類型
  • 示例:add就是一個聯合類型對象,因為js天然支持number和sting求和時,進行自動數據類型轉換
// add :: (NumOrString, NumOrString) -> NumOrString
const add = (a, b) => a + b
add(1, 2) // Returns number 3
add('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 類型(有時稱為聯合類型 )

  • 是將兩種類型的組合合併成另一種類型
  • 之所以被稱為 sum ,是因為結果類型中可能的值的數量是輸入類型的總和
  • JavaScript 沒有這樣的類型,但是我們可以使用 Set 來假裝
// 想象一下,在這裡我們不能設置只能具有這些值的類型
const bools = new Set([true, false])
const halfTrue = new Set(['half-true'])
// 弱邏輯類型包含 bools 和 halfTrue 值的總和
const weakLogicValues = new Set([...bools, ...halfTrue])

Option | maybe

  • Option 是一種sum type ,它有兩種情況,Some 或者 None。
  • Option 對於組合可能不返回值的函數很有用
  • 在其它的一些地方,Option 也稱為 Maybe,Some 也稱為 Just,None 也稱為 Nothing

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.常見標簽 2.常見標簽 3.常見標簽 4.列表標簽 ...
  • 一 、數組 1、迭代數組(斐波那契數列迴圈) 2、數組操作 push() //添加元素到數組末尾 unshift() //添加元素到數組首位 pop() //刪除數組最後元素 shift() //刪除數組首位元素 splice(5,3,2,3,4) //從索引5開始刪除3個元素,並開始添加元素2,3 ...
  • css選擇器種類 id選擇器 類選擇器、屬性選擇器、偽類選擇器 元素選擇器、偽元素選擇器 通配符選擇器、子類選擇器、後代選擇器、相鄰兄弟選擇器、選擇器分組 一、id選擇器 二、類選擇器、屬性選擇器、偽類選擇器 1、類選擇器 2、屬性選擇器 3、偽類選擇器 :link 向未被訪問的超鏈接添加樣式 :v ...
  • 2. ...
  • 判斷以下代碼的執行結果(涉及變數提升,函數聲明,原型鏈,this指向,作用域等知識點) "掘金" 上看到的一個筆試題目,記錄並分析總結以下考察點。 第一個 不用說什麼,直接調用Foo構造函數的getName屬性,輸出2。 第二個 調用當前作用域下的getName函數,要註意 函數表達式 和 函數聲明 ...
  • 數組的方法 數組的的大部分方法都可以實現數組的遍歷。 foreach方法 實現數組的遍歷 map方法 map方法的作用:會生成一個與遍歷對象數組相同長度的新數組,並且map中的返回值就是新數組的參數值。 filter方法 過濾,起到篩選的作用。 find方法 includes方法 some方法和ar ...
  • 今天突然看到一篇關於CSS中盒模型的文章,忽然覺得自己竟然遺忘了很多小的地方,所以寫一篇文章來記憶一下 (摘抄於千與千尋寫的CSS盒子模型理解,併在自己基礎上添加了一些東西,希望更完善,對大家有幫助) 1.基本的盒模型知識 CSS css盒子模型 又稱框模型 (Box Model) ,包含了元素內容 ...
  • 靜態資源的請求和載入速度,直接影響頁面呈現,應該怎麼優化呢? ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...