av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

Scala如何改變了我的編程風(fēng)格:從命令式到函數(shù)式

編輯推薦:Scala編程語(yǔ)言專題

在汾陽(yáng)等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站、成都外貿(mào)網(wǎng)站建設(shè)公司 網(wǎng)站設(shè)計(jì)制作按需策劃,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計(jì),成都全網(wǎng)營(yíng)銷,外貿(mào)網(wǎng)站制作,汾陽(yáng)網(wǎng)站建設(shè)費(fèi)用合理。

編者前言:這篇文章最初寫于2008年底,作者Bill Venners一方面是美國(guó)著名開發(fā)網(wǎng)站Artima的總編,另一方面也是一位十分關(guān)注Scala語(yǔ)言的Java程序員。在這幾個(gè)月間的Scala創(chuàng)始人Martin Odersky訪談系列中,與Martin對(duì)話的正是Bill Venners。這篇文章雖然已經(jīng)完成了半年有余,但對(duì)于還不很熟悉Scala語(yǔ)言的Java程序員而言,仍然是一篇非常實(shí)用的Scala語(yǔ)言簡(jiǎn)介。以下是譯文:

每次我學(xué)習(xí)一門新的語(yǔ)言,我都會(huì)學(xué)到某些編程方面的東西。比如說,當(dāng)我以一個(gè)C++程序員的身份學(xué)習(xí)Java的時(shí)候,Java的接口構(gòu)造教會(huì)我來自純粹的抽象基類的多重繼承的價(jià)值。盡管在C++里面這種編程風(fēng)格是有可能的,但在我使用C++的日子里,我卻沒有考慮用這種方式進(jìn)行多重繼承,而我在C++設(shè)計(jì)中也不怎么使用抽象基類。然而,一旦我開始進(jìn)行Java編程,我就開始一直使用這種風(fēng)格了。學(xué)習(xí)Java—尤其是它的接口構(gòu)造—改變了我OO設(shè)計(jì)的方法。

編輯推薦:充分利用面向?qū)ο笳Z(yǔ)言的接口特性 | 面向?qū)ο蟮乃季S過程

我學(xué)習(xí)Scala編程的時(shí)候也發(fā)生了類似的情況。在過去的兩年里,我有相當(dāng)多的時(shí)間是用Scala工作的,Scala是Java平臺(tái)上的一種新的靜態(tài)類型語(yǔ)言,它融合了面向?qū)ο缶幊毯秃瘮?shù)型程序設(shè)計(jì)的概念。Scala能讓我寫出幾乎跟Ruby和Python一樣簡(jiǎn)潔的代碼。在Scala我可以跟在Java里面一樣方便地調(diào)用Java庫(kù),包括我已有的Java庫(kù)??紤]到Scala是靜態(tài)類型的,我可以享受到諸多靜態(tài)類型的好處,諸如將文檔作為類型,IDE代碼自動(dòng)完成,動(dòng)態(tài)代碼重構(gòu)(deterministic refactoring)以及執(zhí)行速度等(Scala程序的執(zhí)行速度跟Java的一樣快)。但Scala還讓我以簡(jiǎn)潔和類型安全的方式獲得某些通常是動(dòng)態(tài)語(yǔ)言的好處,例如在已有類上增加新方法的能力,或者將類型傳遞給沒有共同繼承關(guān)系的方法。

Scala是怎樣改變了我對(duì)編程的看法的呢?一句話:我學(xué)會(huì)了欣賞函數(shù)化的風(fēng)格。函數(shù)化的編程風(fēng)格強(qiáng)調(diào)不可變對(duì)象、變量可被初始化但不能重新賦值(Java中的最終變量)、數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換,以及方法和控制的構(gòu)造,最終產(chǎn)生一個(gè)沒有副作用的結(jié)果。這個(gè)領(lǐng)域的另一端是命令式的風(fēng)格,以可變對(duì)象、變量可被重新賦值(Java里的正常變量)、在數(shù)據(jù)結(jié)構(gòu)中索引、以及帶副作用的方法和控制構(gòu)造為特征。

