免费观看又色又爽又黄的小说免费_美女福利视频国产片_亚洲欧美精品_美国一级大黄大色毛片

怎么用C++進行函數(shù)式編程-創(chuàng)新互聯(lián)

本篇內(nèi)容主要講解“怎么用C++進行函數(shù)式編程”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“怎么用C++進行函數(shù)式編程”吧!

古浪ssl適用于網(wǎng)站、小程序/APP、API接口等需要進行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為創(chuàng)新互聯(lián)建站的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:028-86922220(備注:SSL證書合作)期待與您的合作!

用C++進行函數(shù)式編程

純函數(shù)

純函數(shù)是這樣一種函數(shù):它只會查看傳進來的參數(shù),它的全部行為就是返回基于參數(shù)計算出的一個或多個值。它沒有邏輯副作用。這當(dāng)然只是一種抽象;在CPU層面,每個函數(shù)都是有副作用的,多數(shù)函數(shù)在堆的層面上就有副作用,但這一抽象仍然有價值。

純函數(shù)不查看也不更新全局狀態(tài),不維護內(nèi)部狀態(tài),不執(zhí)行任何I/O操作,也不更改任何輸入?yún)?shù)。好不要傳遞任何無關(guān)的數(shù)據(jù)給它——如果傳一個allMyGlobals指針進來,這一目標就基本破滅了。

純函數(shù)有許多良好的屬性。

  • 線程安全 使用值參數(shù)的純函數(shù)是徹底線程安全的。使用引用或指針參數(shù)的話,就算是const的,你也應(yīng)當(dāng)知曉一個執(zhí)行非純操作的線程可能更改或釋放其數(shù)據(jù)的風(fēng)險。但即便是這種情況,純函數(shù)仍不失為編寫安全多線程代碼的利器。你可以輕松地將一個純函數(shù)替換為并行實現(xiàn),或者運行多種實現(xiàn)并比較結(jié)果。這讓代碼的試驗和演化都更加便利。

  • 可復(fù)用性 移植一個純函數(shù)到新的環(huán)境要容易很多。類型定義和所有被調(diào)用的其他純函數(shù)仍然需要處理,但不會有滾雪球效應(yīng)。有多少次,你明明知道另一個系統(tǒng)有代碼可以實現(xiàn)你的需要,但要把它從所有對系統(tǒng)環(huán)境的假設(shè)中解脫出來,還不如重寫一遍來得容易?

  • 可測試性 純函數(shù)具有引用透明性(referential
    transparency),也就是說,不論何時調(diào)用它,對于同一組參數(shù)它永遠給出同樣的結(jié)果,這使它跟那些與其他系統(tǒng)相互交織的東西比起來更易于使用。在編寫測試代碼的問題上,我從來沒有特別盡責(zé);太多代碼與大量系統(tǒng)交互,以至于使用它們需要相當(dāng)精細的控制,而我常常能夠說服自己(也許不正確)這樣的付出并不值得。純函數(shù)很容易測試,其測試代碼就像直接從教料書上摘抄下來的一樣:構(gòu)造一些輸入并查看結(jié)果。每次遇到一小段目前看起來有些奇技淫巧的代碼,我都會把它拆成一個單獨的純函數(shù)并編寫測試。可怕的是,我常常發(fā)現(xiàn)這樣的代碼中存在問題,意味著我撒下的測試安全網(wǎng)還不夠大。

  • 可理解性與可維護性 輸入和輸出的限制使得純函數(shù)在需要時更易于重新學(xué)習(xí),由于文檔不足而隱藏了外部信息的情況也會更少。

形式系統(tǒng)和軟件的自動推理將來會越來越重要。靜態(tài)代碼分析今天已經(jīng)很重要了,將代碼轉(zhuǎn)換成更加函數(shù)式的風(fēng)格有助于工具對它的分析,或者至少能讓速度更快的局部工具所覆蓋的問題跟速度慢且更加昂貴的全局工具一樣多。我們這個行業(yè)講的是“把事情做出來”,我還看不到關(guān)于整個程序“正確性”的形式證明能成為切實的目標,但能夠證明代碼的特定部分不存在特定種類的問題也是很有價值的。我們可以在開發(fā)過程中多運用一些科學(xué)和數(shù)學(xué)成果。

正在修編程導(dǎo)論課的同學(xué)可能一邊撓頭一邊想:“不是所有的程序都要這么寫嗎?”現(xiàn)實情況卻是“大泥球”(Big Balls of Mud)程序多,架構(gòu)清晰的程序少。傳統(tǒng)的命令式編程語言為你提供了安全艙口,結(jié)果它們就總是被使用。如果你只是寫一些用一下就扔掉的代碼,那就怎么方便怎么來,用到全局狀態(tài)也是常事。如果你在編寫一年之后仍將使用的代碼,那就要將眼前的便利因素跟日后不可避免的麻煩平衡一下了。大部分程序員都不擅長預(yù)測日后改動代碼將會導(dǎo)致的各種痛苦。

“純粹性”實踐

