首頁 後端開發 Golang 從go語言閉包談函數式程式設計

從go語言閉包談函數式程式設計

Jan 07, 2020 pm 05:44 PM
go

從go語言閉包談函數式程式設計

這篇文章從下面幾個面向學習函數式程式設計:

1、數學公式和函數式程式設計有什麼關係

#舉個簡單例子吧,數學中有一個概念叫做映射(y=f(x)),說的通俗一點就是函數啦。而最熟悉的應該就是二次函數(拋物線y=a*x*x b*x c)

現在coding實現求拋物線上某一點的值,我們知道a,b,c是參數,x是自變量,y是因變量,如果是以前,我也許會這麼實現(為了紀念我許久未寫的c ,還是用c 來寫一下)

double getParabola(double a,double b,double c,double x) {
     return a*x*x+b*x+c;
}
登入後複製

 問題一、給定拋物線,求x =2,x=3,x=4時的值,就是下面的做法了

resultA = getParabola(a,b,c,2)
resultB = getParabola(a,b,c,2)
resultC = getParabola(a,b,c,2)
登入後複製

這在程式中,是很正常的做法。但是,如果從數學的角度來看,有沒有辦法變得符合數學公式思考呢?以下是我的另一個實作(這裡用go來實作哈,因為c 我知道怎麼寫),

func getParabola(aa,bb,cc float32){
    var a = aa
    var b = bb
    var c = cc
 
    a := func(x float32) {
           return a*x*x+b*x+c
    }
 
    return a
}
登入後複製

然後,同樣是對於問題一,解決方案如下

parabola := getParabola(a,b,c)
 
resultA := parabola(2)
resultB := parabola(3)
resultC := parabola(4)
登入後複製

是不是跟求函數值一樣?所以,數學關係在函數式程式設計中得到了很好的體現。

2、函數式程式設計有什麼特點,go支援了哪些概念

函數式程式有三大特性

1.變數的不可變性: 變數一經賦值不可改變。如果需要改變,則必須複製出去,然後修改。 go中,string變數一經賦值,不可以像c 那樣,c[2]='a'這樣的修改,而是要明確轉換為[]byte,然後再進行修改。但是已經是另外一塊記憶體了。

2、函數式一等公民: 函數也是變量,可以作為參數,返回值等在程式中傳遞。這個特性,c 和go應該都是支援的。

3、尾遞歸:遞歸的概念在斐波那契數列的時候,就學習過了。如果遞歸很深的話,堆疊可能會爆掉,並導致效能大幅下降。而尾遞歸優化技術,編譯器如果支援的話,可以在每次遞歸時重用stack(尾遞歸表示遞歸調用發生在最後一步,這個時候,之前的結果都作為參數傳遞給最後一步的調用,所以之前的狀態就沒有任何作用了,所以可以重複使用stack)。

函數式程式設計常用技術

1、map&reduce&filter

map用於對每一個輸入,呼叫同一個函數,產生一個輸出,例如c 中的for_each,hadoop裡面的map,python的map等。

reduce用於對每一個輸入,加上上一個輸出,得到下一個輸出,例如python和hadoop中的reduce,

filter用於做過濾,例如c 的count_if等。

2、遞迴

3、pipeline  

把函數實例放到一個陣列或是列表中,然後把資料傳給這個action list,輸入順序地被各個函數所操作(意思是每一個函數的輸出,作為另外一個函數的輸入,資料是流動的,計算是固定的,類似storm的概念),最終得到我們想要的結果。

4、其他(有待進一步學習)

3、函數式程式設計與運行效率

函數式程式設計最重要的一個概念就是函數式一等公民,函數跟變數是一樣的。可以作為參數,傳回值等。不贊成使用賦值語句,所以比較多的使用遞歸,所以函數式程式設計效率一定會比較低。

最近我用的比較多的是閉包,閉包的概念就是一個環境(一個或多個變數)加上一個函數,每一次對閉包表達式求值,都得到一個隔離的結果,這跟普通函數是不一樣的,普通函數就是一段可執行的程式碼,只要入口確定了,呼叫的位置也就確定了。舉個例子,上面拋物線的例子,呼叫

