Halo semuanya, kami mengingatkan Anda bahwa bulan ini di OTUS set baru akan dimulai pada kursus Pengembang Golang . Terlepas dari beberapa kebencian dari artikel sebelumnya tentang Golang, penulis lepas kami memutuskan untuk mengambil risiko melanjutkan serangkaian artikel yang ditujukan untuk bahasa ini. Kami akan mencoba untuk pergi melalui es tipis ini sekali lagi, mengandalkan apa yang tampaknya mengandalkan Golang - paradigma fungsional.
Kami mengingatkan Anda bahwa artikel ini adalah semacam bahan untuk "membaca ekstrakurikuler" dan tidak terkait dengan program kursus, yang dapat ditemukan di sini .Jelas bahwa pemrogram profesional dalam bahasa lain panggilan Golang
iritasi seperti bahasa yang dikompilasi orang dewasa, tetapi konsep kelas dan pewarisan pada prinsipnya tidak ada (meskipun OOP diimplementasikan dalam bahasa, meskipun dengan cara yang agak tidak biasa, melalui sistem struktur dan antarmuka). Namun, hari ini kita melihat implementasi utama dari konstruksi yang dikenal dalam paradigma fungsional dan mencoba menjelaskan keduanya dan sintaksis bahasa itu sendiri.

Sekarang ada banyak hype di sekitar paradigma fungsional (FP). Namun, itu juga bukan obat mujarab untuk semua masalah, dan juga memiliki pro dan kontra.
Secara singkat tentang apa itu paradigma fungsional
Paradigma fungsional datang ke pemrograman dari matematika. Ini membentuk persyaratan berikut untuk program:
- Tidak ada perubahan pada data yang ada.
- Tidak ada kondisi tersembunyi.
Apa yang ini berikan pada kita?Fungsi kami berfungsi tanpa efek pihak ketiga. Dengan kata lain, fungsi seharusnya hanya mengembalikan nilai dan seharusnya tidak mempengaruhi data eksternal.
Menggunakan fitur murni. Mereka meningkatkan keandalan pengujian ulang fungsi terlepas dari data yang masuk - dengan kata lain, program menjadi lebih dapat diandalkan untuk pengujian dan hasilnya menjadi lebih dapat diprediksi.
Jadi, apa saja kemungkinan yang dimiliki Golang untuk menerapkan paradigma fungsional:
Fungsi kelas satu
Fungsi kelas satu tersedia dalam banyak bahasa pemrograman. Pembaca artikel ini kemungkinan besar sudah tahu konsep mereka dari JavaScript yang begitu luas, tetapi saya akan mengulanginya lagi. Fungsi-fungsi kelas pertama (fungsi urutan tinggi) adalah fungsi yang dapat mengembalikan fungsi lain sebagai pengetahuan, mengambil fungsi sebagai argumen, dan meneruskan nilai fungsi ke variabel lain.
Mari kita sepakati sejak awal : untuk menghemat tempat, saya membuang dua baris pertama dari kode yang disajikan di sini: 'paket utama' dan impor 'impor "fmt"'. Tetapi untuk menjalankan kode pada mesin Anda, ingatlah untuk menambahkannya).
func main() { var list = []int{15, 16, 45, 34}
Faktanya, sama sekali tidak perlu untuk menciptakan
map
Anda sendiri atau
foreach
dari awal. Ada banyak perpustakaan yang menerapkan ini, tetap hanya untuk menghubungkannya. Misalnya yang
ini .
Fungsi penutup dan kari
Ada hubungan pendek dalam banyak bahasa pemrograman modern. Penutupan adalah fungsi yang merujuk ke variabel lingkup bebas dari fungsi induknya. Currying fungsi adalah perubahan fungsi dari bentuk
func(a,b,c)
ke bentuk
func(a)(b)(c)
.
Berikut adalah contoh penutupan dan kari di Go:
Fungsi murni
Seperti yang kami katakan sebelumnya, fungsi murni adalah yang mengembalikan nilai yang hanya dikaitkan dengan argumen yang masuk dan tidak mempengaruhi keadaan global.
Ini adalah contoh dari kegagalan, fungsi kotor:
var arrToSave = map[string]int{}
Di sini, fungsi kami harus menerima untuk bekerja semampu mungkin:
func simpleSum(x, y int) int { return x + y } func main() { fmt.Printf("%v", dirtySum(13, 12))
"Entah bagaimana rekursi memasuki bar, dan tidak ada orang lain yang masuk bar"
Dari koleksi lelucon yang tidak lucu.Rekursi
Dalam paradigma fungsional, sudah lazim untuk memberikan preferensi pada rekursi - untuk kemurnian dan transparansi, alih-alih menggunakan iterasi sederhana hingga.
Berikut adalah contoh penghitungan faktorial menggunakan paradigma imperatif dan deklaratif:
func funcFactorial(num int) int { if num == 0 { return 1 } return num * funcFactorial(num-1) } func imperativeFactorial(num int) int { var result int = 1 for ; num > 0; num-- {
Sekarang fungsi rekursi bekerja sangat tidak efisien. Mari kita coba menulis ulang sedikit untuk mengoptimalkan kecepatan perhitungannya:
func factTailRec(num int) int { return factorial(1, num)
Kecepatan komputasi faktorial kami sedikit meningkat. Saya tidak akan memberikan tolok ukur).
Sayangnya, Go tidak menerapkan optimasi rekursi di luar kotak, jadi Anda harus mengoptimalkan sendiri rekursi tersebut. Meskipun, tidak diragukan lagi, perpustakaan yang bermanfaat tentang topik ini tentu saja dapat ditemukan. Misalnya, ada "Loadash for Golang" yang keren tentang
topik ini.
Komputasi malas
Dalam teori pemrograman, komputasi malas (juga dikenal sebagai "komputasi ditangguhkan") adalah proses menunda komputasi sampai diperlukan. Golang tidak memiliki dukungan untuk komputasi malas langsung sehingga kami hanya dapat mensimulasikan ini:
func mult(x, y int) int { fmt.Println(" ") return x * x. } func divide(x, y int) int { fmt.Println(" ") return x / y
Paling sering, "emulasi" ekspresi malas tidak sepadan karena terlalu menyulitkan kode, tetapi jika fungsi Anda cukup sulit untuk dikelola, maka Anda harus menggunakan metode ini. Tetapi Anda dapat beralih ke solusi lain, misalnya, untuk
ini .

Itu saja. Kami hanya mendapatkan pengantar paradigma fungsional tentang Golang. Sayangnya, sebagian dari kemungkinan harus disimulasikan. Sebagian, teknik fungsional yang dikembangkan sepenuhnya, seperti monad, tidak dimasukkan di sini, karena ada
banyak artikel tentang mereka di Go on the hub Banyak yang masih dapat ditingkatkan dalam bahasa itu sendiri, misalnya dengan versi besar berikutnya (GO 2) generik diharapkan dalam bahasa tersebut. Baiklah, kita akan menunggu dan berharap).