自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

大辯論:Java不是C++ 閉包讓Java更簡(jiǎn)單

原創(chuàng)
開(kāi)發(fā) 后端
Java真的需要閉包嗎?或者說(shuō),Java真的不需要閉包嗎?Java閉包的三個(gè)提案中,F(xiàn)CM提案最終得到了通過(guò)。這增加的一個(gè)語(yǔ)言特性,真的會(huì)令Java變得異常復(fù)雜么?本文作者認(rèn)為,人們不應(yīng)太擔(dān)心這個(gè),而是應(yīng)該為了閉包使Java更簡(jiǎn)單而感到高興。

【51CTO精選譯文】編者按:在上個(gè)月舉行的Devoxx大會(huì)上,Sun宣布Java 7中將包含簡(jiǎn)單的閉包特性。這與之前一年Sun的宣布完全相反——當(dāng)時(shí)他們說(shuō)Java將不會(huì)考慮閉包,因?yàn)镴ava不需要。Java社區(qū)對(duì)此是有人欣喜有人怒,不過(guò),到底有什么好爭(zhēng)論的呢?一位對(duì)C++和Java十分了解,一直關(guān)注編程語(yǔ)言的資深開(kāi)發(fā)者M(jìn)arek Krj在最近的一篇博文中詳細(xì)的分析了Java需要閉包的理由,并引申C++和C#的一些情況做為自己的論據(jù)。以下是Marek的討論:

#t#多年前,Sun這樣描述微軟對(duì)Java的擴(kuò)展提案:

Visual J++的許多優(yōu)點(diǎn)——類型安全、面向?qū)ο蟆⑶乙子诮M件互聯(lián)(component interconnection)——只是對(duì)Java對(duì)象模型的安全性和靈活性的繼承………

方法綁定(Bound)引用根本沒(méi)有必要,它們并不屬于Java編程語(yǔ)言的一個(gè)部分,因此它們也不能被標(biāo)準(zhǔn)的編譯器接受。此外,這些做法會(huì)讓Java語(yǔ)言損失掉簡(jiǎn)便性和統(tǒng)一性(unity)。
   
如此等等,這都是些營(yíng)銷時(shí)所說(shuō)的胡言亂語(yǔ)。我不知道還有什么比這更惱人的:1.自詡面向?qū)ο蟮恼y(tǒng)地位;2.自滿:“我們更理解Java”。但無(wú)論如何,James Gosling(Java之父本人)也很可能會(huì)常說(shuō)他希望閉包(closure)包含在Java中,而不是匿名內(nèi)部類(anonymous inner classes);3. 對(duì)于如何將函數(shù)作為Java語(yǔ)言的頭等公民(first class citiciens)那樣包含進(jìn)去,沒(méi)有一個(gè)完整的提案!這就是他們所謂的“根本沒(méi)有必要”的論據(jù)……

圍繞著閉包的思想存在著相當(dāng)大的爭(zhēng)議,這有點(diǎn)像我們最近討論過(guò)的關(guān)于C++ concepts特性的爭(zhēng)論:人們認(rèn)為它不必要,而且太復(fù)雜了(51CTO編者注:作者此處意為今年7月下旬,C++標(biāo)準(zhǔn)委員會(huì)確定將concepts特性從C++0x中移除一事。C++編程語(yǔ)言的作者Bjarne Stroustrup為此聲稱C++0x已死,將希望放在新一代C++標(biāo)準(zhǔn)上。)。由于在C++0x中,我們可以使用lambda函數(shù),這沒(méi)引起多少爭(zhēng)議,因此Java社區(qū)對(duì)于閉包的這一爭(zhēng)論激起了我的興趣。來(lái)啊,為什么不引入閉包呢?甚至C#都包含了一些閉包!

那么,什么是閉包(Closure)呢?在這篇博文中,我們把它認(rèn)為是類似于C++(或Python和Groovy)中l(wèi)ambda那樣的函數(shù),即一個(gè)匿名的、獨(dú)立式的函數(shù),比如下面這種:

  1. auto print = [] (int x) { cout << x; } 

現(xiàn)在,讓我們用Java語(yǔ)言來(lái)表示這一概念。

1.提案

