函數式編程那些事兒

2021-01-21 網際網路前世今生

函數式編程是一種編程範式,在其中它試圖將每個函數都綁定到純數學函數中。這是一種聲明式的編程風格,著重於解決什麼而不是如何解決。

Clojure,Common Lisp,Erlang,Haskell和Scala是遵循函數式編程方法的一些著名程式語言。編程範例基於lambda演算,下面簡要說明:

Lambda演算

它使用表達式來代替語句。與執行語句以分配變量的語句不同,表達式的求值產生一個值。Lambda演算構成了幾乎所有使用的功能程式語言的基礎。

Lambda Calculus由Alonzo Church開發,是用於研究具有函數的計算的框架。使用lambda演算認為任何事物都是可計算的。它可以被標記為所有語言中最簡潔的程式語言。

就計算能力而言,lambda演算類似於圖靈機,後者為命令式編程奠定了基礎。簡單來說,lambda演算是一個描述函數及其評價的理論框架。

純函數

純函數具有兩個重要屬性,它們是:

無論其他因素如何,始終使用相同的參數產生相同的輸出,此屬性也稱為不變性純函數要麼提供一些輸出,要麼修改任何參數或全局變量,即它們沒有副作用,次屬性叫做確定性由於純函數沒有副作用或隱藏的I / O,因此使用函數範式構建的程序易於調試。此外,純函數使編寫並發應用程式更加容易。

使用函數式編程風格編寫代碼時,有能力的編譯器將能夠:

記住結果並行運算等待評估結果遞歸

在函數式編程範例中,沒有for和while循環。相反,函數式程式語言依賴於遞歸進行迭代。遞歸是使用遞歸函數實現的,遞歸函數會重複調用自己,直到達到基本情況為止。

引用透明性

一旦在函數式程式語言中定義了變量,就不允許在程序執行期間更改它們持有的值。這稱為引用透明性。它確保相同的語言表達式給出相同的輸出。

功能程序沒有任何賦值語句。為了在使用功能編程開發的程序中存儲其他值,必須定義新變量。在這樣的程序中,變量的狀態在任何時候都是恆定的。

引用透明性幾乎消除了任何不良影響的可能性,這是因為在程序執行的任何時候都可以用其實際值替換任何變量。

函數是一流的,可以是高階的

函數式編程風格的函數被視為變量。因此,它們是一流的功能。這些一流的函數被允許作為參數傳遞給其他函數,或者從函數返回或存儲在數據結構中。

高階函數是將其他函數用作參數和/或返回函數的函數。在函數式程式語言中,一等函數可以是高階函數。

變量是不可變的

變量是不可變的,即變量一旦初始化就無法修改。儘管我們可以創建一個新變量,但不允許修改現有變量。

函數式程式語言中變量的不變性質以在整個程序執行過程中保持狀態的形式受益。

優點

由於純函數不會更改任何狀態,並且完全取決於輸入,因此它們很容易理解。這些函數給定的返回值與它們產生的輸出相同。純函數的參數和返回類型由其函數籤名給出。由於純函數具有避免更改變量或變量之外的任何數據的性質,因此實現並發變得有效它支持延遲評估的概念,這意味著僅在需要時才評估和存儲該值。純函數僅接受一次參數並產生不變的輸出。因此,它們不會產生任何隱藏的輸出。它們使用不可變的值,從而使調試和測試更加容易。它的樣式將函數視為值,並將其作為參數傳遞給其他函數。它增強了代碼的理解性和可讀性。缺點

不變的值與遞歸結合可能會導致性能下降在某些情況下,編寫純函數會導致代碼的可讀性下降儘管編寫純函數很容易,但是將其與應用程式的其餘部分以及I / O操作結合起來很困難以遞歸方式編寫程序來代替使用循環,這可能是一項艱巨的任務應用領域

通常,函數式程式語言通常首選用於學術目的,而不是用於商業軟體開發。

但是,遵循功能性編程範例的幾種傑出的程式語言,例如Clojure,Erlang,F#,Haskell和Racket,被廣泛用於開發各種商業和工業應用。

WhatsApp利用Erlang(一種遵循功能性編程範例的程式語言)讓100多名員工即可管理超過15億人的數據。

函數式編程風格的另一個重要語言是Haskell。Facebook在其反垃圾郵件系統中使用了它。甚至JavaScript(使用最廣泛的程式語言之一)也喜歡使用函數式編程。

函數式編程風格對於各種程式語言引領不同領域至關重要。例如,統計中的R和財務分析中的J,K和Q。

領域特定的聲明性語言(例如Lex / Yacc和SQL)甚至使用這種編程範例的某些元素來避開可變值。

通常,此範例廣泛用於:

針對並發或並行的應用進行數學計算總結