a:=getParabola(0.2,0.1,0.3)
b:=getParabola(0.1,0.1,0.4)
登入後複製

得到的是兩條拋物線。之所以我覺得效率會降低,是因為閉包本身就是一個求值賦值的過程,牽涉到變數的創建銷毀。當然,我沒有實際去測試性能。如果後續發行server效率降低,也許這是一個需要考慮的地方。

更多go語言知識請關注PHP中文網go語言教學專欄。

以上是從go語言閉包談函數式程式設計的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Go WebSocket 訊息如何發送? Go WebSocket 訊息如何發送? Jun 03, 2024 pm 04:53 PM

在Go中,可以使用gorilla/websocket包發送WebSocket訊息。具體步驟:建立WebSocket連線。傳送文字訊息:呼叫WriteMessage(websocket.TextMessage,[]byte("訊息"))。發送二進位訊息:呼叫WriteMessage(websocket.BinaryMessage,[]byte{1,2,3})。

深入理解 Golang 函數生命週期與變數作用域 深入理解 Golang 函數生命週期與變數作用域 Apr 19, 2024 am 11:42 AM

在Go中,函數生命週期包括定義、載入、連結、初始化、呼叫和返回;變數作用域分為函數級和區塊級,函數內的變數在內部可見,而區塊內的變數僅在區塊內可見。

如何在 Go 中使用正規表示式匹配時間戳記? 如何在 Go 中使用正規表示式匹配時間戳記? Jun 02, 2024 am 09:00 AM

在Go中,可以使用正規表示式比對時間戳記:編譯正規表示式字串,例如用於匹配ISO8601時間戳記的表達式:^\d{4}-\d{2}-\d{2}T \d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-][0-9]{2}:[0-9]{2})$ 。使用regexp.MatchString函數檢查字串是否與正規表示式相符。

Golang 技術效能優化中如何避免記憶體洩漏? Golang 技術效能優化中如何避免記憶體洩漏? Jun 04, 2024 pm 12:27 PM

記憶體洩漏會導致Go程式記憶體不斷增加,可通過:關閉不再使用的資源,如檔案、網路連線和資料庫連線。使用弱引用防止記憶體洩漏,當物件不再被強引用時將其作為垃圾回收目標。利用go協程,協程棧記憶體會在退出時自動釋放,避免記憶體洩漏。

Golang 與 Go 語言的區別 Golang 與 Go 語言的區別 May 31, 2024 pm 08:10 PM

Go和Go語言是不同的實體,具有不同的特性。 Go(又稱Golang)以其並發性、編譯速度快、記憶體管理和跨平台優點而聞名。 Go語言的缺點包括生態系統不如其他語言豐富、文法更嚴格、缺乏動態類型。

如何在 IDE 中查看 Golang 函數文件? 如何在 IDE 中查看 Golang 函數文件? Apr 18, 2024 pm 03:06 PM

使用IDE檢視Go函數文件:將遊標停留在函數名稱上。按下熱鍵(GoLand:Ctrl+Q;VSCode:安裝GoExtensionPack後,F1並選擇"Go:ShowDocumentation")。

如何使用 Golang 的錯誤包裝器? 如何使用 Golang 的錯誤包裝器? Jun 03, 2024 pm 04:08 PM

在Golang中,錯誤包裝器允許你在原始錯誤上追加上下文訊息,從而創建新錯誤。這可用於統一不同程式庫或元件拋出的錯誤類型,簡化偵錯和錯誤處理。步驟如下:使用errors.Wrap函數將原有錯誤包裝成新錯誤。新錯誤包含原始錯誤的上下文資訊。使用fmt.Printf輸出包裝後的錯誤,提供更多上下文和可操作性。在處理不同類型的錯誤時,使用errors.Wrap函數統一錯誤類型。

Go 並發函數的單元測試指南 Go 並發函數的單元測試指南 May 03, 2024 am 10:54 AM

對並發函數進行單元測試至關重要,因為這有助於確保其在並發環境中的正確行為。測試並發函數時必須考慮互斥、同步和隔離等基本原理。可以透過模擬、測試競爭條件和驗證結果等方法對並發函數進行單元測試。

See all articles