那么,讓我們來(lái)看一看這三個(gè)提案。

a) BGGA(源自Bracha、Gafter、Gosling 和 Ahe的首字母)

這是最雄心勃勃的一個(gè)提案。它引入了一個(gè)新的語(yǔ)言類型:函數(shù)類型,以及它的一個(gè)全新的標(biāo)記方法(notation),這讓我想起了的Haskell或lambda函數(shù)的演算類型(calculus types):

{T => U} 表示一個(gè)從T到U的函數(shù){T => U => V} (或者這種形式{T,U => V}?) 表示一個(gè)從 T和U到V的函數(shù)

我認(rèn)為,這種標(biāo)記方法是許多Java從業(yè)者不太喜歡此提案的原因之一。另一個(gè)原因顯然歸因于非局部(nonlocal)環(huán)境語(yǔ)句(return ,break等)。新問(wèn)題再次出現(xiàn),非局部是指那個(gè)局部?嗯,舉個(gè)例子來(lái)說(shuō)吧,這意味著返回語(yǔ)句將不會(huì)從閉包返回,而是從調(diào)用該閉包的區(qū)域內(nèi)返回。它們不是綁定在閉包上,而是綁定在一個(gè)環(huán)境中。為什么這會(huì)是一件好事呢?親愛(ài)的讀者,下一節(jié)將為您詳細(xì)說(shuō)明。

一個(gè)使用的例子:

  1. {Integer => void} print = { Integer x => System.out.println(x); } 

b) CICE (簡(jiǎn)明實(shí)例創(chuàng)建方式,Concise Instance Creation Expressions)

這是三個(gè)提案中最簡(jiǎn)單的一個(gè)?;旧希黄鸬皆谡Z(yǔ)法上不斷定義匿名類的作用而已,沒(méi)有其他的用處。沒(méi)有第一類函數(shù)(first class functions)!沒(méi)有晦澀難懂的函數(shù)編程理論!

以下是一個(gè)例子:

  1. public interface IPrint { public void invoke(Integer x);} // exacltly 1 method!  
  2. Print print = IPrint(Integer x) { System.out.println(x); } 

雖然CICE是最簡(jiǎn)單的提案,但我認(rèn)為它也是最煩人的一個(gè)提案:你必須經(jīng)常返回去查詢一些接口的定義,真是太差勁了!

c) FCM(第一類方法,F(xiàn)irst Class Methods)

這是上面兩個(gè)方案的折衷:它引入了第一類函數(shù),但其閉包返回語(yǔ)句中并沒(méi)有包含非局部綁定,而且去掉了讓人討厭的lambda形式符號(hào)。(51CTO編者注:FCM是此次Sun宣布通過(guò)的提案,詳見(jiàn)Devoxx大會(huì)的相關(guān)報(bào)道。不過(guò),作者這篇文章寫于Devoxx之前,當(dāng)時(shí)對(duì)此還并不知曉。)

以下是一個(gè)例子:

  1. #(void(Integer)) print = #(Integer x) { System.out.println(x); } 

從以上三類的語(yǔ)法構(gòu)成上來(lái)說(shuō),我最喜歡的BGGA提案,因?yàn)槟隳軌蛴檬煜さ拇a塊(code-block)方式來(lái)編程,而不必使用FCM的hash和CICE的接口標(biāo)簽。

  1. #(void(Integer)) print = #(Integer x) { System.out.println(x); } 

2.爭(zhēng)論

說(shuō)得客氣一點(diǎn),我有時(shí)覺(jué)得這場(chǎng)辯論有點(diǎn)幼稚。下面是典型的辯點(diǎn):

◆正方觀點(diǎn):如果沒(méi)有閉包,我將永遠(yuǎn)不會(huì)用Java寫哪怕一行代碼,我會(huì)轉(zhuǎn)而使用Scala進(jìn)行編程。

◆反方觀點(diǎn):如果引入閉包,我將會(huì)崩潰掉……雖然我不會(huì)轉(zhuǎn)向其它語(yǔ)言,但我會(huì)因此而怨恨你!