并非所有東西都可以是純的,除非程序只操作自己的代碼,否則到某個點總要與外部世界交互。嘗試較大限度地推進代碼的純粹性可以帶來難以想象的樂趣,然而,要達到一個務(wù)實的臨界點,我們需要承認副作用到某一刻是必要的,然后有效地管理它們。

即使對某個特定的函數(shù)而言,這都不是一個“要么全有要么全無”的目標。隨著一個函數(shù)的純度不斷提高,其價值可以連續(xù)增大,而且從“幾乎純粹”到“完全純粹”帶來的價值要低于從“意大利面條狀態(tài)”到“基本純粹”帶來的價值。只要讓函數(shù)朝著純粹的目標前進,即使不能達到完全的純度,也能改善你的代碼。增減全局計數(shù)器或檢查一個全局調(diào)試標志的函數(shù)是不純的,但如果那是它的不足,它仍然可以收獲函數(shù)式的大部分好處。

避免在更大的上下文中造成最壞的結(jié)果通常比在有限的情形中達到完美狀態(tài)更加重要。考慮一下你曾經(jīng)對付過的最令人不爽的函數(shù)或系統(tǒng),那種只有全副武裝才能應(yīng)付的,幾乎可以確定,其中必有復(fù)雜的狀態(tài)網(wǎng)絡(luò)和代碼行為所依賴的各種假設(shè),而這些復(fù)雜性還不只發(fā)生在參數(shù)上。在這些方面強化一下約束,或至少努力防止更多的代碼陷入類似的混亂局面,帶來的影響將比擠壓幾個底層的數(shù)學(xué)函數(shù)大得多。

朝著純粹性的目標重構(gòu)代碼,這一過程通常包含將計算從它所運行的環(huán)境中解脫出來,這幾乎必然意味著更多的參數(shù)傳遞。似乎有點奇特——編程語言中的煩瑣累贅已被人罵夠了,而函數(shù)式編程卻常常與代碼體積的減少相關(guān)。函數(shù)式編程語言寫的程序會比命令式語言的實現(xiàn)更加簡潔,其中的因素與使用純函數(shù)在很大程度上是正交的,這些因素包括垃圾回收、強大的內(nèi)建類型、模式匹配、列表推導(dǎo)、函數(shù)合成以及各種語法糖等。程序體積的減少多半與函數(shù)式無關(guān),某些命令式語言也能帶來同樣的效果。

如果你必須給一個函數(shù)傳遞十多個參數(shù),惱火是應(yīng)該的,你可以通過一些降低參數(shù)復(fù)雜性的方法來重構(gòu)代碼。C++中沒有任何維護函數(shù)純粹性的語言支持,這確實不太理想。如果有人通過一些不好的方法把一個大量使用的基礎(chǔ)函數(shù)變得不再純粹,所有使用這一函數(shù)的代碼便統(tǒng)統(tǒng)失去了純粹性。從形式系統(tǒng)的角度聽起來這是災(zāi)難性的,但還是那句話,這并不是一念之惡便與佛無緣的那種“要么全有要么全無”的主張。很遺憾,大規(guī)模軟件開發(fā)中的問題只能是統(tǒng)計意義上的。

看來未來的C/C++語言標準很有必要增加一個“pure”關(guān)鍵字。C++中已經(jīng)有了一個近似的關(guān)鍵字const—一個支持編譯時檢查程序員意圖的可選修飾符,加上它對代碼百利而無一害。D語言倒是提供了一個“pure”關(guān)鍵字:http://www.d-programming-language.org/function.html。注意它們對弱純粹性和強純粹性的區(qū)分—要達到強純粹,輸入?yún)?shù)中的引用或指針需要使用const修飾。

從某些方面來看,語言關(guān)鍵字過于嚴格了—一個函數(shù)即使調(diào)用了非純粹的函數(shù)也仍然可以是純粹的,只要副作用不逃出函數(shù)之外即可。如果一個程序只處理命令行參數(shù)而不操作隨機的文件系統(tǒng)狀態(tài),那么整個程序都可看做純粹的函數(shù)式單元。

面向?qū)ο蟪绦蛟O(shè)計

Michael Feathers(twitter @mfeathers)說:OO通過把移動的部件封裝起來使代碼可理解。FP通過把移動的部件減到最少使代碼可理解。

“移動的部件”就是更改中的狀態(tài)。通知一個對象改變自己,這是面向?qū)ο缶幊袒A(chǔ)教材的第一課,在大多數(shù)程序員的觀念中根深蒂固,但它卻是一種反函數(shù)式的行為。將函數(shù)和它們操作的數(shù)據(jù)結(jié)構(gòu)組織在一起,這一基本的OOP思想顯然有其價值,但如果想在自己的部分代碼中獲得函數(shù)式編程的好處,那么在這些部分,你必須疏遠一下某些面向?qū)ο蟮男袨椤?/p>

