成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

編程范式與函數(shù)式編程

noONE / 3418人閱讀

摘要:聲明式編程一種編程范式,與命令式編程相對(duì)立。常見(jiàn)的聲明式編程語(yǔ)言有數(shù)據(jù)庫(kù)查詢語(yǔ)言,正則表達(dá)式邏輯編程函數(shù)式編程組態(tài)管理系統(tǒng)等。函數(shù)式編程,特別是純函數(shù)式編程,嘗試最小化狀態(tài)帶來(lái)的副作用,因此被認(rèn)為是聲明式的。

編程范式與函數(shù)式編程 一、編程范式的分類

常見(jiàn)的編程范式有:函數(shù)式編程、程序編程、面向?qū)ο缶幊?、指令式編程等。在面向?qū)ο缶幊痰氖澜纾绦蚴且幌盗邢嗷プ饔茫ǚ椒ǎ┑膶?duì)象(Class Instances),而在函數(shù)式編程的世界,程序會(huì)是一個(gè)無(wú)狀態(tài)的函數(shù)組合序列。不同的編程語(yǔ)言也會(huì)提倡不同的“編程范型”。一些語(yǔ)言是專門為某個(gè)特定的范型設(shè)計(jì)的,如Smalltalk和Java支持面向?qū)ο缶幊?。而Haskell和Scheme則支持函數(shù)式編程。現(xiàn)代編程語(yǔ)言的發(fā)展趨勢(shì)是支持多種范型,如 C#、Java 8+、Kotlin、 Scala、ES6+ 等等。

與成百種編程語(yǔ)言相比,編程范式要少得多。多數(shù)范式之間僅相差一個(gè)或幾個(gè)概念,比如函數(shù)編程范式,在加入了狀態(tài)(state)之后就變成了面向?qū)ο缶幊谭妒健?/p>

雖然范式有很多種,但是可以簡(jiǎn)單分為三類:

1.命令式編程(Imperative programming)

計(jì)算機(jī)的硬件負(fù)責(zé)運(yùn)行使用命令式的風(fēng)格來(lái)寫(xiě)的機(jī)器碼。計(jì)算機(jī)硬件的工作方式基本上都是命令式的。大部分的編程語(yǔ)言都是基于命令式的。高級(jí)語(yǔ)言通常都支持四種基本的語(yǔ)句:

(1)運(yùn)算語(yǔ)句
一般來(lái)說(shuō)都表現(xiàn)了在存儲(chǔ)器內(nèi)的數(shù)據(jù)進(jìn)行運(yùn)算的行為,然后將結(jié)果存入存儲(chǔ)器中以便日后使用。高階命令式編程語(yǔ)言更能處理復(fù)雜的表達(dá)式,產(chǎn)生四則運(yùn)算和函數(shù)計(jì)算的結(jié)合。

(2)循環(huán)語(yǔ)句
容許一些語(yǔ)句反復(fù)運(yùn)行數(shù)次。循環(huán)可依據(jù)一個(gè)默認(rèn)的數(shù)目來(lái)決定運(yùn)行這些語(yǔ)句的次數(shù);或反復(fù)運(yùn)行它們,直至某些條件改變。

(3)條件分支
容許僅當(dāng)某些條件成立時(shí)才運(yùn)行某個(gè)區(qū)塊。否則,這個(gè)區(qū)塊中的語(yǔ)句會(huì)略去,然后按區(qū)塊后的語(yǔ)句繼續(xù)運(yùn)行。

(4)無(wú)條件分支
容許運(yùn)行順序轉(zhuǎn)移到程序的其他部分之中。包括跳躍(在很多語(yǔ)言中稱為Goto)、副程序和Procedure等。

循環(huán)、條件分支和無(wú)條件分支都是控制流程。
早期的命令式編程語(yǔ)言,例如匯編,都是機(jī)器指令。雖然硬件的運(yùn)行更容易,卻阻礙了復(fù)雜程序的設(shè)計(jì)。

