簡體   English   中英

功能編程效率與命令式

[英]functional programming efficiency vs imperative

我是函數式編程的新手,我只是遇到了一些問題,並且想知道是否有辦法解決這個問題。

假設我有

myArray = [
  { a : 1 }
  { a : 4 }
  { a : 5 }
  { a : 6 }
  { a : 7 }
  { a : 8 }
]

假設我需要對此數據集進行統計操作,例如

const median = myArray[ Math.ceil( myArray.length / 2 ) ]['a'] // Math.ceil .. Side Effect?
const fiveOrMore = myArray.filter( value => value.a >= 5 )
const lessThanFive = myArray.filter( value => value.a < 5 )

一些隨意的例子。 目前的問題是,隨着我需要做的統計操作量的增加,效率會降低。

憑借命令式的風格,我可以在ONE for循環中做所有事情。 這是我正在采用的函數式編程的錯誤方法還是功能編程范式本身的折衷

功能風格你也可以在一個減少中完成它。 只需要一個檢查元素在下面的函數,累加器就是一個帶有兩個列表的結構,你要添加元素。

如果您正在考慮通過一系列高階函數傳遞列表,那么您可以減少Trancducers的開銷,這基本上像個別map一樣工作, filter但操作之間沒有列表。

如果您可能不會使用結果中的所有元素,則會有使用延遲評估的

還有發電機 基本上,你可以多次for循環和使用ỳield來“回報”的值,你可以鏈接這些,因為所有發電機可以用迭代for of 此外,只要有足夠的數據,您就可以暫停。

所以這些都有利有弊。 如果你要使用生成器和流來計算所有元素將會有一點性能。 傳感器可能是一個更好的選擇,它可以提供很少的列表制作的可組合性,但循環當然會更快。

通過功能實現,測試更容易,您可以測試隔離的各個階段。 規則整個應用程序的一個非常大的循環通常很難調試。 當你有一個只在功能樣式中重寫一個循環的reduce時,這也會發生。

這當然不那么高效。 而性能的提升取決於您選擇的風格。

有人可能認為這不是什么大問題,因為時間復雜度是O(n)唯一的區別是常數 我會說確保你對應用程序進行性能測試。 如果它很慢 - 是時候優化某些代碼塊了。

過早優化是邪惡的。 在許多情況下,命令式代碼比功能性代碼更快或更快地運行得快得多,並且根據情況你可能會或可能不會那么好。

此外,還有各種技術可以改善性能。 你不一定要改變風格。 比方說,在某些情況下, memoization可以大大提高函數的速度,同時保持代碼的功能。 只是在盒子外思考。

你可以用功能或命令式的方式將事物塞進一個循環中。 這兩種風格中都會損害可讀性。 這兩種樣式中,編譯器都可以進行循環融合以消除額外的循環。 此外,單個循環並不總是更快,編譯器將能夠辨別融合比人類更容易融合的情況。

正如Sylwester指出的那樣,函數式編程有許多技術可以讓你分別編寫循環但是一起執行它們。 功能樣式也更容易顯式並行化到多個線程上。

通常還有庫函數已經在單個循環中執行了您想要的操作,並且更具描述性和更簡潔。 例如,您的最后兩行可以使用分區完成:

_.partition(myArray, x => x['a'] < 5)

我的一個口號是:

“我不在乎我能以多快的速度計算出錯誤的答案。”

我可能會嘗試編寫一些超快速代碼,但如果我的代碼很難理解並因此很容易引入錯誤/很難發現錯誤,那么它就有風險。 除非代碼對執行速度至關重要,否則我選擇的方法最容易表達我正在嘗試做的事情:有時功能方法可以使您的意圖非常清晰,而在其他情況下,命令更合適。

一旦我有了可行的代碼,並通過了一組單元測試,我就可以根據需要重寫以尋求更快的速度。

順便說一下,這就是我現在享受Swift的原因 - 我有功能和必要的選擇。 哦,我知道它不是純粹的功能,但是用我的工程而不是計算機科學的帽子,它足夠接近! ;-)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM