您好,登錄后才能下訂單哦!
這篇文章主要介紹了匯編語言的函數式編程實例分析的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇匯編語言的函數式編程實例分析文章都會有所收獲,下面我們一起來看看吧。
要了解函數式編程,我們需要首先了解函數。 這聽起來可能很無聊,但總而言之,它很有見地。
簡單地說,函數是將輸入轉換為輸出的東西。只是事情并沒有那么簡單。思考一下,在Python
中的下面這個函數的意義:
def square(x): return x*x
這個函數很簡單。 它需要一個變量x
,可能是一個int
,或者是一個 float
或 double
,然后輸出該變量的平方。
再思考一下下面的這個函數:
global_list = [] def append_to_list(x): global_list.append(x)
乍一看,這個函數接受了一個變量 x
,無論是哪種類型,由于沒有 return
語句,它什么也不返回。事實真的是這樣嗎?
如果事先沒有定義 global_list
,那么這個函數就不能工作,它的輸出是相同的列表,盡管經過了修改。雖然 global_list
沒有聲明輸入,但當我們使用該函數時,它就會發生變化:
append_to_list(1) append_to_list(2) global_list
它返回了 [1,2]
,而不是空列表。這可能就是問題所在,列表確實是函數的一個輸入,雖然我們沒有明確說明。
這些隱含的輸入,或者其他情況下的輸出,有一個官方名稱:副作用。雖然我們只列舉了一個簡單的例子,但在更復雜的程序中,這些可能會讓我們面臨真正的困難。
大家可以思考一下該如何測試 append_to_list
:我們不僅需要閱讀第一行并使用任何 x
來測試函數,還需要閱讀整個定義,了解其作用,定義 global_list
并以這種方式進行測試。這個例子告訴我們,當你在處理有數千行代碼的程序時,簡單的東西很快就會變得乏味。
好消息是,有一個簡單的解決方法:對函數作為輸入的內容誠實。這樣更好:
newlist = [] def append_to_list2(x, some_list): some_list.append(x) append_to_list2(1,newlist) append_to_list2(2,newlist) newlist
我們并沒有作太大的改變,輸出結果仍然是 [1,2]
,其他所有內容也保持不變。
但是,我們已經更改了一件事情:該代碼現在沒有副作用。
現在,當我們查看函數聲明時,能確切知道發生了什么。如果程序運行不正常,我們也可以輕松地單獨測試每個功能并查明哪個功能有問題。
具有明確聲明的輸入和輸出的函數是沒有副作用的函數,而沒有副作用的函數就是純函數。
函數編程的一個非常簡單的定義是:僅用純函數編寫程序。純函數永遠不會修改變量,只會創建新的變量作為輸出。
此外,對于給定輸入的純函數,我們可以得到特定的輸出。相反,不純函數可能依賴于某些全局變量。因此,如果全局變量不同,則相同的輸入變量可能導致不同的輸出。后者會讓調試和代碼維護變得更加困難。
這里有一個容易發現副作用的簡單規則:由于每個函數必須具有某種輸入和輸出,因此沒有任何輸入或輸出的函數聲明必須是不純的。如果采用函數式編程,這是你可能想要更改的第一個聲明。
循環不是函數式編程中的東西。首先,我們先來思考以下的Python
循環:
integers = [1,2,3,4,5,6] odd_ints = [] squared_odds = [] total = 0 for i in integers: if i%2 ==1 odd_ints.append(i) for i in odd_ints: squared_odds.append(i*i) for i in squared_odds: total += i
相較于我們要執行的簡單操作,以上代碼明顯過長。而且也沒有起到作用,因為我們正在修改全局變量。
相反,我們可以用以下代碼替代:
from functools import reduce integers = [1,2,3,4,5,6] odd_ints = filter(lambda n: n % 2 == 1, integers) squared_odds = map(lambda n: n * n, odd_ints) total = reduce(lambda acc, n: acc + n, squared_odds)
這是完整的函數式。它比較短,也更快,因為我們不需要迭代太多的數組元素。如果你理解 filter
, map
和 reduce
如何工作,代碼也就不難理解了。
這并不意味著所有的函數代碼都使用 map
、reduce
等。這也不意味著你需要函數式編程來理解 map
和 reduce
。只是當你抽象循環時,這些函數會彈出很多。
在談到函數式編程的歷史時,許多人都是從lambda
函數的發明開始的。 盡管 lambda
是函數式編程毫無疑問的基石,但它們并不是根本原因。
Lambda
函數是可用于使程序起作用的工具。 但是,我們也可以在面向對象的編程中使用lambda
。
上面的示例雖然不是靜態類型的,但是它依然是函數式的。
即使靜態類型為我們的代碼增加了一層額外的安全保護,但是其函數正常也并非必不可少。 不過,這可能是一個不錯的補充。
Perl
對副作用的處理方法與大多數編程語言截然不同。它包含了一個神奇的參數 $\
。Perl
確實有它的優點,但我不會用它進行函數式編程。
如果你在用 Java
進行函數式編程,那我只能祝你好運了。因為你的程序有一半是由靜態關鍵字組成的,而且其他 Java
開發人員也會把你的程序視為恥辱。
這并不是說 Java
有多糟糕,而是因為它并不是為那些用函數式編程解決問題而設計的,比如數據庫管理或機器學習應用程序。
有趣的是:Scala
的目標是統一面向對象和函數式編程。如果你覺得這有點奇怪,那你不是一個人,因為所有人都這么覺得:函數式編程的目標是完全消除副作用,而面向對象編程是把副作用保留在對象內部。
盡管如此,很多開發人員認為 Scala
是一種幫助他們從面向對象編程過渡到函數式編程的語言。或許在未來幾年里,它們會更容易全面發揮作用。
Python
鼓勵函數式編程。一個事實就能看到這一點:每個函數在默認情況下至少有一個輸入self
。這很像Python
的禪:顯式比隱式好!
據它的創建者說,Clojure
大約有 80% 是函數式編程。默認情況下,所有值都是不可變的,就像在函數式編程中需要它們一樣。但是,我們可以通過在這些不可變的值周圍使用可變值包裝器來解決這個問題。當你打開這樣一個包裝,你得到的東西又是不變的。
這是為數不多的純函數式和靜態類型的語言之一。雖然在開發過程中這看起來像是一個時間消耗器,但在調試程序時,Haskell
會付出巨大的代價。它不像其他語言那么容易學,但絕對值得投資!
關于“匯編語言的函數式編程實例分析”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“匯編語言的函數式編程實例分析”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。