函數(shù)式編程簡析

想要知道什么是函數(shù)式編程就需要先理解什么是編程范式


編程范式是什么?

編程范型、編程范式或程序設(shè)計法(英語:Programming paradigm),(范即模范、典范之意,范式即模式、方法),是一類典型的編程風(fēng)格,是指從事軟件工程的一類 "典型的風(fēng)格(可以對照方法學(xué))"。如:函數(shù)式編程、程序編程、面向?qū)ο缶幊獭⒅噶钍骄幊痰鹊葹椴煌木幊谭缎汀?/p>

提煉概要 編程范式是一種編程思想

編程語言與編程范式的區(qū)別

編程范型和編程語言之間的關(guān)系可能十分復(fù)雜,由于一個編程語言可以支持多種范型。

作為編程語言界的大佬 java 來說在1.8版本 作為最近很火的python 還有 javascript scala 等都有函數(shù)式編程的特點
這里不做過多介紹,參考wiki

函數(shù)式編程的定義

函數(shù)式編程(英語:functional programming)或稱函數(shù)程序設(shè)計,又稱泛函編程,是一種編程典范,它將電腦運算視為數(shù)學(xué)上的函數(shù)計算,并且避免使用程序狀態(tài)以及易變對象。函數(shù)編程語言最重要的基礎(chǔ)是λ演算(lambda calculus)。而且λ演算的函數(shù)可以接受函數(shù)當作輸入(引數(shù))和輸出(傳出值)。
比起指令式編程,函數(shù)式編程更加強調(diào)程序執(zhí)行的結(jié)果而非執(zhí)行的過程,倡導(dǎo)利用若干簡單的執(zhí)行單元讓計算結(jié)果不斷漸進,逐層推導(dǎo)復(fù)雜的運算,而不是設(shè)計一個復(fù)雜的執(zhí)行過程。

函數(shù)式編程發(fā)明的目的

我沒找到,但是根據(jù)網(wǎng)上的蛛絲馬跡,個人推測是為了最開始是簡單,因為最開始是一群數(shù)學(xué)家在玩,現(xiàn)在來看已經(jīng)應(yīng)用于好多方面了。

函數(shù)式編程的基本概念

閉包和高階函數(shù)

函數(shù)編程支持函數(shù)作為第一類對象,有時稱為閉包或者仿函數(shù)(functor)對象。實質(zhì)上,閉包是起函數(shù)的作用并可以像對象一樣操作的對象。與此類似,F(xiàn)P 語言支持高階函數(shù)。高階函數(shù)可以用另一個函數(shù)(間接地,用一個表達式) 作為其輸入?yún)?shù),在某些情況下,它甚至返回一個函數(shù)作為其輸出參數(shù)。這兩種結(jié)構(gòu)結(jié)合在一起使得可以用優(yōu)雅的方式進行模塊化編程,這是使用 FP 的最大好處。 [4]

惰性計算

除了高階函數(shù)和仿函數(shù)(或閉包)的概念,F(xiàn)P 還引入了惰性計算的概念。在惰性計算中,表達式不是在綁定到變量時立即計算,而是在求值程序需要產(chǎn)生表達式的值時進行計算。延遲的計算使您可以編寫可能潛在地生成無窮輸出的函數(shù)。因為不會計算多于程序的其余部分所需要的值,所以不需要擔(dān)心由無窮計算所導(dǎo)致的 out-of-memory 錯誤。一個惰性計算的例子是生成無窮 Fibonacci 列表的函數(shù),但是對第n個Fibonacci 數(shù)的計算相當于只是從可能的無窮列表中提取一項。

遞歸

FP 還有一個特點是用遞歸做為控制流程的機制。例如,Lisp 處理的列表定義為在頭元素后面有子列表,這種表示法使得它自己自然地對更小的子列表不斷遞歸。

函數(shù)式編程具有五個鮮明的特點。

函數(shù)是"第一等公民"

所謂"第一等公民"(first class),指的是函數(shù)與其他數(shù)據(jù)類型一樣,處于平等地位,可以賦值給其他變量,也可以作為參數(shù),傳入另一個函數(shù),或者作為別的函數(shù)的返回值。

舉例來說,下面代碼中的print變量就是一個函數(shù),可以作為另一個函數(shù)的參數(shù)。

var print = function(i){ console.log(i);};
  [1,2,3].forEach(print);

只用"表達式",不用"語句"