得了吧,各位!只不過(guò)是一個(gè)語(yǔ)言的特性而已。如果你不喜歡的話,你不使用它不就得了嗎?而且,選擇什么語(yǔ)言進(jìn)行開(kāi)發(fā),是由項(xiàng)目經(jīng)理決定,而不是由開(kāi)發(fā)人員說(shuō)了算!如果經(jīng)理們認(rèn)為一個(gè)語(yǔ)言能夠帶來(lái)某種好處,那么該語(yǔ)言就有可能被采用。但這與你是否喜歡Scala或其他所謂更好的語(yǔ)言沒(méi)有半點(diǎn)的關(guān)系。

那么,閉包是否會(huì)使Java變得異常復(fù)雜?閉包是否真的如下面所說(shuō)的那樣:

 “……使編程語(yǔ)言變得復(fù)雜,超過(guò)了正常的可用范圍:主流程序員將放棄Java,人們還會(huì)繼續(xù)爭(zhēng)論下去,然后會(huì)轉(zhuǎn)向使用其它更為簡(jiǎn)單的編程語(yǔ)言……

Java會(huì)變成一個(gè)只有小范圍內(nèi)的專家才會(huì)使用的稀有語(yǔ)言”?

那請(qǐng)你告訴我,對(duì)JVM而言什么語(yǔ)言是最簡(jiǎn)單的!我找不出最簡(jiǎn)單的語(yǔ)言(非腳本語(yǔ)言)。專家語(yǔ)言(Guru language)?你在開(kāi)玩笑嗎?閉包的目的是讓Java變得更簡(jiǎn)單,因此每個(gè)人都應(yīng)該開(kāi)心才對(duì)。為什么要害怕呢?

一個(gè)可能的答案(非PC)是:認(rèn)為“太復(fù)雜”的一方對(duì)Java的現(xiàn)狀很滿意,他們不關(guān)注語(yǔ)言優(yōu)雅性的是否缺失,而且不想學(xué)習(xí)新的機(jī)制?;蛟S這是因?yàn)樵谀撤N程度上,Java已經(jīng)存在著太多的機(jī)制(或范型(paradigms))了?而對(duì)我來(lái)說(shuō),作為一個(gè)使用C++的開(kāi)發(fā)人員,我已習(xí)慣了“多范型設(shè)計(jì)”,因?yàn)镃++在這方面確實(shí)包羅萬(wàn)象。我不會(huì)去考慮那些我目前使用不到的機(jī)制。

也許,這對(duì)Java領(lǐng)域來(lái)說(shuō)并不簡(jiǎn)單,因?yàn)槎嗄暌詠?lái)Java程序員一直被灌輸一種常識(shí),即世界上只有面向?qū)ο筮@一種范型。這可以解釋人們?yōu)槭裁凑J(rèn)為泛型(generics)的加入會(huì)使語(yǔ)言的復(fù)雜性大大增加(另一個(gè)解釋是設(shè)計(jì)選擇上(特別對(duì)于通配符)需要考慮向后兼容性)。

因此,事情似乎是這樣:要么是由于人們對(duì)泛型機(jī)制的憤怒,要么是由于BGGA提案中包含非局部變量返回這一不常用的做法,激起了人們的強(qiáng)烈反對(duì)。你難道不這樣認(rèn)為嗎?

3.討論

讓我們的描述得更加技術(shù)一點(diǎn):為什么我們?cè)贘ava里面需要閉包呢?答案很可能是:因?yàn)镽uby語(yǔ)言里面有這個(gè)東西。Java 社區(qū)似乎還集體性的停留在一個(gè)過(guò)去Ruby所帶來(lái)的創(chuàng)傷,而仿效Ruby的特性在其本身看來(lái)理由十分充分。正如過(guò)去人們?cè)阼F幕時(shí)期常常說(shuō)的那樣:學(xué)習(xí)Ruby就是學(xué)習(xí)如何取勝!所以現(xiàn)在,就像在Ruby(或者Groovy和C#)里一樣,我們能夠用Java這樣編程:

  1. Utils.forEach(names, { Integer x => System.out.println(x); }); // BGGA 

而這是我們?cè)趲в蠸TL和lambda庫(kù)的C++里面常常使用的東西。

