對函數(shù)式編程簡單理解
函數(shù)式編程是一種編程范式,和面向對象的編程方式一樣,是一種編程思想。函數(shù)式編程現(xiàn)在相當?shù)幕鸨罱苍陉P注這方面的思想。
對于面向對象編程主要有三點特性:封裝,多態(tài),繼承
封裝就是把對象的屬性和對象的行為封裝到一個定義的類里面
多態(tài)就是同一個對象可以表現(xiàn)為多種具體的形式
繼承就是子類可以繼承父類的屬性和行為
面向對象編程的思想是把所有的事物都當做對象來看待,任何事物皆對象。我們在學習面向對象的編程的時候,最喜歡舉的例子就是形狀->長方形->正方形 ,對于這種例子,面向對象的編程的確是非常合適的。對于大多數(shù)的自然界事物,都是可以抽象出來一個具體的對象,在具體化對象的屬性和行為。這種編程思想和人類的認知具體事物的方式非常接近,所以面向對象的方法一直流行了20幾年。
但是在某些情況下,并不是世界上所有的事物都適合用對象來表示,最常見的就是數(shù)學中的科學計算和邏輯運算
我們舉一個簡單的例子,我們定義一個函數(shù) f(x) = x*x + 2*x - 100 ,我們需要對f(1)到f(n)的結果進行求和,看看如何實現(xiàn)這一段邏輯
用面向對象的方式實現(xiàn)
面向對象的方式需要抽象出來一個對象來表現(xiàn)現(xiàn)實世界的事物,在這里,我們定義個函數(shù)接口,來表現(xiàn)f(x)這個函數(shù),通過實現(xiàn)這個接口,來實現(xiàn)具體的算法.
下面是function類的定義
public interface Function {
public int call(int x);
}
在來定義具體的實現(xiàn)函數(shù)
public class ConcreteFunction implements Function {
@Override
public int call(int x) {
return (x * x + 2 * x + 1);
}
}
最后我們定義一個靜態(tài)類,我們發(fā)現(xiàn)這個類基本上沒有任何意義,只是為了進行一次計算行為,當然我們還是可以抽象出來這一次計算行為,但是在這個例子里面,我們簡單一點,就是定義了一個靜態(tài)類實現(xiàn)這個功能
public class SumUtils {
public static final int sum(int n) {
int temp = 0;
for (int i = 0; i < n; i++) {
temp = temp + new ConcreteFunction().call(i);
}
return temp;
}
public static void main(String[] args) {
System.out.println(SumUtils.sum(10));
}
}
最后打印出來結果是 385.
用面向對象構造出來這個過程,有兩個地方比較丑陋,對于不同的f(x)我們需要定義出具體的實現(xiàn)類,每一個實現(xiàn)類代表一個具體的算法,用面向對象的觀點來看,不同的邏輯函數(shù)是不同的對象,這些對象之間完全沒有任何聯(lián)系,而且這些對象沒有任何屬性,不存在封裝的必要,同時也不會有被繼承的特性。在計算我們想要的結果的時候,我們必須在定義無意義的對象去找出我們想要的結果,這純粹是為了面向對象而定義對象,最后一個SumUtils類完全沒有任何意義。
從上面這個例子來看,面向對象并不是任何時候都適用的。下面我們看看用函數(shù)式編程如何實現(xiàn)這個功能。這里我們選擇scala語言來實現(xiàn)
def main(args: Array[String]) = {
var f = { x: Int => x * x + 2 * x + 1 };
var result = 0;
for (val x <- 0 to 9) {
result = result + f(x);
}
println(result);
}
我們首先定義了一個f 函數(shù),可以采用def f(x:Int) = {x*x + 2*x + 1} 的方式,也是采用代碼塊的方式,然后進行循環(huán)調用,計算出來結果。
從上面的代碼行數(shù)來看,四行代碼可以搞定。如果用一些高階功能,代碼可以做到更大皆簡化和最大的擴展性。極端情況下一行代碼就可以搞定。用函數(shù)來表示數(shù)學中的函數(shù),比用對象表現(xiàn)數(shù)學中的函數(shù)更形象,更具有可讀性。
函數(shù)式編程的特點:函數(shù)是第一公民,無副作用,內部不存在狀態(tài),易于并發(fā)。
有時候在想,面向對象和函數(shù)式編程結合起來,能夠極大的簡化我們的編程工作,寫出跟易于擴展的和可讀的代碼。在設計上,兩者思想是想通的。在不同的領域里面,用不同的思想去設計程序,這個是需要我們分析的。
其實面向對象程序中的設計模式,很多和函數(shù)式編程里面的思想想通。我們常用的模板模式和回調模式和函數(shù)式編程里面的高階函數(shù)設計思想類似,當設計能力達到一定層次之后,在去看函數(shù)式編程,就會對設計模式的理解更家深入。
正好這兩天也看到一個詞,編程極端主義——大概說的是,當某了解某一概念的時候,在任何情況下都套用這一概念。
編程極端主義 (跟極限編程沒有關系)是一種接受某種理論、在所有事情上檢驗它、在所有地方運用它的行為。一通實驗,塵埃落定后,人們通常會回想這次極端行為,認識到“不錯,這很有趣,但很明顯,在Y上使用X明顯不合適。干這個事情我們需要使用合適的技術!”
編程極端主義能夠讓你在學習一門新的技術或者概念的時候更深入的了解其特性,適用性以及局限性。基本上,java語言的設計思想就是一個編程極端主義的典型用例,在java里面,基本上任何東西都是對象(除了基本的類型之外),在學習了java之后,對面向對象的方式編程會有非常深入的了解,但是思想也會被局限在其中,導致在任何時候都會用面向對象的方式去思考,而這其中有一些并不適合面向對象的設計,最典型的就是java里面的Math類。
在學習函數(shù)式編程,也可以按照這個思路去學習,忘掉面向對象的設計,在任何情況下考慮函數(shù)式思想。haskell就是一門純粹的函數(shù)式編程。
14年互聯(lián)網(wǎng)技術、產品、運營經(jīng)驗,前支付寶技術專家,互金創(chuàng)業(yè)公司CTO,大令保事業(yè)部總經(jīng)理。
在互金領域有比較強的產品以及運營經(jīng)驗,尤其擅長用戶增長、轉化、運營上的經(jīng)驗,兼具技術、產品、運營思維。
目前是云貓增長實驗室 創(chuàng)始人
團隊成員來自阿里等國內知名互聯(lián)網(wǎng)公司,曾在互聯(lián)網(wǎng)金融、互聯(lián)網(wǎng)保險、企業(yè)級SaaS等項目中負責用戶增長,團隊管理的工作,擁有豐富的一線流量增長經(jīng)驗與實操手段。
歡迎關注我們,用技術驅動增長
浙公網(wǎng)安備 33010602011771號