天天看點

《Spark大資料分析:核心概念、技術及實踐》一 第2章 Scala程式設計

  本節書摘來自華章出版社《spark大資料分析:核心概念、技術及實踐》一書中的第2章,第2.1節,作者[美] 穆罕默德·古勒(mohammed guller),更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

第2章

scala程式設計

scala是目前熱門的現代程式設計語言之一。它是程式設計語言界的凱迪拉克。它是一門強大且優美的語言。學會了它,對你的職業生涯大有裨益。

用不同的程式設計語言都可以編寫大資料應用程式,比如java、python、c++、scala等。hadoop本身就是用java編寫的。盡管大多數的hadoop應用程式都是用java編寫的,但它也支援用其他語言來編寫。類似地,spark是由scala編寫的,但是它也支援其他的語言,包括scala、java、python和r。

對于開發大資料應用程式而言,scala是一門很棒的語言。使用它有諸多好處。首先,開發者使用scala能顯著提高生産力。其次,它能幫助開發者減少bug,寫出健壯的代碼。最後,spark就是用scala編寫的,因而對于開發spark應用而言使用scala是最自然的。

本章把scala當作一門通用語言來進行介紹。本章的目的并不是讓你成為scala專家,而是讓你有足夠多的scala知識進而能了解并使用scala來編寫spark應用。本書的示例代碼全部都由scala編寫,是以掌握scala,将更容易了解本書的内容。如果你已經學會了scala,那麼你可以跳過這一章。

基于上述目的,本章隻介紹scala程式設計的基礎知識。為了能更高效地使用scala,了解函數式程式設計是很重要的,是以本章将首先介紹函數式程式設計。最後,将介紹如何編寫一個單獨的scala應用程式。

2.1 函數式程式設計

函數式程式設計是一種程式設計範式,它把函數作為代碼的基本構成元素,避免使用指令式程式設計中的可變變量以及循環等控制結構。它把計算當作對數學函數的求值,函數的輸出完全依賴于傳遞給函數的參數值。程式就是由這些函數構成的。總之,在函數式程式設計語言中函數是一等公民。

在這幾年,函數式程式設計引起了大量的關注。甚至一些主流語言(比如c++、java和python)都添加了對函數式程式設計的支援。它的流行主要有如下幾個原因。

首先,使用函數式程式設計能極大地提升生産效率。相比于指令式程式設計,在解決同樣的問題上,函數式程式設計隻需要更少的代碼。舉例來說,在java中一個用一百行代碼實作的功能,用scala來實作隻需要10行或20行即可。函數式程式設計能帶來5~10倍的生産效率提升。

其次,函數式程式設計更容易編寫多并發或多線程的應用。随着多核、多cpu計算機的來臨,編寫多程序應用顯得愈發重要。在目前提升單cpu半導體數量已經越來越難的情況下,硬體産商開始采用增加cpu數量、增加核心數的方式來維持摩爾定律的有效性。現在多核計算機已經很普遍了。應用程式也需要利用多核帶來的優勢。相對于指令式程式設計語言,使用函數式程式設計語言更易于編寫利用多核的應用程式。

再者,函數式程式設計能幫助你寫出健壯的代碼。它可以幫你避免一些常見的程式設計錯誤。而且一般來說,應用中bug的數量與代碼和行數成正比。由于函數式程式設計相對于指令式程式設計通常代碼行數更少,是以使用它将帶來更少的bug。

最後,使用函數式程式設計語言更容易寫出便于閱讀、了解的優雅代碼。如果運用得當,用函數式程式設計語言寫出來的代碼看上去是很漂亮的,既不複雜也不混亂。你将從你的代碼中得到巨大的快樂和滿足。

本節将會介紹函數式程式設計中的幾個重要概念。

2.1.1 函數

函數是一段可以執行的代碼。通過函數,程式員可以将一個大型的程式分割成一些友善管理的代碼片段。在函數式程式設計中,應用程式就是建構在函數之上的。