盡管Scala經(jīng)常被吹捧為函數(shù)型編程語(yǔ)言,當(dāng)它并不僅僅是函數(shù)型的。Scala同時(shí)支持函數(shù)式和命令式兩種風(fēng)格。如果你自己選擇要這么做的話,你可以以Java的編程方式進(jìn)行Scala編程,那種風(fēng)格主要是命令式的。這樣有助于Scala的學(xué)習(xí)曲線變緩,但隨著對(duì)Scala越來越熟悉,你就會(huì)發(fā)現(xiàn)自己會(huì)更喜歡函數(shù)式的。我就是這樣。為什么?因?yàn)槲野l(fā)現(xiàn)函數(shù)型風(fēng)格往往要比命令式風(fēng)格的代碼更簡(jiǎn)潔,且更不易出錯(cuò)。函數(shù)式風(fēng)格的代碼通常層次更高,這使得它編寫起來更快,閱讀也更為容易。舉個(gè)例子,看看下面這段確定一個(gè)字符串是否包含大寫字符的Java代碼。

boolean nameHasUpperCase = false; // 這是Java

for (int i = 0; i < name.length(); ++i) {

    if (Character.isUpperCase(name.charAt(i))) {

        nameHasUpperCase = true;

        break;

    }

}

這里的命令式風(fēng)格是很明顯的,因?yàn)閚ameHasUpperCase變量被重新賦值會(huì)給loop循環(huán)帶來副作用,loop是通過字符串中的字母索引進(jìn)行迭代的。在Java你還可以以更為簡(jiǎn)潔的方式得到相同的結(jié)果,像下面這樣:

boolean nameHasUpperCase = !name.toLowerCase().equals(name);

這一行Java代碼展現(xiàn)出一種更為函數(shù)化的風(fēng)格,因?yàn)樗D(zhuǎn)換不可變數(shù)據(jù):name這個(gè)字符串被轉(zhuǎn)換為另外一個(gè)全部字母都是小寫的字符串,然后值被轉(zhuǎn)換為布爾結(jié)果。此外,nameHasUpperCase這個(gè)變量被初始化了,但僅限于這一小塊代碼里,而沒有被重新賦值。如果該變量為最終值的話,它的函數(shù)化就會(huì)更為清晰。

在Scala里面,你可以寫出跟以上兩個(gè)例子類似的代碼,不過更為理想的編寫方式是像下面這樣的:

val nameHasUpperCase = name.exists(_.isUpperCase)

nameHasUpperCase變量被定義為 val,即可被初始化但不能被重新賦值的變量(類似于Java里面的最終變量)。甚至于盡管本例中并無顯式的類型標(biāo)注,Scala的類型推斷機(jī)制也會(huì)給nameHasUpperCase賦予Boolean類型。exists 方法在對(duì)象集合中迭代,并依次將每個(gè)元素傳遞給函數(shù)對(duì)象。在這里, name字符串被視為字符集合,因此exists會(huì)把字符串的每一個(gè)字符都傳遞給該函數(shù)。_.isUpperCase的語(yǔ)法是Scala里的一種函數(shù)顯式聲明(function literal),是一種編寫少量代碼就可以到處傳遞和調(diào)用的速寫方式。下劃線代表該函數(shù)的唯一參數(shù)。因此你可以把下劃線視為每次該函數(shù)被調(diào)用時(shí)待填的空白。如果exists 方法發(fā)現(xiàn)該函數(shù)因被傳遞的字符中的其中一個(gè)而返回true—比如說,其中一個(gè)字符是大寫的—而返回true。否則就返回false。

盡管最后的這個(gè)單行代碼對(duì)于某些不熟悉Scala的人來說像是天書,只要你了解了Scala,你就能一眼看出代碼的目的。相反,其他的兩個(gè)版本卻要費(fèi)上一點(diǎn)功夫去研究一下。另外需要注意的一點(diǎn)不同是命令式例子中潛在的偏移錯(cuò)誤,因?yàn)槟惚仨氾@式地指出迭代的上標(biāo)。在函數(shù)化的版本里這種錯(cuò)誤不會(huì)產(chǎn)生,在這種方式下,函數(shù)化版本相對(duì)而言不易出錯(cuò)。

最后,我想指出的是我轉(zhuǎn)向Scala的時(shí)候并沒有“徹底函數(shù)化”。盡管我已經(jīng)發(fā)現(xiàn)通常大部分情況下函數(shù)化風(fēng)格的代碼來得更為簡(jiǎn)潔、明晰,更不易出錯(cuò),我還發(fā)現(xiàn)有時(shí)候命令式風(fēng)格也可帶來更為清晰和簡(jiǎn)潔的代碼。在那種情況下,我就會(huì)使用命令式的。Scala允許我方便地應(yīng)用函數(shù)式和命令式的風(fēng)格,結(jié)合使用此二者,我就能找到寫出清晰代碼的最佳方式。