2.面向?qū)ο缶幊蹋ㄔ幊蹋∣bject-oriented programming,OOP)

怎樣為一個(gè)模糊不清的問(wèn)題找到一個(gè)最恰當(dāng)?shù)拿枋觯▎?wèn)題描述)? 抽象(Abstraction)通常是我們用來(lái)簡(jiǎn)化復(fù)雜的現(xiàn)實(shí)問(wèn)題的方法。在面向?qū)ο蟪绦蚓幊汤?,?jì)算機(jī)程序會(huì)被設(shè)計(jì)成彼此相關(guān)的對(duì)象。對(duì)象則指的是類的實(shí)例。它將對(duì)象作為程序的基本單元,將程序和數(shù)據(jù)封裝其中,以提高軟件的重用性、靈活性和擴(kuò)展性,對(duì)象里的程序可以訪問(wèn)及經(jīng)常修改對(duì)象相關(guān)連的數(shù)據(jù)。對(duì)象包含數(shù)據(jù)(字段、屬性)與方法。

面向?qū)ο蟪绦蛟O(shè)計(jì)可以看作一種在程序中包含各種獨(dú)立而又互相調(diào)用的對(duì)象的思想,這與傳統(tǒng)的思想剛好相反:傳統(tǒng)的程序設(shè)計(jì)主張將程序看作一系列函數(shù)的集合,或者直接就是一系列對(duì)計(jì)算機(jī)下達(dá)的指令。面向?qū)ο蟪绦蛟O(shè)計(jì)中的每一個(gè)對(duì)象都應(yīng)該能夠接受數(shù)據(jù)、處理數(shù)據(jù)并將數(shù)據(jù)傳達(dá)給其它對(duì)象,因此它們都可以被看作一個(gè)小型的“機(jī)器”,即對(duì)象。目前已經(jīng)被證實(shí)的是,面向?qū)ο蟪绦蛟O(shè)計(jì)推廣了程序的靈活性和可維護(hù)性,并且在大型項(xiàng)目設(shè)計(jì)中廣為應(yīng)用。此外,支持者聲稱面向?qū)ο蟪绦蛟O(shè)計(jì)要比以往的做法更加便于學(xué)習(xí),因?yàn)樗軌蜃屓藗兏?jiǎn)單地設(shè)計(jì)并維護(hù)程序,使得程序更加便于分析、設(shè)計(jì)、理解。反對(duì)者在某些領(lǐng)域?qū)Υ擞枰苑裾J(rèn)。

當(dāng)我們提到面向?qū)ο蟮臅r(shí)候,它不僅指一種程序設(shè)計(jì)方法。它更多意義上是一種程序開(kāi)發(fā)方式。在這一方面,我們必須了解更多關(guān)于面向?qū)ο笙到y(tǒng)分析和面向?qū)ο笤O(shè)計(jì)(Object Oriented Design,簡(jiǎn)稱OOD)方面的知識(shí)。許多流行的編程語(yǔ)言是面向?qū)ο蟮?它們的風(fēng)格就是會(huì)透由對(duì)象來(lái)創(chuàng)出實(shí)例。重要的面向?qū)ο缶幊陶Z(yǔ)言包含Common Lisp、Python、C++、Objective-C、Smalltalk、Delphi、Java、Swift、C#、Perl、Ruby 與 PHP等。面向?qū)ο缶幊讨?,通常利用繼承父類,以實(shí)現(xiàn)代碼重用和可擴(kuò)展性。

3.聲明式編程(Declarative programming)

一種編程范式,與命令式編程相對(duì)立。它描述目標(biāo)的性質(zhì),讓計(jì)算機(jī)明白目標(biāo),而非具體過(guò)程。聲明式編程不用告訴計(jì)算機(jī)問(wèn)題領(lǐng)域,從而避免隨之而來(lái)的副作用。而命令式編程則需要用算法來(lái)明確的指出每一步該怎么做。聲明式編程通常被看做是形式邏輯的理論,把計(jì)算看做推導(dǎo)。聲明式編程大幅簡(jiǎn)化了并行計(jì)算的編寫(xiě)難度。

