摘要:動態(tài)類型語言的表達(dá)力動態(tài)語言通常更方便開發(fā)較小的項目,因為可以無需聲明類型而節(jié)省了很多麻煩。
函數(shù)式編程與面向?qū)ο缶幊蘙2]: 靜態(tài)類型語言的表達(dá)力 靜態(tài)類型語言與動態(tài)類型語言
之劍
2016.5.3 21:43:20
像Java或者C#這樣強類型的準(zhǔn)靜態(tài)語言在實現(xiàn)復(fù)雜的業(yè)務(wù)邏輯、開發(fā)大型商業(yè)系統(tǒng)、以及那些生命周期很長的應(yīng)用中也有著非常強的優(yōu)勢
下面我們就來學(xué)習(xí)一下這些知識.
有三個名詞容易混淆:
Dynamic Programming Language (動態(tài)語言或動態(tài)編程語言)
Dynamically Typed Language (動態(tài)類型語言)
Statically Typed Language (靜態(tài)類型語言)
先定義一下標(biāo)準(zhǔn):
強類型語言(靜態(tài)類型語言)是指需要進行變量/對象類型聲明的語言,一般情況下需要編譯執(zhí)行。例如C/C++/Java/C#
弱類型語言(動態(tài)類型語言)是指不需要進行變量/對象類型聲明的語言,一般情況下不需要編譯(但也有編譯型的)。例如PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等。
1 靜態(tài)類型語言靜態(tài)類型語言的類型判斷是在運行前判斷(如編譯階段),比如C#、java就是靜態(tài)類型語言,靜態(tài)類型語言為了達(dá)到多態(tài)會采取一些類型鑒別手段,如繼承、接口,而動態(tài)類型語言卻不需要,所以一般動態(tài)語言都會采用dynamic typing,常出現(xiàn)于腳本語言中.
不過,是不是動態(tài)類型語言與這門語言是不是類型安全的完全不相干的,不要將它們聯(lián)系在一起!
沒有單元測試或者單元測試沒有達(dá)到語句覆蓋或者更強的弱條件組合覆蓋,從而導(dǎo)致某些非正常流程發(fā)生時,流經(jīng)這些未被測試的語句導(dǎo)致語法錯誤而最終整個程序都掛掉.對于業(yè)務(wù)系統(tǒng)來說,這是非常嚴(yán)重的事情。
1.1 優(yōu)點靜態(tài)類型語言的主要優(yōu)點在于其結(jié)構(gòu)非常規(guī)范,便于調(diào)試,方便類型安全
現(xiàn)在有這樣一種趨勢,那就是合并動態(tài)類型與靜態(tài)類型在一種語言中,這樣可以在必要的時候取長補短(下面在第4節(jié)中:在Scala語言的特色時介紹).
現(xiàn)在開發(fā)效率比以前高多了,主要原因是因為開發(fā)語言和編譯器的進步,這個趨勢,只會繼續(xù)下去,不要抱著過去的教條不放,java也是在不斷改進的,加了reflection, 加了assert,加了泛型,下個版本,也要加腳本支持了。
其實靜態(tài)類型語言,除了性能方面的考量之外,最大的優(yōu)勢就是可以提供靜態(tài)類型安全,編譯器可以檢查你的每一個函數(shù)調(diào)用是不是書寫了正確的名字,是不是提供了正確類型的參數(shù)。這樣一個系統(tǒng),配合自定義類型的功能,可以讓很多錯誤(比許多人想象的要多)在編譯時就能被發(fā)現(xiàn)和定位。
1.2 缺點缺點是為此需要寫更多的類型相關(guān)代碼,導(dǎo)致不便于閱讀、不清晰明了。
2 動態(tài)類型語言所謂的動態(tài)類型語言,意思就是類型的檢查是在運行時做的,比如如下代碼是不是合法的要到運行時才判斷(注意是運行時的類型判斷):
def sum(a, b): return a + b2.1 優(yōu)點
動態(tài)類型語言的優(yōu)點在于方便閱讀,不需要寫非常多的類型相關(guān)的代碼;動態(tài)語言代表著更快更簡單的技術(shù)大趨勢,因此它將必然成為未來構(gòu)建軟件和互聯(lián)網(wǎng)技術(shù)的主角。
動態(tài)語言足夠靈活,因此雖然它能夠讓人更集中精力思考業(yè)務(wù)邏輯的實現(xiàn),同時也向人工智能的方向走得更近一些,但因此它也更依賴于開發(fā)人員本身的技術(shù)功底,初學(xué)者、中級開發(fā)者,難以很好的利用它。 而靜態(tài)類型語言,與我們計算機教學(xué)的基本科目(c/pascal/basic)延續(xù)性比較好,所以對于剛畢業(yè)的學(xué)生而言,更好接受和學(xué)習(xí)。
2.2 缺點缺點自然就是不方便調(diào)試,命名不規(guī)范時會造成讀不懂,不利于理解等。
3 動態(tài)類型語言的表達(dá)力動態(tài)語言通常更方便開發(fā)較小的項目,因為可以無需聲明類型而節(jié)省了很多麻煩。另外一個答案是,動態(tài)類型解除了程序員的束縛,可以最大的 發(fā)揮程序員的編程技能,能最有效的利用編程語言里的各種特征和模式。但這些能力都是一把雙刃劍,更多的依賴于程序員的個人才能,如果用不好,或用的過度, 都會產(chǎn)生負(fù)面的害處。
觀點一:靜態(tài)類型語言因為類型強制聲明,所以IDE可以做到很好的代碼感知能力,因為有IDE的撐腰,所以開發(fā)大型系統(tǒng),復(fù)雜系統(tǒng)比較有保障。
對于像Java來說,IDEA/Eclipse確實在代碼感知能力上面已經(jīng)非常強了,這無疑能夠增加對大型系統(tǒng)復(fù)雜系統(tǒng)的掌控能力。但是除了Java擁有這么強的IDE武器之外,似乎其他語言從來沒有這么強的IDE。C#的Visual Studio在GUI開發(fā)方面和Wizard方面很強,但是代碼感知能力上和Eclipse差的不是一點半點。至于Visual C++根本就是一個編譯器而已,更不要說那么多C/C++開發(fā)人員都是操起vi吭哧吭哧寫了幾十萬行代碼呢。特別是像Linux Kernel這種幾百萬行代碼,也就是用vi寫出來的阿,夠復(fù)雜,夠大型,夠長生命周期。
觀點二:靜態(tài)語言相對比較封閉的特點,使得第三方開發(fā)包對代碼的侵害性可以降到很低。
也就是說靜態(tài)類型語言可以保障package的命名空間分割,從而避免命名沖突,代碼的良好隔離性。但是這個觀點也缺乏說服力。
靜態(tài)類型語言中C,VB都缺乏良好的命名空間分割,容易產(chǎn)生沖突,但是并沒有影響他們做出來的系統(tǒng)就不夠大,不夠復(fù)雜。
而動態(tài)類型語言中Ruby/Python/Perl都有比較好的命名空間,特別是Python和Perl,例如CPAN上面的第三方庫成噸成噸的,也從來沒有聽說什么沖突的問題。
誠然像PHP,JavaScript這樣缺乏命名空間的動態(tài)語言很容易出現(xiàn)問題,但是這似乎是因為他們?nèi)狈O機制導(dǎo)致的,而不是因為他們動態(tài)類型導(dǎo)致的吧?
說到大型系統(tǒng),復(fù)雜業(yè)務(wù)邏輯系統(tǒng),Google公司很多東西都是用python開發(fā)的,這也證明了動態(tài)類型語言并非不能做大型的復(fù)雜的系統(tǒng)。其實我個人認(rèn)為:
動態(tài)類型語言,特別是高級動態(tài)類型語言,反而能夠讓人們不需要分心去考慮程序編程問題,而集中精力思考業(yè)務(wù)邏輯實現(xiàn),即思考過程即實現(xiàn)過程,用DSL描述問題的過程就是編程的過程,這方面像Unix Shell,ruby,SQL,甚至PHP都是相應(yīng)領(lǐng)域當(dāng)之無愧的DSL語言。而顯然靜態(tài)類型語言基本都不滿足這個要求。
那靜態(tài)類型語言的優(yōu)勢究竟是什么呢?我認(rèn)為就是執(zhí)行效率非常高。所以但凡需要關(guān)注執(zhí)行性能的地方就得用靜態(tài)類型語言。其他方面似乎沒有什么特別的優(yōu)勢。
4 Java語言的問題 4.1 生產(chǎn)力問題??開發(fā)調(diào)試慢,整體解決方案復(fù)雜。這只是相對而言,對于熟練的開發(fā)這也許不是問題,作為企業(yè)級解決方案而言,Java語言確實比較繁重,即使依賴了很多自動編譯、動態(tài)加載、打包并部署的持續(xù)集成工具,調(diào)試速度依然很慢,與現(xiàn)在的快節(jié)奏的開發(fā)要求有明顯矛盾. 不過, Java語言的生態(tài)不僅僅是語言, 而是JVM. 所以java語言只是JVM生態(tài)的一個語言.后來者, 有Scala, Groovy, Fantom, Clojure, Ceylon, Kotlin 和Xtend–mostly等.
??
??
4.2 表達(dá)力問題??總體來說Java語言的編寫過程更傾向于過程式的開發(fā),在上一層面上封裝了面向?qū)ο蟮奶卣骱托袨?,語言的設(shè)計是上個世紀(jì)九十年代的風(fēng)格,不是說語言本身不好是其抽象能力不夠,即使到了Java8也只是對Lambda表達(dá)式進行了支持,因此引入了Functional Interface也即只有一個方法的接口,和接口里邊的帶具體實現(xiàn)的方法(為了兼容以前的代碼不得不作出的讓步)。Java語言發(fā)展到現(xiàn)在其語言特性龐大,如果要完全了解需要幾百頁的文檔,在其發(fā)展過程中又只做加法沒又減法,語言慢慢風(fēng)格混雜,變成了現(xiàn)在這種四不像的狀態(tài),函數(shù)式的特性硬生生的嫁接在原來的面向?qū)ο筇匦灾稀?br>??
????一段Java 實體類代碼
?? ?? package com.femon.entity; import java.util.Date; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; /** * @author 一劍 2015年12月23日 下午4:10:18 */ @Entity @Table(name = "cm_service") public class Service { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; private String name; private String host; private String requestUrl; private String responseBody; private String expect; private String method; private int paramsType;// 1 : 普通參數(shù)請求串query str // 2 : header參數(shù) // 3: 表單方式提交參數(shù) // 4: json post請求 private String paramsMap; private String platform;// H5 Web App private int todaySuccessTimes; private int todayFailTimes; /** * 0 失敗 1 正常 */ private int state; private int totalSuccessTimes; private int totalFailTimes; private Date gmtCreate; private Date gmtModify; /** * platform. * * @return the platform * @since JDK 1.7 */ public String getPlatform() { return platform; } /** * platform. * * @param platform * the platform to set * @since JDK 1.7 */ public void setPlatform(String platform) { this.platform = platform; } public String getParamsMap() { return paramsMap; } public void setParamsMap(String paramsMap) { this.paramsMap = paramsMap; } public Date getGmtCreate() { return gmtCreate; } public void setGmtCreate(Date gmtCreate) { this.gmtCreate = gmtCreate; } public Date getGmtModify() { return gmtModify; } public void setGmtModify(Date gmtModify) { this.gmtModify = gmtModify; } public int getTodaySuccessTimes() { return todaySuccessTimes; } public void setTodaySuccessTimes(int todaySuccessTimes) { this.todaySuccessTimes = todaySuccessTimes; } public int getTodayFailTimes() { return todayFailTimes; } public void setTodayFailTimes(int todayFailTimes) { this.todayFailTimes = todayFailTimes; } public int getTotalSuccessTimes() { return totalSuccessTimes; } public void setTotalSuccessTimes(int totalSuccessTimes) { this.totalSuccessTimes = totalSuccessTimes; } public int getTotalFailTimes() { return totalFailTimes; } public void setTotalFailTimes(int totalFailTimes) { this.totalFailTimes = totalFailTimes; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public String getRequestUrl() { return requestUrl; } public void setRequestUrl(String requestUrl) { this.requestUrl = requestUrl; } public String getResponseBody() { return responseBody; } public void setResponseBody(String responseBody) { this.responseBody = responseBody; } public int getState() { return state; } public void setState(int state) { this.state = state; } public String getExpect() { return expect; } public void setExpect(String expect) { this.expect = expect; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public int getParamsType() { return paramsType; } public void setParamsType(int paramsType) { this.paramsType = paramsType; } /** * TODO * * @see java.lang.Object#toString() */ @Override public String toString() { return "Service [id=" + id + ", name=" + name + ", host=" + host + ", requestUrl=" + requestUrl + ", responseBody=" + responseBody + ", expect=" + expect + ", method=" + method + ", paramsType=" + paramsType + ", paramsMap=" + paramsMap + ", platform=" + platform + ", todaySuccessTimes=" + todaySuccessTimes + ", todayFailTimes=" + todayFailTimes + ", state=" + state + ", totalSuccessTimes=" + totalSuccessTimes + ", totalFailTimes=" + totalFailTimes + ", gmtCreate=" + gmtCreate + ", gmtModify=" + gmtModify + "]"; }}
????
而其實,我們早就知道,雖然這些 getter,setter都是模板化的東西, 可以自動生成的,但是這么冗余的代碼,看起來還是不爽!那些寫Java代碼的牛逼程序員老鳥們里面有一個叫Martin Odersky的, 就整了一個基于JVM的支持函數(shù)式又無縫融合OOP的程序設(shè)計語言Scala. 這樣的實體類代碼,在Scala中寫作如下:
??
package com.steda.entity import java.util.Date import javax.persistence.{Entity, GeneratedValue, GenerationType, Id} import scala.beans.BeanProperty @Entity class TedaCase { @Id @GeneratedValue(strategy = GenerationType.AUTO) @BeanProperty var id: Long = _ @BeanProperty var name: String = _ @BeanProperty var interfaceId: Long = _ @BeanProperty var paramJsonStr: String = _ @BeanProperty var expectOutput: String = _ @BeanProperty var actualOutput: String = _ @BeanProperty var dataSourceId: Long = _ @BeanProperty var clearSql: String = _ @BeanProperty var tddlApp: String = _ @BeanProperty var state: Integer = _ @BeanProperty var runTimes: Integer = _ @BeanProperty var owner: String = _ @BeanProperty var gmtCreate: Date = _ @BeanProperty var gmtModify: Date = _ }
?我們再看一個Controller層的寫作, Scala可以與Java生態(tài)中優(yōu)秀的框架無縫融合, 比如Spring,Junit. 尤其當(dāng)今發(fā)展勢頭正猛的SpringBoot, JPA等框架, 更是大大的提升了開發(fā)測試的生產(chǎn)力.
?
?
4.3 資源消耗問題package com.steda.controller
import java.util.Date
import com.steda.dao.{DataSourceDao, TedaCaseDao}
import com.steda.entity.TedaCase
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.ui.Model
import org.springframework.util.StringUtils
import org.springframework.web.bind.annotation._
import org.springframework.web.servlet.ModelAndView@RestController
@RequestMapping(Array("/tedacase"))
class TedaCaseController @Autowired()(private val tedaCaseDao: TedaCaseDao, private val dataSourceDao: DataSourceDao) {@RequestMapping(Array("/newPage/{interfaceId}"))
def goNewPage(@PathVariable(value = "interfaceId") interfaceId: Long, model: Model): ModelAndView = {model.addAttribute("dataSources", dataSourceDao.findAll()) model.addAttribute("interfaceId", interfaceId) new ModelAndView("/tedacase/new")}
@RequestMapping(Array("/editPage/{id}"))
def goEditPage(model: Model, @PathVariable(value = "id") id: Long): ModelAndView = {val tedacase = tedaCaseDao.findOne(id) model.addAttribute("tedacase", tedacase) model.addAttribute("dataSources", dataSourceDao.findAll()) new ModelAndView("/tedacase/edit")}
@RequestMapping(Array("/detailPage/{id}"))
def goDetailPage(model: Model, @PathVariable(value = "id") id: Long): ModelAndView = {val tedacase = tedaCaseDao.findOne(id) model.addAttribute("tedacase", tedacase) new ModelAndView("/tedacase/detail")}
@RequestMapping(value = {
Array("", "/")}, method = Array(RequestMethod.GET))
def list(model: Model, @RequestParam(value = "tedaCaseName", required = false) tedaCaseName: String): ModelAndView = {var tedaCases: java.util.List[TedaCase] = new java.util.ArrayList[TedaCase] if (!StringUtils.isEmpty(tedaCaseName)) { tedaCases = tedaCaseDao.findByName(tedaCaseName) } else { tedaCases = tedaCaseDao.findAll() } model.addAttribute("tedaCases", tedaCases) model.addAttribute("tedaCaseName", tedaCaseName) new ModelAndView("/tedacase/list")}
@RequestMapping(value = Array("/postnew"), method = Array(RequestMethod.POST))
@ResponseBody
def newOne(@RequestParam(value = "name") name: String, @RequestParam(value = "interfaceId") interfaceId: Long,@RequestParam(value = "paramJsonStr") paramJsonStr: String,@RequestParam(value = "expectOutput") expectOutput: String, @RequestParam(value = "owner") owner: String,@RequestParam(value = "clearSql") clearSql: String, @RequestParam(value = "dataSourceId") dataSourceId: Long, @RequestParam(value = "tddlApp") tddlApp: String) = {val teda = new TedaCase() teda.clearSql = clearSql teda.dataSourceId = dataSourceId teda.interfaceId = interfaceId teda.tddlApp = tddlApp teda.expectOutput = expectOutput teda.owner = owner teda.paramJsonStr = paramJsonStr teda.name = name teda.state = -1 // -1 未執(zhí)行 0 失敗 1 成功 teda.runTimes = 0 teda.gmtCreate = new Date() teda.gmtModify = new Date() tedaCaseDao.save(teda)}
@RequestMapping(value = Array("/postedit"), method = Array(RequestMethod.POST))
@ResponseBody
def editOne(@RequestParam(value = "id") id: Long, @RequestParam(value = "name") name: String,@RequestParam(value = "paramJsonStr") paramJsonStr: String,@RequestParam(value = "expectOutput") expectOutput: String, @RequestParam(value = "owner") owner: String,@RequestParam(value = "clearSql") clearSql: String, @RequestParam(value = "dataSourceId") dataSourceId: Long, @RequestParam(value = "tddlApp") tddlApp: String) = {val teda = tedaCaseDao.findOne(id) teda.clearSql = clearSql teda.dataSourceId = dataSourceId teda.tddlApp = tddlApp teda.expectOutput = expectOutput teda.owner = owner teda.paramJsonStr = paramJsonStr teda.name = name teda.gmtModify = new Date() tedaCaseDao.save(teda)}
}
??Java語言號稱一次編譯,處處運行,就在于它基于一個需要首先先安裝到他所謂的處處的JDK,通過JVM解析編譯完成后的字節(jié)碼來運行,跟操作系統(tǒng)的接口也是在JVM托管的。這樣的好處是JVM可以在實時運行的時候?qū)ψ止?jié)碼進行進一步的優(yōu)化,也就是大名鼎鼎的JIT,問題是所有的機器上都要安裝可以兼容你的應(yīng)用程序的JDK,同時JVM啟動消耗的資源不少,起碼數(shù)百M,且啟動速度緩慢,同樣的直接編譯成目標(biāo)操作系統(tǒng)二進制可執(zhí)行程序的服務(wù),啟動起來消耗的資源小很多且速度快了很多。
在當(dāng)前差異化的芯片結(jié)構(gòu)中,像C、GO、RUST這種能直接運行于操作系統(tǒng)之上不基于某些龐大繁重的VM之上還是很有必要的,比如物聯(lián)網(wǎng)的控制芯片,通常內(nèi)存也只有幾百K,適用性更強一些,而且現(xiàn)在LLVM架構(gòu)的編譯器能夠帶來性能的大幅優(yōu)化,所以編譯依然是一個很好的選擇,除非JIT能夠逆天的達(dá)到解釋執(zhí)行的極限,因此假如我們看到某些語言有Java語言的開發(fā)能力和內(nèi)存安全特性,依然是可以考慮的。
5 Haskell, Go, Scala 5.1 Haskell他雖然很老但是一直是作為學(xué)院派函數(shù)式語言的代表,其純函數(shù)式的特性和簡潔漂亮的語法(糖)讓人看了非常舒服,在接觸了面向過程和面向?qū)ο蟮拈_發(fā)后,如果要學(xué)習(xí)一種新的寫代碼的思路,面向函數(shù)式的語言是目前最好的選擇了,而Haskell有是函數(shù)式語言的先驅(qū)和集大成者,很多函數(shù)式語言的語法都是從Haskell借鑒來的。
作為純函數(shù)式語言,Haskell將必然會產(chǎn)生Side-Effect的代碼比如IO操作放到了一起,也即monad風(fēng)格的部分,而其他的函數(shù)可以保證完全的函數(shù)式特征,對于同樣的輸入無論運行多少次結(jié)果都是一樣的,跟數(shù)學(xué)中函數(shù)的定義一樣嚴(yán)格,函數(shù)式是一種CPU友好的語言,在當(dāng)前多核計算機發(fā)展?fàn)顩r下,函數(shù)式可以讓程序非常安全的在多個核心上并發(fā)而不用擔(dān)心大量的數(shù)據(jù)交互和side-effect, 從而在語言編譯過程中能夠針對并發(fā)進行大幅的優(yōu)化。語言本身的很多寫法也跟數(shù)學(xué)中的定義很接近,比如定義一個集合
ghci> [x*2 | x <- [1..10]] [2,4,6,8,10,12,14,16,18,20]
看起來很像數(shù)學(xué)定義,語言可謂優(yōu)雅漂亮,看著很舒服。作為學(xué)院派語言,語言自身設(shè)計的要求不可謂不嚴(yán)格,完美的闡述了函數(shù)式是什么意思,但是語言的復(fù)雜度較高,學(xué)習(xí)曲線很陡峭,很難保證團隊成員的接收程度,也很難招到相關(guān)的技術(shù)人才。從效率上來講,Haskell可以優(yōu)化的跟C語言的級別類似,但如果對某些特性不熟悉稍微改動一些就會造成性能的大幅下降,對新手不算友好。
同時在函數(shù)式不那么擅長的領(lǐng)域Haskell的商業(yè)化程度很低,我們不可能都用Haskell來寫一些語法解釋或者正則解析等,涉及IO的分布式存儲和計算都相對很初級,尤其是對于我們比較感興趣的數(shù)據(jù)挖掘機器學(xué)習(xí)領(lǐng)域沒有成熟的解決方案,對于Web項目支持的尚可,有優(yōu)秀的Yesod框架作為代表。
總的來說,Haskell值的學(xué)習(xí)但不會在大型的生產(chǎn)環(huán)境中使用。
5.2 Scala??Scala語言的出現(xiàn)目的很明確,感覺就是為了替代Java而存在,在Java語言越來越力不從心的今天,能夠有一門語言既繼承了它廣大的生態(tài)系統(tǒng),又能夠在表達(dá)能力和開發(fā)效率大大改進的情況,可以說是很有希望的。
Scala從一開始就是一門設(shè)計良好的語言,幾乎完美的集合了函數(shù)式的特性和面向?qū)ο蟮奶匦裕m然他的函數(shù)式不是純函數(shù)式。其面向?qū)ο蟮母杏X更像Ruby而不是Java,所有的東西都是對象,包括簡單類型例如Int,以及函數(shù)本身都是一種對象,這樣在這個層面實現(xiàn)了面向?qū)ο蠛秃瘮?shù)式的統(tǒng)一。
Scala運行于JVM之上,能夠無縫的使用所有的原來Java語言所開發(fā)的各種庫,語言上作為Java的超集,遷移過來只會更強大而不會打折。
Java8的出現(xiàn)雖然增加了針對集合的stream api以及Lambda表達(dá)式這種函數(shù)式特性的支持,但只會讓人們覺得Java與Scala更像了,即使Java在以后的發(fā)展過程中擁有了所有的Scala的能力.
打個比方一塊歪歪扭扭的經(jīng)過各種后期焊接所建造起來的機器和一個一開始就有目的的設(shè)計出來的結(jié)構(gòu)精密、風(fēng)格統(tǒng)一、表達(dá)高效的機器比較,后者更像前者的重構(gòu),而前者雖然如日中天但已經(jīng)是暮年的四不像,不停的往身上增加各種各樣的功能.
也許Java9會有進步,但現(xiàn)在我看到Java8后反而更傾向于Scala。
Scala的元編程能力可以讓他修改自己的語言定義,不只是實現(xiàn)某些業(yè)務(wù)邏輯,這樣從符號層面上,scala可以做到自洽,除了核心的一些規(guī)則,其他的都可以被自己根據(jù)狀態(tài)調(diào)整所修改,這種能力可以極大的擴展語言自身的能力,當(dāng)然也帶來了一些負(fù)面效果,每學(xué)習(xí)一種新的包不只是了解他的API,而是學(xué)習(xí)了一種新的語言,風(fēng)格可能跟scala大不相同。
強有力的證明,大數(shù)據(jù)生態(tài)系統(tǒng)代表-Spark&Kafka,一個是分布式計算一個是分布式大規(guī)模數(shù)據(jù)吞吐,都證明了Scala的開發(fā)能力和效率。
5.3 GoScala的問題其實也有跟Java類似的地方,首先這個語言雖然是重新設(shè)計的,但是使用起來復(fù)雜度依然很高,對于范型的繼承,+-等范型標(biāo)注不好理解,
??Go語言目前呈現(xiàn)了很火爆的趨勢,由于其簡單,整個語言的specification也不過十幾頁,最多半天就能夠完全了解并上手寫一些小工具。GO語言最初是希望替代C和C++成為新的系統(tǒng)語言,自帶GC垃圾回收,不過最終更多的是替代了python來開發(fā)一些服務(wù)或者工具,并沒有成為系統(tǒng)級別的語言。
??Go語言有很多的優(yōu)點,編譯速度快,有協(xié)程和Channel做并發(fā)支持和通信,有很多官方的網(wǎng)絡(luò)協(xié)議的庫,非常適合于寫一些網(wǎng)絡(luò)服務(wù),啟動一個http的接口服務(wù)只需要幾行代碼。目前github上也有大量的第三方項目使用go語言來開發(fā)應(yīng)用或者擴展go的功能,在使用的時候直接import即可。Go的多返回機制也還不錯,節(jié)省了大量的無意義數(shù)據(jù)結(jié)構(gòu)和不可讀的Map的使用,總的來說Go在其擅長的領(lǐng)域生產(chǎn)力很高,寫起來比較流暢,靜態(tài)類型也足夠的安全。目前Docker生態(tài)系統(tǒng)里邊的各種工具都是Go來寫的。最新發(fā)布的1.5版本使得交叉編譯更加容易,靜態(tài)鏈接庫的方式使生成的可執(zhí)行文件在相同CPU架構(gòu)的操作系統(tǒng)都能運行,減少了額外查找依賴的問題,對我們現(xiàn)在基本同構(gòu)的Linux服務(wù)器而言,也打到了一次編譯處處運行的目的。同時Go語言在運行時消耗的資源也比Java要小,啟動速度更快,確實是輕量級服務(wù)的優(yōu)選。
??
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/65859.html
摘要:通常一個完成的不僅僅包含了還包括了以及相關(guān)版本該版本在中使用?;谠秃瘮?shù)先行的語言使用基于原型的的繼承機制,函數(shù)是的第一等公民其他相關(guān)的語言特性編譯型語言把做好的源程序全部編譯成二進制代碼的可運行程序。 轉(zhuǎn)載請注明出處,創(chuàng)作不易,更多文章請戳 https://github.com/ZhengMaste... 前言:JavaScript誕生于1995年,它是一門腳本語言,起初的目...
摘要:所有變量的類型在編譯時已知在程序運行之前,因此編譯器也可以推導(dǎo)出所有表達(dá)式的類型。像變量的類型一樣,這些聲明是重要的文檔,對代碼讀者很有用,并由編譯器進行靜態(tài)檢查。對象類型的值對象類型的值是由其類型標(biāo)記的圓。 大綱 1.編程語言中的數(shù)據(jù)類型2.靜態(tài)與動態(tài)數(shù)據(jù)類型3.類型檢查4.易變性和不變性5.快照圖6.復(fù)雜的數(shù)據(jù)類型:數(shù)組和集合7.有用的不可變類型8.空引用9.總結(jié) 編程語言中的數(shù)據(jù)...
摘要:我們的目標(biāo)是建立對每一種語言的認(rèn)識,它們是如何進化的,未來將走向何方。有點的味道是堅持使用動態(tài)類型,但唯一還收到合理擁泵的編程語言,然而一些在企業(yè)的大型團隊中工作的開發(fā)者擇認(rèn)為這會是的一個缺陷。 為什么我們需要如此多的JVM語言? 在2013年你可以有50中JVM語言的選擇來用于你的下一個項目。盡管你可以說出一大打的名字,你會準(zhǔn)備為你的下一個項目選擇一種新的JVM語言么? 如今借助來自...
摘要:原文鏈接有大量平均水平左右的工人可被選擇參與進來這意味著好招人有成熟的大量的程序庫可供選擇這意味著大多數(shù)項目都是既有程序庫的拼裝,標(biāo)準(zhǔn)化程度高而定制化場景少開發(fā)工具測試工具問題排查工具完善,成熟基本上沒有團隊愿意在時間緊任務(wù)重的項目情況 原文鏈接:http://pfmiles.github.io/blog/java-groovy-mixed/ 有大量平均水平左右的工人可被選擇、參與...
摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
閱讀 1563·2021-11-17 09:33
閱讀 1113·2021-11-12 10:36
閱讀 2425·2019-08-30 15:54
閱讀 2449·2019-08-30 13:14
閱讀 2924·2019-08-26 14:05
閱讀 3300·2019-08-26 11:32
閱讀 3012·2019-08-26 10:09
閱讀 3005·2019-08-26 10:09