盡管很多程式設計語言都支援函數的感念,但是函數式程式設計語言把函數當成一等公民。而且,函數是可以随意組合的,并沒有其他的副作用。

一等公民

函數式程式設計把函數當成一等公民。函數擁有和變量、值一樣的地位。函數可以像變量一樣使用。如果你把函數式程式設計中的函數和指令式程式設計語言(比如c)中的函數對比,更容易了解這個概念。

指令式程式設計語言中變量和函數是差別對待的。舉例來說,c語言中是不允許在函數内部定義函數的,它也不允許把一個函數當成參數傳給另外一個函數。

函數式程式設計允許把函數當成參數傳遞給另一個函數。函數也可以當成傳回值從另一個函數中傳回。函數可以在任何地方定義,包括在其他函數内部。它可以寫成匿名函數字面量,然後像字元串字面量一樣作為參數傳遞給另一個函數。

可組合

函數式程式設計中,函數是可以随意組合的。函數組合指的是可以把一些簡單的函數組合在一起進而建立一個複雜的函數,它是一個數學概念也是一個計算機科學概念。比如,兩個可組合的函數可以組合成一個新函數。考慮下面兩個數學函數。

f(x)=x*2

g(x)=x+2

函數f以一個數字作為輸入,将它的兩倍作為輸出。函數g以一個數字作為輸入,将它的值加2作為輸出。

如下所示,可以将f和g組合為一個新的函數。

h(x)=f(g(x))=f(x+2)=(x+2)*2

對于同樣的輸入,函數h的效果和先調用函數g處理輸入,然後将函數g的輸出作為參數調用函數f是一樣的。

為了解決複雜的問題,可以将它分解成幾個小問題,函數組合在這種方式下是很有用的。對于每個小問題可以寫若幹個函數,最後再把它們組合起來,進而解決這個複雜的問題。

無副作用

在函數式程式設計中函數并沒有什麼副作用。函數的傳回值完全依賴于傳遞給它的參數。函數的行為并不會随着時間的改變而改變。對于給定的參數值,無論調用這個函數多少次,始終傳回同樣的結果。換句話說,函數是無狀态的,它既不依賴也不會改變任何全局變量的值。

函數的無副作用性有如下幾個好處。首先,它們可以按任意順序組合在一起。其次,便于了解代碼。最後,使用這樣的函數便于編寫多線程的應用程式。

簡單

函數式程式設計中的函數是很簡單的。一個函數由幾行代碼構成,并且隻做一件事。一個簡單的函數是便于了解的。函數也保證了代碼的健壯性以及高品質。

可組合的簡單函數很适合用來實作複雜的算法,并且不容易出錯。函數式程式設計鼓勵人們不斷把問題分解成若幹個子問題,直到一個子問題能夠用一個簡單函數去解決為止。然後,把這些簡單函數組合起來就能得到解決這個複雜問題的函數了。

2.1.2 不可變資料結構

函數式程式設計強調使用不可變資料結構。純函數方式程式并不會使用任何可變資料結構或變量。換句話說,資料從不會在原地修改,這與指令式程式設計語言(比如c/c++、java和python)相比是不同的。沒有函數式程式設計背景的人很難想象沒有可變變量的程式是什麼樣子的。實際上,使用不可變資料結構寫代碼并非難事。

使用不可變資料結構具有如下好處。首先,它能減少bug。使用不可變資料結構編寫的代碼便于了解。另外,函數式程式設計語言的編譯器會強制使用不可變的資料結構。因而,很多bug在編譯期間就能捕獲。

其次,使用不可變資料結構便于編寫多線程應用程式。編寫一個能充分利用多核的應用程式并不容易。競争條件和資料損壞在多線程應用程式中是常見的問題。使用不可變資料結構有助于避免這些問題。

2.1.3 一切皆表達式

在函數式程式設計中,每一個語句都是一個表達式,都會有傳回值。比如scala中的if-else控制結構就是一個有傳回值的表達式。這與可以在if-else中寫多個語句的指令式程式設計語言顯著不同。

這一特性有助于不用可變變量編寫應用程式。