常見(jiàn)的聲明式編程語(yǔ)言有:
數(shù)據(jù)庫(kù)查詢語(yǔ)言(SQL,XQuery)
正則表達(dá)式
邏輯編程
函數(shù)式編程
組態(tài)管理系統(tǒng)等。

聲明式編程透過(guò)函數(shù)、推論規(guī)則或項(xiàng)重寫(xiě)(term-rewriting)規(guī)則,來(lái)描述變量之間的關(guān)系。它的語(yǔ)言運(yùn)行器(編譯器或解釋器)采用了一個(gè)固定的算法,以從這些關(guān)系產(chǎn)生結(jié)果。很多文本標(biāo)記語(yǔ)言例如HTML、MXML、XAML和XSLT往往是聲明式的。函數(shù)式編程,特別是純函數(shù)式編程,嘗試最小化狀態(tài)帶來(lái)的副作用,因此被認(rèn)為是聲明式的。不過(guò),大多數(shù)函數(shù)式編程語(yǔ)言,例如Scheme、Clojure、Haskell、OCaml、Standard ML和Unlambda,允許副作用的存在。

二、3種最常用編程范式的特點(diǎn)

過(guò)程式編程的核心在于模塊化,在實(shí)現(xiàn)過(guò)程中使用了狀態(tài),依賴了外部變量,導(dǎo)致很容易影響附近的代碼,可讀性較少,后期的維護(hù)成本也較高。

函數(shù)式編程的核心在于“避免副作用”,不改變也不依賴當(dāng)前函數(shù)外的數(shù)據(jù)。結(jié)合不可變數(shù)據(jù)、函數(shù)是第一等公民等特性,使函數(shù)帶有自描述性,可讀性較高。

面向?qū)ο缶幊痰暮诵脑谟诔橄螅峁┣逦膶?duì)象邊界。結(jié)合封裝、集成、多態(tài)特性,降低了代碼的耦合度,提升了系統(tǒng)的可維護(hù)性。

不同的范式的出現(xiàn),目的就是為了應(yīng)對(duì)不同的場(chǎng)景,但最終的目標(biāo)都是提高生產(chǎn)力。

1、過(guò)程式編程(Procedural)

過(guò)程式編程和面向?qū)ο缶幊痰膮^(qū)別并不在于是否使用函數(shù)或者類,也就是說(shuō)用到類或?qū)ο蟮目赡苁沁^(guò)程式編程,只用函數(shù)而沒(méi)有類的也可能是面向?qū)ο缶幊?。那么他們的區(qū)別又在哪兒呢?

面向過(guò)程其實(shí)是最為實(shí)際的一種思考方式,可以說(shuō)面向過(guò)程是一種基礎(chǔ)的方法,它考慮的是實(shí)際地實(shí)現(xiàn)。一般的面向過(guò)程是從上往下步步求精,所以面向過(guò)程最重要的是模塊化的思想方法。當(dāng)程序規(guī)模不是很大時(shí),面向過(guò)程的方法還會(huì)體現(xiàn)出一種優(yōu)勢(shì)。因?yàn)槌绦虻牧鞒毯芮宄粗K與函數(shù)的方法可以很好的組織。

2、函數(shù)式編程(Functional)

當(dāng)談?wù)摵瘮?shù)式編程,會(huì)提到非常多的“函數(shù)式”特性。提到不可變數(shù)據(jù),第一類對(duì)象以及尾調(diào)用優(yōu)化,這些是幫助函數(shù)式編程的語(yǔ)言特征。提到mapping(映射),reducing(歸納),piplining(管道),recursing(遞歸),currying(科里化),以及高階函數(shù)的使用,這些是用來(lái)寫(xiě)函數(shù)式代碼的編程技術(shù)。提到并行,惰性計(jì)算以及確定性,這些是有利于函數(shù)式編程的屬性。