無法聲明為const的類方法從定義上就是不純的,因為它們要修改對象的部分或全部狀態(tài)集合,這一集合可能十分龐大。它們也不是線程安全的,這里戳一下,那里捅一下,一點一點地把對象置成了非預(yù)期的狀態(tài),這種力量才真正是Bug的不竭之源。如果不考慮那個隱含的const this指針,從技術(shù)角度const對象方法仍可看做純函數(shù),但許多對象十分龐大,大到它本身就足以構(gòu)成一種全局狀態(tài),從而弱化了純函數(shù)的在簡潔清晰上的一些好處。構(gòu)造函數(shù)也可以是純函數(shù),通常應(yīng)該努力使之成為純函數(shù)——它們接受參數(shù)并返回一個對象。

從靈活編程的層面來看,你常常可以用更加函數(shù)式的方法使用對象,但可能需要一點接口上的改變。在id Software,我們曾有十年時間在使用一個idVec3類,它只有一個改變自己的void Normalize()方法,卻沒有相應(yīng)的idVec3 Normalized() const方法。許多字符串方法也是以類似的方式定義的,它們操作自身,而不是返回執(zhí)行過相應(yīng)操作的一個新的副本——比如ToLowerCase()、StripFileExtension()等。

性能影響

在任何情況下,直接修改內(nèi)存塊幾乎都是無法逾越的最優(yōu)方案,而不這么做就難免犧牲性能。多數(shù)時候這只有理論上的好處,我們一向都在用性能換生產(chǎn)率。

使用純函數(shù)編程會導(dǎo)致更多的數(shù)據(jù)復(fù)制,出于性能方面的考慮,某些情況下這顯然會成為不正確的實現(xiàn)策略。舉個極端的例子,你可以寫一個純函數(shù)的DrawTriangle(),接受一個幀緩存(framebuffer)參數(shù)并返回一個全新的畫上三角形的幀緩存作為結(jié)果。可別這么做。

按值返回一切結(jié)果是自然的函數(shù)式編程風(fēng)格,然而總是依靠編譯器實施返回值優(yōu)化會對性能造成危害,因此對于函數(shù)輸出的復(fù)雜數(shù)據(jù)結(jié)構(gòu),傳遞引用參數(shù)常常是合理的,但這么也有不好的一面:它阻止你將返回值聲明為const以避免多次賦值。

很多時候人們都有強烈的欲望去更新傳入的復(fù)雜結(jié)構(gòu)中的某個值,而不是復(fù)制一份副本并返回修改后的版本,但這樣等于舍棄了線程安全保障,因此不要輕易這么做。列表的產(chǎn)生倒是一種可以考慮就地更新的合理情形。往列表中追加新的元素,純函數(shù)式的做法是返回尾端包含新元素的一個全新列表副本,原先的列表則保持不變。真正的函數(shù)式語言都在實現(xiàn)上運用了特別手法,從而使這種行為的后果沒有聽上去那么糟糕,但如果在典型的C++容器上這么做,那你就死定了。

一項重要的緩解因素是,如今性能意味著并行程序設(shè)計,相比單線程環(huán)境,并行程序即使在性能最優(yōu)的情形中也需要更多的復(fù)制與合并操作,因此復(fù)制造成的損失減少了,而復(fù)雜性的降低和正確性的提高這兩方面的好處相應(yīng)增加了。例如,當(dāng)開始考慮并行地運行一個游戲世界中的所有角色時,你就會漸漸明白,用面向?qū)ο蟮姆椒▉砀聦ο螅@在并行環(huán)境中難度很大。或許所有對象都引用了世界狀態(tài)的一個只讀版本,而在一幀結(jié)束時卻復(fù)制了更新后的版本……嗨,等一下……

如何行動

在自己的代碼庫中檢查某些有一定復(fù)雜度的函數(shù),跟蹤它能觸及的每一比特外部狀態(tài)以及所有可能的狀態(tài)更新。即使對它不做一點改動,把這些信息放入一個注釋塊就已經(jīng)是好的文檔了。如果函數(shù)能夠——比方說,通過渲染系統(tǒng)觸發(fā)一次屏幕刷新,你就可以直接把手舉在空中,聲明這個函數(shù)所有的正副作用已經(jīng)超出了人類的理解力。你要著手的下一項任務(wù)是基于實際執(zhí)行的計算從頭開始重新考慮這個函數(shù)。收集所有的輸入,把它傳給一個純函數(shù),然后接收結(jié)果并做相應(yīng)處理。

調(diào)試代碼的時候,讓自己著重了解那些更新的狀態(tài)和隱藏的參數(shù)悄然登場,從而掩蓋實際動作的部分。修改一些工具對象的代碼,讓函數(shù)返回新的副本而不是修改自身,除了迭代器,試著在自己使用的每個變量之前都加上const。

到此,相信大家對“怎么用C++進行函數(shù)式編程”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)建站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

網(wǎng)頁名稱:怎么用C++進行函數(shù)式編程-創(chuàng)新互聯(lián)
鏈接地址:http://m.newbst.com/article2/ccjgic.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站維護品牌網(wǎng)站建設(shè)云服務(wù)器自適應(yīng)網(wǎng)站虛擬主機定制網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

營銷型網(wǎng)站建設(shè)