"表達式"(expression)是一個單純的運算過程,總是有返回值;"語句"(statement)是執(zhí)行某種操作,沒有返回值。函數(shù)式編程要求,只使用表達式,不使用語句。也就是說,每一步都是單純的運算,而且都有返回值。

原因是函數(shù)式編程的開發(fā)動機,一開始就是為了處理運算(computation),不考慮系統(tǒng)的讀寫(I/O)。"語句"屬于對系統(tǒng)的讀寫操作,所以就被排斥在外。

當然,實際應(yīng)用中,不做I/O是不可能的。因此,編程過程中,函數(shù)式編程只要求把I/O限制到最小,不要有不必要的讀寫行為,保持計算過程的單純性。

沒有"副作用"

所謂"副作用"(side effect),指的是函數(shù)內(nèi)部與外部互動(最典型的情況,就是修改全局變量的值),產(chǎn)生運算以外的其他結(jié)果。

函數(shù)式編程強調(diào)沒有"副作用",意味著函數(shù)要保持獨立,所有功能就是返回一個新的值,沒有其他行為,尤其是不得修改外部變量的值。

不修改狀態(tài)

上一點已經(jīng)提到,函數(shù)式編程只是返回新的值,不修改系統(tǒng)變量。因此,不修改變量,也是它的一個重要特點。

在其他類型的語言中,變量往往用來保存"狀態(tài)"(state)。不修改變量,意味著狀態(tài)不能保存在變量中。函數(shù)式編程使用參數(shù)保存狀態(tài),最好的例子就是遞歸。下面的代碼是一個將字符串逆序排列的函數(shù),它演示了不同的參數(shù)如何決定了運算所處的"狀態(tài)"。

引用透明性

函數(shù)程序通常還加強引用透明性,即如果提供同樣的輸入,那么函數(shù)總是返回同樣的結(jié)果。就是說,表達式的值不依賴于可以改變值的全局狀態(tài)。這使您可以從形式上推斷程序行為,因為表達式的意義只取決于其子表達式而不是計算順序或者其他表達式的副作用。這有助于驗證正確性、簡化算法,甚至有助于找出優(yōu)化它的方法。

副作用

副作用是修改系統(tǒng)狀態(tài)的語言結(jié)構(gòu)。因為 FP 語言不包含任何賦值語句,變量值一旦被指派就永遠不會改變。而且,調(diào)用函數(shù)只會計算出結(jié)果 ── 不會出現(xiàn)其他效果。因此,F(xiàn)P 語言沒有副作用。

函數(shù)式編程的優(yōu)點

① 代碼簡介,開發(fā)快速
② 接近自然語言,易于理解
③ 更方便的代碼管理 (函數(shù)式編程不依賴、也不會改變外界的狀態(tài),只要給定輸入?yún)?shù),返回的結(jié)果必定相同。因此,每一個函數(shù)都可以被看做獨立單元,很有利于進行單元測試(unit testing)和除錯(debugging),以及模塊化組合。)

按照百度百科的定義在我看來這就是程序運行的可再現(xiàn)性

④代碼的熱升級 這點不是很理解

函數(shù)式編程的缺點

函數(shù)式編程常被認為嚴重耗費CPU和存儲器資源。主因有二:

  • 在實現(xiàn)早期的函數(shù)式編程語言時并沒有考慮過效率問題。
  • 面向函數(shù)式編程特性(如保證函數(shù)參數(shù)不變性等)的獨特數(shù)據(jù)結(jié)構(gòu)和算法。
函數(shù)式編程的應(yīng)用

函數(shù)式編程的 不可變狀態(tài)、閉包和高階函數(shù)等概念,在對于編寫高度并發(fā)和分布式應(yīng)用程序而言,它們非常適合

  • WhatsApp 僅通過50個使用 Erlang 的開發(fā)工程師,就能夠支持9億的用戶;

  • Discord 以類似的方式使用 Elixir 處理每分鐘超過一百萬次的請求;

總結(jié)

就目前來看 隨著大數(shù)據(jù)、機器學(xué)習(xí)的發(fā)展,函數(shù)式編程已經(jīng)開始普及開來,高效快速的開發(fā),并發(fā)編程,都出現(xiàn)它的身影,這種思想未來結(jié)合其他的編程范式,讓開發(fā)變得更簡單高效,但是也不會取代底層的開發(fā),可能會出現(xiàn)兩極化的現(xiàn)象,只有熟悉了解其中的原理,目的才能能好的利用其特性做最優(yōu)效的開發(fā)

參考:

百度百科:函數(shù)式編程
wiki:函數(shù)式編程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容