最主要的原則是避免副作用,它不會(huì)依賴也不會(huì)改變當(dāng)前函數(shù)以外的數(shù)據(jù)。

聲明式的函數(shù),讓開(kāi)發(fā)者只需要表達(dá) “想要做什么”,而不需要表達(dá) “怎么去做”,這樣就極大地簡(jiǎn)化了開(kāi)發(fā)者的工作。至于具體 “怎么去做”,讓專門的任務(wù)協(xié)調(diào)框架去實(shí)現(xiàn),這個(gè)框架可以靈活地分配工作給不同的核、不同的計(jì)算機(jī),而開(kāi)發(fā)者不必關(guān)心框架背后發(fā)生了什么。

3、面向?qū)ο缶幊?Object-Oriented)

并不是使用類才是面向?qū)ο缶幊?。如果你專注于狀態(tài)改變和密封抽象,你就是在用面向?qū)ο缶幊?。類只是幫助?jiǎn)化面向?qū)ο缶幊痰墓ぞ?,并不是面向?qū)ο缶幊痰囊蠡蛑甘酒?。封裝是一個(gè)過(guò)程,它分隔構(gòu)成抽象的結(jié)構(gòu)和行為的元素。封裝的作用是分離抽象的概念接口及其實(shí)現(xiàn)。類只是幫助簡(jiǎn)化面向?qū)ο缶幊痰墓ぞ?,并不是面向?qū)ο缶幊痰囊蠡蛑甘酒鳌?/p>

隨著系統(tǒng)越來(lái)越復(fù)雜,系統(tǒng)就會(huì)變得越來(lái)越容易崩潰,分而治之,解決復(fù)雜性的技巧。面對(duì)對(duì)象思想的產(chǎn)生是為了讓你能更方便的理解代碼。有了那些封裝,多態(tài),繼承,能讓你專注于部分功能,而不需要了解全局。

總結(jié)

命令式編程、面向?qū)ο缶幊?、函?shù)式編程,雖然受人追捧的時(shí)間點(diǎn)各不相同,但是本質(zhì)上并沒(méi)有優(yōu)劣之分。 面向?qū)ο蠛秃瘮?shù)式、過(guò)程式編程也不是完成獨(dú)立和有嚴(yán)格的界限,在抽象出各個(gè)獨(dú)立的對(duì)象后,每個(gè)對(duì)象的具體行為實(shí)現(xiàn)還是有函數(shù)式和過(guò)程式完成。

三、重點(diǎn)說(shuō)一下函數(shù)式編程 1.函數(shù)式編程中的一些基本概念

(1)函數(shù)
函數(shù)式編程中的函數(shù),這個(gè)術(shù)語(yǔ)不是指命令式編程中的函數(shù)(我們可以認(rèn)為C++程序中的函數(shù)本質(zhì)是一段子程序Subroutine),而是指數(shù)學(xué)中的函數(shù),即自變量的映射(一種東西和另一種東西之間的對(duì)應(yīng)關(guān)系)。也就是說(shuō),一個(gè)函數(shù)的值僅決定于函數(shù)參數(shù)的值,不依賴其他狀態(tài)。

在函數(shù)式語(yǔ)言中,函數(shù)被稱為一等函數(shù)(First-class function),與其他數(shù)據(jù)類型一樣,作為一等公民,處于平等地位,可以在任何地方定義,在函數(shù)內(nèi)或函數(shù)外;可以賦值給其他變量;可以作為參數(shù),傳入另一個(gè)函數(shù),或者作為別的函數(shù)的返回值。

(2)純函數(shù)
純函數(shù)是這樣一種函數(shù),即相同的輸入,永遠(yuǎn)會(huì)得到相同的輸出,而且沒(méi)有任何可觀察的副作用。不依賴外部狀態(tài),不改變外部狀態(tài)。