#p#

函數(shù)式編程和命令式編程簡(jiǎn)介

什么是函數(shù)式編程?(參考資料:《征服RIA:基于JavaScript的Web客戶端開發(fā)》第8章JavaScript函數(shù)對(duì)象

在數(shù)學(xué)領(lǐng)域,函數(shù)是一種關(guān)系,這種關(guān)系使一個(gè)集合里的每一個(gè)元素對(duì)應(yīng)到另一個(gè)集合里的唯一元素。函數(shù)是將唯一的輸出值賦予每一輸入的"法則"。這一"法則"可以用函數(shù)表達(dá)式、數(shù)學(xué)關(guān)系,或者一個(gè)將輸入值與輸出值對(duì)應(yīng)列出的簡(jiǎn)單表格來表示。函數(shù)最重要的性質(zhì)是其決定性,即同一輸入總是對(duì)應(yīng)同一輸出(注意,反之未必成立)。從這種視角,可以將函數(shù)看做"機(jī)器"或者"黑盒",它將有效的輸入值變換為唯一的輸出值。通常將輸入值稱做函數(shù)的參數(shù),將輸出值稱做函數(shù)的值。

《Why Functional Programming Matters》的作者John Hughes 說明了模塊化是成功編程的關(guān)鍵,而函數(shù)編程可以極大地改進(jìn)模塊化。在函數(shù)編程中,編程人員有一個(gè)天然框架用來開發(fā)更精練的、更小的、更簡(jiǎn)單的和更一般化的模塊,然后將它們組合在一起。函數(shù)式編程的基本特點(diǎn)是:

豐富的數(shù)據(jù)類型;

函數(shù)是運(yùn)算元;

在函數(shù)內(nèi)保存數(shù)據(jù);

函數(shù)內(nèi)的運(yùn)算對(duì)函數(shù)外無副作用。

函數(shù)式編程只描述在程序輸入上執(zhí)行的操作,不必使用臨時(shí)變量保存中間結(jié)果。重點(diǎn)是捕捉"是什么以及為什么",而不是"如何做"。與將重點(diǎn)放在執(zhí)行連續(xù)命令上的過程性編程相比,函數(shù)式編程的重點(diǎn)是函數(shù)的定義而不是狀態(tài)機(jī)(State Machine)的實(shí)現(xiàn)。是一種強(qiáng)調(diào)表達(dá)式的計(jì)算而非命令的執(zhí)行的一種編程風(fēng)格。表達(dá)式是用函數(shù)結(jié)合基本值構(gòu)成的,它類似于用參數(shù)調(diào)用函數(shù)(函數(shù)式的優(yōu)美的說明可見《Functional Programming For The Rest of Us》)。

什么是命令式編程?(參考資料:維基百科)

命令式編程,是種描述電腦所需作出的行為的編程典范。幾乎所有電腦的硬體工作都是命令式的;幾乎所有電腦的硬體都是設(shè)計(jì)來執(zhí)行機(jī)器碼,使用命令式的風(fēng)格來寫的。較高階的命令式編程語(yǔ)言使用變數(shù)和更復(fù)雜的語(yǔ)句,但仍依從相同的典范。食譜和行動(dòng)清單,雖非電腦程式,但與命令式編程有相似的風(fēng)格:每步都是指令,有形的世界控制情況。因?yàn)槊钍骄幊痰幕A(chǔ)觀念,不但概念上比較熟悉,而且較容易具體表現(xiàn)于硬體,所以大部分的編程語(yǔ)言都是命令式的。

原文:How Scala Changed My Programming Style  作者:Bill Venners

【相關(guān)閱讀】

  1. Scala的類型系統(tǒng) 比Java更靈活
  2. Java程序員,你為什么要關(guān)注Scala
  3. Scala創(chuàng)始人:創(chuàng)造比Java更好的語(yǔ)言
  4. Java以外的選擇 Scala編程語(yǔ)言簡(jiǎn)介
  5. Java之外,選擇Scala還是Groovy?

網(wǎng)頁(yè)題目:Scala如何改變了我的編程風(fēng)格:從命令式到函數(shù)式
文章位置:http://uogjgqi.cn/article/copoges.html
掃二維碼與項(xiàng)目經(jīng)理溝通

我們?cè)谖⑿派?4小時(shí)期待你的聲音

解答本文疑問/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流