不過(guò),以上的敘述也不是爭(zhēng)論的全部。上述三個(gè)提案中每個(gè)都有第二部分,能夠允許包含某些細(xì)致的資源管理,可以認(rèn)為這是一種“現(xiàn)代的析構(gòu)函數(shù)”。我只能說(shuō)“最終這樣做了”,因?yàn)镴ava后期的資源管理非常麻煩。

BGGA試圖通過(guò)上面提到的非本地控制語(yǔ)句來(lái)達(dá)到這個(gè)目標(biāo),然后可以允許執(zhí)行“execute around”模式,即所謂的“控制抽象化”,但是有些不是很直觀。在BGGA提案里,關(guān)鍵詞是根據(jù)詞匯綁定的,而且會(huì)自動(dòng)指向定義了閉包的嵌套類型(enclosing type)實(shí)例。對(duì)我來(lái)說(shuō),Groovy一定程度上比較清楚的解決了非本地綁定的問(wèn)題——引進(jìn)了兩個(gè)閉包成員:owner(關(guān)于嵌套對(duì)象)和delegate(定義詞匯綁定)。通過(guò)這種方式,總是能夠清楚的說(shuō)明我們需要什么類型的詞匯綁定,delegate的默認(rèn)值是owner。

其他的提案也試圖解決同樣的問(wèn)題:CICE包含了ARM(自動(dòng)資源管理模塊 —— 一個(gè)特殊的模塊類型,當(dāng)不使用它的時(shí)候會(huì)自動(dòng)應(yīng)用處理方法),而FCM 包含了JCA(Java控制抽象化 —— 這個(gè)很像上面提到的“execute around“那種類型,而且和BGGA一樣需要非本地的詞匯綁定)。

在這一點(diǎn)上,讓我們?cè)囍贸龅囊恍┙Y(jié)論是:

第一:C#的3.0版本里面有l(wèi)ambda,C++0x里面同時(shí)包含有l(wèi)ambda和auto specifier,如果Java 7里再不包含閉包的話,就會(huì)顯得十分陳舊了。

但也不要絕望,目前有一個(gè)庫(kù)解決方案(http://code.google.com/p/lambdaj/)。在這種情況下,一個(gè)庫(kù)解決方案是否足夠呢?我不知道,因?yàn)樗恼Z(yǔ)法看起來(lái)不是很直觀,但是它可能已經(jīng)是你能夠得到的最佳方案了。

第二:我發(fā)現(xiàn)此處最有教育意義的內(nèi)容是:我們能夠看到析構(gòu)函數(shù)的老概念其實(shí)一點(diǎn)也不過(guò)時(shí)!既然C#有它的使用聲明,那么Java也理應(yīng)(而且需要)包含一些類似于析構(gòu)函數(shù)的機(jī)制。Java這一(前)“現(xiàn)代語(yǔ)言”也需要如此。

原文:Java's Closures Debate for C++ Eyes  作者:Marek Krj

責(zé)任編輯:yangsai 來(lái)源: 51CTO.com
相關(guān)推薦

2015-10-15 11:27:02

cookie安全總結(jié)

2013-06-09 16:49:56

布線系統(tǒng)TIA40Gb

2015-05-26 15:17:44

OpenStack

2011-09-27 09:16:36

JavaScript

2022-05-06 16:18:00

Block和 C++OC 類lambda

2011-07-27 16:55:12

Objective-c 閉包

2012-04-17 09:17:35

HTML 5App應(yīng)用

2015-05-20 12:50:42

C#開(kāi)發(fā)抽象增刪改

2011-05-16 17:02:44

云計(jì)算

2021-03-15 10:29:50

人工智能

2012-06-20 13:36:42

Surface平板

2009-06-15 09:43:11

Java閉包

2015-10-21 16:47:47

Testin云測(cè)

2019-04-04 14:05:20

consolejs前端

2019-07-10 10:20:36

前端用戶體驗(yàn)javascript

2009-08-19 09:57:01

C++ RAII

2024-01-22 09:51:32

Swift閉包表達(dá)式尾隨閉包

2011-08-05 09:33:30

Func局部變量作用域

2009-08-19 10:09:21

C#和C++

2023-09-24 23:44:10

C++類型安全
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)