比如Javascript里slice和splice,這兩個(gè)函數(shù)的作用相似。 slice符合純函數(shù)的定義是因?yàn)閷?duì)相同的輸入它保證能返回相同的輸出。splice卻會(huì)嚼爛調(diào)用它的那個(gè)數(shù)組,然后再吐出來(lái);這就會(huì)產(chǎn)生可觀察到的副作用,即這個(gè)數(shù)組永久地改變了。

var xs = [1,2,3,4,5];

// 純的
xs.slice(0,3);
//=> [1,2,3]
xs.slice(0,3);
//=> [1,2,3]
xs.slice(0,3);
//=> [1,2,3]


// 不純的
xs.splice(0,3);
//=> [1,2,3]
xs.splice(0,3);
//=> [4,5]
xs.splice(0,3);
//=> []

(3)變量與表達(dá)式

純函數(shù)式編程語(yǔ)言中的變量也不是命令式編程語(yǔ)言中的變量(存儲(chǔ)狀態(tài)的內(nèi)存單元),而是數(shù)學(xué)代數(shù)中的變量,即一個(gè)值的名稱。變量的值是不可變的(immutable),也就是說(shuō)不允許像命令式編程語(yǔ)言中那樣能夠多次給一個(gè)變量賦值。比如說(shuō)在命令式編程語(yǔ)言我們寫(xiě)x = x + 1。函數(shù)式語(yǔ)言中的條件語(yǔ)句,循環(huán)語(yǔ)句等也不是命令式編程語(yǔ)言中的控制語(yǔ)句,而是一種表達(dá)式。

“表達(dá)式”(expression)是一個(gè)單純的運(yùn)算過(guò)程,總是有返回值;
“語(yǔ)句”(statement)是執(zhí)行某種操作(更多的是邏輯語(yǔ)句。),沒(méi)有返回值。

函數(shù)式編程要求,只使用表達(dá)式,不使用語(yǔ)句。也就是說(shuō),每一步都是單純的運(yùn)算,而且都有返回值。比如在Scala語(yǔ)言中,if else不是語(yǔ)句而是三元運(yùn)算符,是有返回值的。嚴(yán)格意義上的函數(shù)式編程意味著不使用可變的變量,賦值,循環(huán)和其他命令式控制結(jié)構(gòu)進(jìn)行編程。 當(dāng)然,很多所謂的函數(shù)式編程語(yǔ)言并沒(méi)有嚴(yán)格遵循這一類的準(zhǔn)則,只有某些純函數(shù)式編程語(yǔ)言,如Haskell等才是完完全全地依照這種準(zhǔn)則設(shè)計(jì)的。

(4)狀態(tài)

首先要意識(shí)到,我們的程序是擁有“狀態(tài)”的。 想一想我們調(diào)試C++程序的時(shí)候,經(jīng)常會(huì)在某處設(shè)置一個(gè)斷點(diǎn)。程序執(zhí)行斷點(diǎn)就暫停了,也就是說(shuō)程序停留在了某一個(gè)狀態(tài)上。這個(gè)狀態(tài)包括了當(dāng)前定義的全部變量,以及一些當(dāng)前系統(tǒng)的狀態(tài),比如打開(kāi)的文件、網(wǎng)絡(luò)的連接、申請(qǐng)的內(nèi)存等等。具體保存的信息和語(yǔ)言有關(guān)系。比如使用過(guò)Matlab、R之類的科學(xué)計(jì)算語(yǔ)言的朋友會(huì)知道,在退出程序的時(shí)候它會(huì)讓你選擇是否要保存當(dāng)前的session,如果保存了,下次打開(kāi)時(shí)候它會(huì)從這個(gè)session開(kāi)始繼續(xù)執(zhí)行,而不是清空一切重來(lái)。你之前定義了一個(gè)變量x = 1,現(xiàn)在這個(gè)x還在那里,值也沒(méi)變。這個(gè)狀態(tài)就是圖靈機(jī)的紙帶。有了狀態(tài),我們的程序才能不斷往前推進(jìn),一步步向目標(biāo)靠攏的。函數(shù)式編程不一樣。函數(shù)式編程強(qiáng)調(diào)無(wú)狀態(tài),不是不保存狀態(tài),而是強(qiáng)調(diào)將狀態(tài)鎖定在函數(shù)的內(nèi)部,不依賴于外部的任何狀態(tài)。更準(zhǔn)確一點(diǎn),它是通過(guò)函數(shù)創(chuàng)建新的參數(shù)或返回值來(lái)保存程序的狀態(tài)的。
狀態(tài)完全存在的棧上。

