一、為什么聲明性語(yǔ)言往往適合于并行執(zhí)行
函數(shù)式編程里的程序在輸入相同時(shí)總是得到相同的輸出,不包含其他狀態(tài),也不影響其他程序的狀態(tài),所以在哪里執(zhí)行都一樣,這樣就很容易調(diào)度到其他線程、進(jìn)程甚至遠(yuǎn)程服務(wù)器上。而命令式代碼通常隱含地使用全局狀態(tài),這些狀態(tài)在不同代碼之間是共享的,代碼的執(zhí)行時(shí)序會(huì)影響執(zhí)行結(jié)果,這就導(dǎo)致難以并行化。
但這并非沒(méi)有代價(jià)。純粹的函數(shù)式編程無(wú)法處理帶有狀態(tài)的外部組件,而磁盤(pán)讀寫(xiě)、網(wǎng)絡(luò)輸入輸出等IO操作天生是有狀態(tài)的,如果不能處理這些對(duì)象,語(yǔ)言的適用范圍是很窄的。所以函數(shù)式編程語(yǔ)言通常也會(huì)要么帶有命令式的支持,要么將處理有狀態(tài)的對(duì)象的過(guò)程封裝到某些外部的統(tǒng)一模型當(dāng)中(比如Erlang的消息機(jī)制)
聲明性范式只要求程序員提供程序的目的,然后系統(tǒng)自己有編譯器,lib或優(yōu)化器去計(jì)算出”怎么達(dá)到目的”較好的執(zhí)行路徑,而不用程序員提供怎么達(dá)到目的方法或者h(yuǎn)int。而命令式范式需要程序員手把手的告訴機(jī)器怎么完成任務(wù)。機(jī)器無(wú)法區(qū)分目的和手段,而必須嚴(yán)格按照程序指定的來(lái)執(zhí)行。
相比之下,就是根據(jù)“優(yōu)化器”計(jì)算出來(lái)的執(zhí)行路徑好,還是人指定的好呢?(把“好”定義為價(jià)值除以產(chǎn)生價(jià)值需要的時(shí)間)
舉個(gè)例子: 對(duì)SQL來(lái)說(shuō),你只需要指定你想找什么。數(shù)據(jù)庫(kù)會(huì)自己算出來(lái)怎么按照你的要求找。 你如果用java或C在一大塊硬盤(pán)上找數(shù)據(jù),你就要自己去指定機(jī)器每一步怎么運(yùn)行才能給你結(jié)果。
延伸閱讀:
二、聲明式與命令式
命令式(Imperative)和聲明式(Declarative)是很早就有的概念,比如 SQL、HTML、CSS 是典型的聲明式語(yǔ)言,而我們使用的絕大部分編程語(yǔ)言都是命令式的。
命令式編程就像它的名字一樣,它由開(kāi)發(fā)者我們一步一步的告述計(jì)算機(jī),執(zhí)行一系列的操作,然后得到想要的結(jié)果,起主要作用的是開(kāi)發(fā)者,計(jì)算機(jī)只是幫助開(kāi)發(fā)者執(zhí)行計(jì)算而已。
而聲明式編程卻與此相反,它不是告述計(jì)算機(jī)做什么做,而是直接告述計(jì)算它想要的結(jié)果,至于怎么做,由預(yù)先寫(xiě)好的程序依據(jù)一定的算法由計(jì)算機(jī)自動(dòng)推算出來(lái)。
聲明式與命令式的主要區(qū)別在于,聲明式描述的是結(jié)果,它不關(guān)心過(guò)程。比如 SQL,我們告述數(shù)據(jù)庫(kù)的是,我們要查詢某張表滿足某某條件的數(shù)據(jù),但我們并不會(huì)告述數(shù)據(jù)庫(kù)怎么去查,怎么查數(shù)據(jù)是數(shù)據(jù)庫(kù)系統(tǒng)自己關(guān)心的事情。