摘要:本文屬於原創,歡迎轉載,轉載請保留出處:https://github.com/jasonGeng88/bloghtml
原文:https://hackernoon.com/you-should-learn-functional-programming-in-2017-91177148ec00git
函數式編程已經存在了很長了時間,早在50年代 Lisp 編程語言的介紹中就有提過。若是你有關注近兩年裏內熱門的 Clojure,Scala,Erlang,Haskell,Elixir 等語言的話,其中都有函數式編程的概念。程序員
那麼到底什麼是函數式編程,爲何每一個人都癡迷於它?在這篇文章中,做者將試圖回答以上問題,而且激起你對函數式編程的興趣。github
正如咱們所說的,早在50年代函數式編程開始以前,Lisp 語言就已經在 IBM 700/7000 系列的科學計算機上運行了。Lisp 引入了不少與咱們如今的函數式編程有關的示例與功能,咱們甚至能夠稱 Lisp 是全部函數式編程語言的鼻祖。編程
這也是函數式編程中最有趣的方面,全部函數式編程語言都是基於相同的 λ演算,這種簡單數學基礎。閉包
λ演算是圖靈完備的,它是一種通用的計算模型,可用於模擬任何一臺單帶圖靈機。它名字中的希臘字母 lambda(λ),被使用在了 lambda 表達式和 lambda 項綁定函數中的變量中。併發
λ演算是一個極其簡單但又十分強大的概念。它的核心主要有兩個概念:app
函數的抽象,經過引入變量來概括得出表達式;編程語言
函數的應用,經過給變量賦值來對已得出的表達式進行計算;分佈式
讓咱們來看個小例子,單參數函數 f,將參數遞增1。
f = λ x. x+1
假設咱們應用函數在數字5上,那麼函數讀取以下:
f(5) => 5 + 1
如今,數學知識已經夠了。讓咱們看一下使函數式編程變得強大的特性有哪些?
在函數式編程中,函數是一等公民,意思是說函數能夠賦值給變量,例如在 elixir 中,
double = fn(x) -> x * 2 end
而後咱們能夠以下來調用函數:
double.(2)
高階函數的定義是,接收一個或多個函數變量做爲參數,而後生成的新函數,即爲高階函數。讓咱們再次使用函數 double 來講明這個概念:
double = fn(x) -> x * 2 end Enum.map(1..10, double)
這例子中,Enum.map 將一個枚舉列表做爲第一參數,以前定義的函數做爲第二參數;而後將這個函數應用到枚舉中的每個元素,結果爲:
[2,4,6,8,10,12,14,16,18,20]
在函數式編程語言中,狀態是不可變的。這意味着一旦一個變量被綁定了一個值,它將不能再被從新定義。這在防止反作用與條件競爭上有明顯的優點,使併發編程更簡單。
和上面同樣,讓咱們使用 Elixir 來講明一下這概念:
iex> tuple = {:ok, "hello"} {:ok, "hello"} iex> put_elem(tuple, 1, "world") {:ok, "world"} iex> tuple {:ok, "hello"}
這個例子中,tuple 的值歷來沒有改變過,第三行 put_elem 是返回了一個徹底新的 tuple, 而沒有去修改原有的值。
做爲一個程序員,咱們生活在激動人心的時代,雲端的承諾已經兌現。與此同時,咱們每一個人都能獲取史無前例的計算機資源。不幸的是,隨之帶來的擴展性、性能、併發性的需求。
面向對象編程根本不能簡單的解決這些需求,尤爲是在處理併發和並行計算的時候。嘗試添加併發性和並行性,只會使語言增長它的複雜性,以及差的性能表現。
函數式編程在另外一方面是很是適合這些挑戰的,不可變狀態、閉包和高階函數等概念,在對於編寫高度併發和分佈式應用程序而言,它們很是適合。
你能夠經過查看「WhatsApp和Discord」等創業公司的技術資料,找到足夠的證實:
這些公司和團隊可以處理這種巨大的增加,要感謝函數式編程的優點。隨着函數式編程獲得愈來愈多的認同,我堅信像 WhatsApp 和 Discord 的例子會愈來愈廣泛。