(5)函數(shù)柯里化
curry 的概念很簡(jiǎn)單:將一個(gè)低階函數(shù)轉(zhuǎn)換為高階函數(shù)的過(guò)程就叫柯里化。

// 柯里化之前
function add(x, y) {
    return x + y;
}
add(1, 2) // 3
// 柯里化之后
function addX(y) {
    return function (x) {
        return x + y;
    };
}
addX(2)(1) // 3

(6)函數(shù)組合(Pointfree:不使用所要處理的值,只合成運(yùn)算過(guò)程)

為了解決函數(shù)嵌套過(guò)深,洋蔥代碼:h(g(f(x))),我們需要用到“函數(shù)組合”,我們一起來(lái)用柯里化來(lái)改他,讓多個(gè)函數(shù)像拼積木一樣。

const compose = (f, g) => (x => f(g(x)));
var first = arr => arr[0];
var reverse = arr = arr.reverse();
var last = compose(first, reverse);
last([1, 2, 3, 4, 5]); // 5

(7)聲明式與命令式代碼

在我們?nèi)粘I(yè)務(wù)開(kāi)發(fā)中,寫(xiě)的代碼絕大多數(shù)都為命令式代碼;
我們通過(guò)編寫(xiě)一條又一條指令去讓計(jì)算機(jī)執(zhí)行一些動(dòng)作,這其中一般都會(huì)涉及到很多繁雜的細(xì)節(jié)。
而聲明式就要優(yōu)雅很多了,我們通過(guò)寫(xiě)表達(dá)式的方式來(lái)聲明我們想干什么,而不是通過(guò)一步一步的指示。

//命令式
let CEOs = [];
for (var i = 0; i < companies.length; i++) {
    CEOs.push(companies[i].CEO)
}
//聲明式
let CEOs = companies.map(c => c.CEO);
2.函數(shù)式編程的特性

(1)高階函數(shù)
高階函數(shù)就是參數(shù)為函數(shù)或返回值為函數(shù)的函數(shù)。有了高階函數(shù),就可以將復(fù)用的粒度降低到函數(shù)級(jí)別。相對(duì)于面向?qū)ο笳Z(yǔ)言,高階函數(shù)的復(fù)用粒度更低。高階函數(shù)提供了一種函數(shù)級(jí)別上的依賴注入(或反轉(zhuǎn)控制)機(jī)制,在上面的例子里,sum函數(shù)的邏輯依賴于注入進(jìn)來(lái)的函數(shù)的邏輯。很多GoF設(shè)計(jì)模式都可以用高階函數(shù)來(lái)實(shí)現(xiàn),如Visitor,Strategy,Decorator等。比如Visitor模式就可以用集合類的map()或foreach()高階函數(shù)來(lái)替代。

(2)閉包
閉包的基礎(chǔ)是一等函數(shù)(First-class function)。閉包在形式上就是一個(gè)函數(shù)內(nèi)部定義另一個(gè)函數(shù),函數(shù)的堆棧在在函數(shù)返回后并不釋放,我們也可以理解為這些函數(shù)堆棧并不在棧上分配而是在堆上分配。

(3)訪問(wèn)權(quán)限控制
js中的作用域

