命令式編程(Imperative) vs聲明式編程( Declarative)

命令式編程(Imperative) vs聲明式編程( Declarative)

4 人贊了文章

最近在向劉編輯@鮪魚da(我也不知道他為什麼結尾有個da,可能是賣萌吧)學習Pytorch,其中提到了Pytorch的兩個特點Imperative programming和Dynamic Computation Graphs. 今天就給大家講講Imperative programming以及和其並列Declarative programming具體指的是什麼。

簡單的定義

  • 命令式編程(Imperative):詳細的命令機器怎麼(How)去處理一件事情以達到你想要的結果(What);
  • 聲明式編程( Declarative):只告訴你想要的結果(What),機器自己摸索過程(How)

以生活中打車到王府井大街作為例子

  • 命令式編程(imperative):詳細描述路徑
    • 下個路口左轉
    • 下個有紅燈的路口右轉
    • 前進100米
    • 在下個路口掉頭
    • 前進1500米
    • 到達王府井大街計程車停車區
  • 聲明式編程(Declarative):只告訴目的地
    • 帶我到王府井大街。

兩者之間各有自己的優缺點,以打車為例子命令式編程(imperative)會給出詳細的路線,這樣做的問題就是如果計程車司機自己知道一條更加優化的路線或者導航軟體知道前方的交通狀況提供了其他路線,但是在命令式編程(imperative)的情況下就司機只能無條件執行用戶命令而無法做出改變。

當你面臨在兩者之間做出選擇使用誰時,最關鍵的是你需要想明白,是否需要給程序詳細的命令。

例子

例子一:SQL資料庫

其實你很早就接觸過聲明式編程語言, SQL語言就是很典型的例子:

SELECT * from userWHERE user_name = Ben

上面是一個很普通的SQL查詢語句,我只只聲明我想要找一個叫Ben的用戶(What) , 就是不說SQL該怎麼(How)去尋找怎麼做。接下來我們看看如果用命令式語言寫會是什麼樣的

//user=[{user_name:ou,user_id=1},.....]var userfor(var i=0;i<user.length;i++){ if(user.user_name=="Ben") { print("find"); break; }}

通過上面的對比你可以看出聲明式語言的優勢-短小精悍,你並不會知道程序的控制流(control flow)我們不需要告訴程序如何去尋找(How),而是只告訴程序我們想要的結果(What),讓程序自己來解決過程(How)。當然SQL具體的細節還是用命令式的編程風格來實現的。

例子二:c#

命令式編程(Imperative)會一步一步的告訴程序該怎麼運行

List<int> array = new List<int> { 1, 2, 3, 4, 5678 };List<int> results = new List<int>();foreach(var num in array){ if (num % 2 != 0) results.Add(num);}

如果使用聲明式編程( Declarative)則會是這樣

List<int> array = new List<int> { 1, 2, 3, 4, 5678 };var results = array.Where( num => num % 2 != 0);

例子三:JavaScript

命令式編程(Imperative)會一步一步的告訴程序該怎麼運行

var array = [1,2,3]var output = []for(var i = 0; i < array.length; i++) { var tmp = array[i] * 2 output.push (tmp)}console.log (output) //=> [2,4,6]

如果使用聲明式編程( Declarative)則會是這樣

var array = [1,2,3,]var output = array.map (function (n) { return n * 2})console.log (output) //=> [2,4,6]

在這裡我們使用了map函數,我們不需要詳細的命令程序做什麼,只需要告訴程序我們需要一個2倍輸出。

通常情況下我們常用的大部分編程語言:c,java,c++等都是命令式編程語言。而像正則表達式(regular expressions)或者邏輯語言(Prolog)則為聲明式語言。

總結

命令式編程更加的精細化,更嚴謹,程序也會一是不夠的執行你的命令。然後聲明式編程能在特定的更高層面代碼領域是給我們帶來效率的提升,程序員只需要對想要的結果(What)進行深思熟慮,程序會自動的解決過程(How)。當然代碼看起來更簡潔也是大大的滿足了眾多強迫症程序猿。

ps.接下來我和劉編輯(就是名字帶da那個人)還會持續給大家更新更多的知識,歡迎大家交流討論。有錯誤也麻煩大家多多指出!


推薦閱讀:

三種面向對象設計思想
Visitor Pattern
js面向對象的原型繼承
面向對象之單例模式

TAG:編程 | 編程範式 | 面向對象編程 |