除了純函數式程式語言外,還可以在非函數式程式語言中建立函數式編程方法。

C ++ 11,C#3.0和Java 8都添加了用於簡化書寫風格的函數式編程。

儘管通常以功能樣式編寫,但是Scala具有副作用和易變狀態的存在。因此,可以將程式語言置於命令式和功能性編程樣式之間的中間狀態。

相關焦點

  • 函數式編程
    來源:酷殼網-陳皓 連結:https://coolshell.cn/articles/10822.html當我們說起函數式編程來說,我們會看到如下函數式編程的長相:函數式編程的三大特性函數式編程的幾個技術map & reduce:這個技術不用多說了,函數式編程最常見的技術就是對一個集合做Map和Reduce操作。這比起過程式的語言來說,在代碼上要更容易閱讀。
  • Java如何支持函數式編程?
    Java是面向對象的語言,無法直接調用一個函數。Java 8開始,引入了函數式編程接口與Lambda表達式,便於開發者寫出更少更優雅的代碼。什麼是函數式編程?函數式編程的特點是什麼?函數式編程並非一個很新的東西,早在50多年前就已經出現了。近幾年,函數式編程越來越被人關注,出現了很多新的函數式程式語言,比如Clojure、Scala、Erlang等。一些非函數式程式語言也加入了很多特性、語法、類庫來支持函數式編程,比如Java、Python、Ruby、JavaScript等。除此之外,Google Guava也有對函數式編程的增強功能。
  • 函數式編程/lambda表達式入門
    函數式編程/lambda表達式入門本篇主要講解 lambda表達式的入門,涉及為什麼使用函數式編程,以及jdk8提供的函數式接口 和 接口的默認方法 等等1.什麼是命令式編程命令式編程就是我們去告訴程序如何實現
  • 大數據入門:Scala函數式編程
    提到Scala,首先會提到的一個概念,就是函數式編程,這也是Scala語言區別與其他程式語言的典型特徵。Scala是一門多範式(multi-paradigm)的程式語言,設計初衷是要集成面向對象編程和函數式編程的各種特性。
  • javascript函數式編程基礎指北
    JavaScript 作為一種典型的多範式程式語言,這兩年隨著React\vue的火熱,函數式編程的概念也開始流行起來,lodashJS、folktale等多種開源庫都使用了函數式的特性。程序的本質是:根據輸入通過某種運算得到輸出函數式編程(Functional programming)是一種編程思想/範式 ,其核心思想是將運算過程抽象成函數(指數學的函數而不是程序的方法或函數即純函數),也就是面向函數編程,描述函數/數據 之間的映射,做到最大程度的復用; 學習函數式編程真正的意義在於讓你認識到一種用函數的角度去抽象問題的思路
  • 函數式編程簡介—Lambda 表達式
    Java作為面向對象的程式語言,如果按照編程種類劃分屬於命令式編程(Imperative Programming)。常見的編程範式還有邏輯式編程(Logic Programming),函數式編程(Functional Programming)。
  • 程式設計師為何與函數式編程「墜入愛河」?
    簡單來說,函數式編程就是為不可變變量構建函數。與之相反,面向對象的編程則是有一組相對固定的函數,而用戶主要是修改或添加新變量。由於函數式編程的特性,它非常適合完成諸如數據分析和機器學習之類的需求任務。但是這並不意味著用戶要告別面向對象的編程,轉而完全使用函數式編程。但用戶需要了解其基本原理,以便在適當的時候使用它們以發揮優勢。
  • java8的函數式編程解析
    其實在java8就已經有java的函數式編程寫法,只是難度較大,大家都習慣了對象式用法,但在其它語言中都有函數式的用法,如js,scala,函數式其實是抽象到極致的思想。什麼是函數式編程 函數式編程並不是Java新提出的概念,其與指令編程相比,強調函數的計算比指令的計算更重要;與過程化編程相比,其中函數的計算可以隨時調用。
  • 為什麼函數式編程在Java中很危險?
    在我的日常工作中,我身邊的開發者大多是畢業於CS編程頂級院校比如MIT、CMU以及Chicago,他們初次涉及的語言是Haskell、Scheme及Lisp。他們認為函數式編程是一種自然的、直觀的、美麗的且高效的編程樣式。
  • 致開發人員:沉迷面向對象編程不可自拔?函數式編程了解一下
    函數式編程已經存在了60多年,但是到目前為止,它一直都很小眾。只有像Google這樣的改變遊戲規則的企業才會依賴函數式編程,普通程式設計師對此幾乎一無所知。這裡有一個容易發現副作用的簡單規則:由於每個函數必須具有某種輸入和輸出,因此沒有任何輸入或輸出的函數聲明必須是不純的。如果採用函數式編程,這是你可能想要更改的第一個聲明。函數式編程不僅是 map 和 reduce循環不是函數式編程中的東西。
  • 函數式編程如何能在常規軟體開發中佔一席之地
    如果你是在使用很傳統的程式語言,例如Java或C#,你應該知道了,這些語言很快就將引入一些函數式編程特徵。就在這美麗的新世界即將來到之際,就在我們摩拳擦掌打算大幹一番之前,我想,現在應該是我們暫停一下、反省一下函數式編程在我們的日常應用開發中是否合適的好時機。 什麼是函數式編程?簡單的回答:一切都是數學函數。
  • 函數式編程是未來的最佳編碼範例嗎?
    簡而言之,函數式編程需要為固定變量構建純函數並通過其響應更改狀態。 相反,其他程式語言具有通過更改程序中變量引用來更改應用程式狀態的能力。 您可以在本文中了解功能編程與面向對象程序的更多區別。由於其純粹的性質,函數式編程對於令人垂涎的任務(如機器學習和數據分析)印象深刻。
  • 一文帶你了解什麼是JavaScript 函數式編程?
    函數式編程在前端已經成為了一個非常熱門的話題。在最近幾年裡,我們看到非常多的應用程式代碼庫裡大量使用著函數式編程思想。本文將略去那些晦澀難懂的概念介紹,重點展示在 JavaScript 中到底什麼是函數式的代碼、聲明式與命令式代碼的區別、以及常見的函數式模型都有哪些?
  • Java新特性之-函數式編程
    面向對象編程範式的優點在於其抽象方式與現實中的概念比較相近。比如,學生、課程、汽車和訂單等這些現實中的概念,在抽象成相應的類之後,我們很容易就能理解類之間的關聯關係。這些類中所包含的屬性和方法可以很直觀地設計出來。函數式編程範式則相對較難理解。這主要是由於函數所代表的是抽象的計算,而不是具體的實體。因此比較難通過類比的方式來理解。
  • 使用JavaScript對象數組進行函數式編程
    我們著眼於使用map,filter和reduce來操縱對象數組,使用從函數式編程中借用的技術。數據操作是任何JavaScript應用程式中的常見任務。幸運的是,新的陣列處理運營商map,filter以及reduce廣泛的支持。雖然這些功能的文檔是足夠的,但它通常會顯示非常基本的實現用例。
  • 這樣理解 Java 中的函數式編程就對了
    在眾多的編程範式中,大多數開發人員比較熟悉的是面向對象編程範式。一方面是由於面向對象程式語言比較流行,與之相關的資源比較豐富,比如Java,c++等。函數式編程範式則相對較難理解。這主要是由於函數所代表的是抽象的計算,而不是具體的實體。因此比較難通過類比的方式來理解。
  • go 學習筆記之學習函數式編程前不要忘了函數基礎
    生物學家會下意識對動植物進行分類歸納,面向對象編程也是如此,用一系列的抽象模型去模擬現實世界的行為規律.數學家向來以嚴謹求學著稱,作為最重要的基礎科學,數學規律以及歸納演繹方法論對應的就是函數式編程,不是模擬現實而是描述規律更有可能創造規律.標準的函數式編程具有濃厚的數學色彩,幸運的是,Go 並不是函數式語言,所以也不必受限於近乎苛責般的條條框框.
  • 從Python到Haskell:程式設計師為何與函數式編程「墜入愛河」?
    不僅是Java或Python這樣的語言越來越多地採用了函數式編程的概念,類似Haskell這樣的新語言也正在完全實現函數式編程。簡單來說,函數式編程就是為不可變變量構建函數。與之相反,面向對象的編程則是有一組相對固定的函數,而用戶主要是修改或添加新變量。由於函數式編程的特性,它非常適合完成諸如數據分析和機器學習之類的需求任務。
  • 面試被虐題:說說 JVM 系語言的函數式編程
    >函數式編程在上世紀五十年代就有了,只不過在工業界一直不溫不火,最近十年才被廣泛認知。其理論基礎也並非為編程而設計,而是一種數學抽象(Lamda演算),其實初中就學過了,λ表達式。在 JS(建議把 JS 作為函數式編程思想學習的入門語言,Java 的實現略顯臃腫,可能不太便於理解)當中,函數式編程算是應用比較多的了。各現代高級程式語言,都或多或少地支持了函數式編程。
  • Swift 不是多範式函數式程式語言
    但是面向對象編程(OOP)只是思考問題的一種方式。函數式編程是思考問題的另一種方式。函數式編程主要是將問題分解為接受並返回不可變值的函數。它通常的結構是一些將值轉換為其他值的函數,以及各種組合函數的方法的集合。它避免了可變狀態,並且不要求函數的求值以任何特定的順序進行。函數式編程將程序視為一個數學問題,而不是一系列操作。