(4)延長(zhǎng)變量生命周期
在面向?qū)ο笳Z(yǔ)言里,函數(shù)內(nèi)的變量都是在棧上分配的,函數(shù)調(diào)用完成后,棧銷毀,變量的生命周期結(jié)束。而對(duì)象是在堆分配的,會(huì)常駐內(nèi)存,除非被手動(dòng)或自動(dòng)回收掉。

(5)函子
Functor(函子)遵守一些特定規(guī)則的容器類型。任何具有map方法的數(shù)據(jù)結(jié)構(gòu),都可以當(dāng)作函子的實(shí)現(xiàn)。
Functor 是一個(gè)對(duì)于函數(shù)調(diào)用的抽象,我們賦予容器自己去調(diào)用函數(shù)的能力。把東西裝進(jìn)一個(gè)容器,只留出一個(gè)接口 map 給容器外的函數(shù),map 一個(gè)函數(shù)時(shí),我們讓容器自己來(lái)運(yùn)行這個(gè)函數(shù),這樣容器就可以自由地選擇何時(shí)何地如何操作這個(gè)函數(shù)。

3.函數(shù)式編程的好處

由于命令式編程語(yǔ)言也可以通過(guò)類似函數(shù)指針的方式來(lái)實(shí)現(xiàn)高階函數(shù),函數(shù)式的最主要的好處主要是不變性帶來(lái)的。

(1)引用透明(Referential transparency)
引用透明(Referential transparency),指的是函數(shù)的運(yùn)行不依賴于外部變量或”狀態(tài)”,只依賴于輸入的參數(shù),任何時(shí)候只要參數(shù)相同,引用函數(shù)所得到的返回值總是相同的。其他類型的語(yǔ)言,函數(shù)的返回值往往與系統(tǒng)狀態(tài)有關(guān),不同的狀態(tài)之下,返回值是不一樣的。這就叫”引用不透明”,很不利于觀察和理解程序的行為。
沒(méi)有可變的狀態(tài),函數(shù)就是引用透明(Referential transparency)

(2)沒(méi)有副作用(No Side Effect)。(Lodash.js)
副作用(side effect),指的是函數(shù)內(nèi)部與外部互動(dòng)(最典型的情況,就是修改全局變量的值),產(chǎn)生運(yùn)算以外的其他結(jié)果。函數(shù)式編程強(qiáng)調(diào)沒(méi)有”副作用”,意味著函數(shù)要保持獨(dú)立,所有功能就是返回一個(gè)新的值,沒(méi)有其他行為,尤其是不得修改外部變量的值。函數(shù)即不依賴外部的狀態(tài)也不修改外部的狀態(tài),函數(shù)調(diào)用的結(jié)果不依賴調(diào)用的時(shí)間和位置,這樣寫(xiě)的代碼容易進(jìn)行推理,不容易出錯(cuò)。這使得單元測(cè)試和調(diào)試都更容易。
還有一個(gè)好處是,由于函數(shù)式語(yǔ)言是面向數(shù)學(xué)的抽象,更接近人的語(yǔ)言,而不是機(jī)器語(yǔ)言,代碼會(huì)比較簡(jiǎn)潔,也更容易被理解。

(3)無(wú)鎖并發(fā)
沒(méi)有副作用使得函數(shù)式編程各個(gè)獨(dú)立的部分的執(zhí)行順序可以隨意打亂,(多個(gè)線程之間)不共享狀態(tài),不會(huì)造成資源爭(zhēng)用(Race condition),也就不需要用鎖來(lái)保護(hù)可變狀態(tài),也就不會(huì)出現(xiàn)死鎖,這樣可以更好地進(jìn)行無(wú)鎖(lock-free)的并發(fā)操作。尤其是在對(duì)稱多處理器(SMP)架構(gòu)下能夠更好地利用多個(gè)處理器(核)提供的并行處理能力。

(4)惰性求值
惰性求值(lazy evaluation,也稱作call-by-need)是這樣一種技術(shù):是在將表達(dá)式賦值給變量(或稱作綁定)時(shí)并不計(jì)算表達(dá)式的值,而在變量第一次被使用時(shí)才進(jìn)行計(jì)算。
這樣就可以通過(guò)避免不必要的求值提升性能。(簡(jiǎn)單例子&&)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/105393.html

相關(guān)文章

  • JavaScript 函數(shù)編程(一)

    摘要:函數(shù)式編程的哲學(xué)就是假定副作用是造成不正當(dāng)行為的主要原因。函數(shù)組合面向?qū)ο笸ǔ1槐扔鳛槊~,而函數(shù)式編程是動(dòng)詞。尾遞歸優(yōu)化函數(shù)式編程語(yǔ)言中因?yàn)椴豢勺償?shù)據(jù)結(jié)構(gòu)的原因,沒(méi)辦法實(shí)現(xiàn)循環(huán)。 零、前言 說(shuō)到函數(shù)式編程,想必各位或多或少都有所耳聞,然而對(duì)于函數(shù)式的內(nèi)涵和本質(zhì)可能又有些說(shuō)不清楚。 所以本文希望針對(duì)工程師,從應(yīng)用(而非學(xué)術(shù))的角度將函數(shù)式編程相關(guān)思想和實(shí)踐(以 JavaScript 為...

    hoohack 評(píng)論0 收藏0
  • 編程模型()小結(jié)

    摘要:參考鏈接面向?qū)ο缶幊棠P同F(xiàn)在的很多編程語(yǔ)言基本都具有面向?qū)ο蟮乃枷?,比如等等,而面向?qū)ο蟮闹饕枷雽?duì)象,類,繼承,封裝,多態(tài)比較容易理解,這里就不多多描述了。 前言 在我們的日常日發(fā)和學(xué)習(xí)生活中會(huì)常常遇到一些名詞,比如 命令式編程模型,聲明式編程模型,xxx語(yǔ)言是面向?qū)ο蟮牡鹊?,這個(gè)編程模型到處可見(jiàn),但是始終搞不清是什么?什么語(yǔ)言又是什么編程模型,當(dāng)你新接觸一門語(yǔ)言的時(shí)候,有些問(wèn)題是需...

    miya 評(píng)論0 收藏0
  • 函數(shù)入門(什么是函數(shù)編程)

    摘要:第一節(jié)函數(shù)式范式什么是函數(shù)式編程函數(shù)式編程英語(yǔ)或稱函數(shù)程序設(shè)計(jì),又稱泛函編程,是一種編程范型,它將電腦運(yùn)算視為數(shù)學(xué)上的函數(shù)計(jì)算,并且避免使用程序狀態(tài)以及易變對(duì)象。 第一節(jié) 函數(shù)式范式 1. 什么是函數(shù)式編程 函數(shù)式編程(英語(yǔ):functional programming)或稱函數(shù)程序設(shè)計(jì),又稱泛函編程,是一種編程范型,它將電腦運(yùn)算視為數(shù)學(xué)上的函數(shù)計(jì)算,并且避免使用程序狀態(tài)以及易變對(duì)...

    StonePanda 評(píng)論0 收藏0
  • 編程 —— 函數(shù)編程入門

    摘要:在函數(shù)式編程中數(shù)據(jù)在由純函數(shù)組成的管道中傳遞。函數(shù)式編程中函子是實(shí)現(xiàn)了函數(shù)的容器下文中將函子視為范疇,模型可表示如下但是在函數(shù)式編程中要避免使用這種面向?qū)ο蟮木幊谭绞饺《畬?duì)外暴露了一個(gè)的接口也稱為。 showImg(https://segmentfault.com/img/remote/1460000018101204); 該系列會(huì)有 3 篇文章,分別介紹什么是函數(shù)式編程、剖析函數(shù)...

    flyer_dev 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<