Rumah > Artikel > Tutorial sistem > Analisis mendalam tentang penggunaan fungsi Kotlin dan prinsip pengaturcaraan berfungsi
Pengenalan | Artikel ini terutamanya memperkenalkan penggunaan fungsi Kotlin dan beberapa pemahaman saya tentang pengaturcaraan berfungsi. Dan akan membuat beberapa perbandingan dengan Python dan C++. |
Sejak bapa Google mengumumkan Kotlin sebagai anak baptisnya, Kotlin telah menjadi sangat popular di komuniti utama.
Jika anda tidak tahu apa-apa tentang sintaks Kotlin, anda disyorkan untuk membaca dokumentasi rasmi atau tapak web Cina (https://www.kotlincn.net/docs/reference/) sebelum membaca artikel ini untuk pemahaman yang lebih mendalam.
Berikut ialah definisi pengaturcaraan berfungsi daripada Wikipedia:
Pengaturcaraan fungsian (Bahasa Inggeris: pengaturcaraan berfungsi), juga dikenali sebagai pengaturcaraan fungsian, ialah paradigma pengaturcaraan yang menganggap operasi komputer sebagai pengiraan fungsi matematik dan mengelakkan penggunaan keadaan atur cara dan objek yang tidak menentu . Asas terpenting bahasa pengaturcaraan berfungsi ialah kalkulus lambda. Dan fungsi kalkulus lambda boleh menerima fungsi sebagai input (argumen) dan output (nilai keluar).
Berikut ialah takrifan fungsi tertib tinggi:
Dalam matematik dan sains komputer, fungsi tertib tinggi ialah fungsi yang memenuhi sekurang-kurangnya satu daripada syarat berikut: menerima satu atau lebih fungsi sebagai input dan mengeluarkan fungsi
Tidak sukar untuk membuat kesimpulan bahawa asas pengaturcaraan berfungsi yang paling penting ialah fungsi peringkat tinggi. Iaitu, fungsi sokongan boleh menerima fungsi sebagai input (argumen) dan output (nilai keluar).
Sebagai warga kelas pertama di Kotlin, fungsi boleh digunakan sebagai input dan output fungsi seperti objek lain. Inilah titik yang pengaturcara Java mendapati perubahan terbesar dan paling sukar difahami apabila mereka beralih kepada Kotlin. Jika anda pernah mempelajari Python atau C++11 sebelum ini, ini mungkin lebih mudah untuk anda. Inilah sebabnya mengapa artikel ini terutamanya memperkenalkan fungsi Kotlin dan pengaturcaraan berfungsi.
Fungsi KotlinBerikut ialah definisi fungsi umum dalam Kotlin Perbezaan dari Java ialah parameter fungsi diletakkan terakhir, dan jenis nilai pulangan diletakkan terakhir. Badan fungsi boleh diberikan kepada definisi fungsi menggunakan tanda sama, dan kesamaan fungsi dan pembolehubah juga boleh dilihat di sini.
fun main(args: Array) { var s = sum(1,2) var m = multi(2,3) var x = maxOf(3,4) } fun sum(a: Int, b: Int): Int { return a + b } fun multi(a: Int, b: Int): Int = a * b fun maxOf(a: Int, b: Int): Int = if (a > b) a else b
Selain itu, Kotlin juga menyokong parameter lalai fungsi, fungsi lanjutan dan ungkapan infix Berikut ialah contoh mudah:
fun main(args: Array) { isBiggerThan(2) isBiggerThan(2, 5) var s = "a".isLetter() var a = 1 add 2 } fun isBiggerThan(a: Int, b: Int = 0) { return a > b } //拓展函数 fun String.isLetter(): Boolean { return matches(Regex("^[a-z|A-Z]$")) } //拓展函数,中缀表达式 infix fun Int.add(x: Int): Int { return this + x }
Fungsi yang menyokong parameter lalai boleh mengurangkan lebihan beban fungsi.
Tiada kaedah dalam objek String untuk menentukan sama ada ia adalah huruf Dalam Java, kami biasanya mentakrifkan beberapa kaedah Utils, manakala dalam Kotlin, kami boleh menentukan fungsi sambungan kelas.
Contoh kedua ialah untuk mentakrifkan fungsi sambungan untuk kelas Int, dan fungsi sambungan dinyatakan sebagai ungkapan infix, memberikan hak kepada pembangun untuk menentukan kata kunci yang serupa.
Sebagai contoh, kita boleh mencipta objek peta seperti ini:
val kv = mapOf("a" to 1, "b" to 2)
Di sini adalah ungkapan infiks, ditakrifkan seperti berikut:
public infix fun<A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
Pair ialah objek yang disimpan dalam Peta, jadi anda juga boleh menciptanya seperti ini
val kv = mapOf(Pair("a", 1), Pair("b", 2))
Dalam Python, jika kita mahu fungsi itu mengembalikan berbilang nilai, kita boleh mengembalikan tuple Kotlin juga boleh mencapai fungsi yang serupa berdasarkan prinsip pemusnahan:
fun main(args: Array) { val (index, count) = findWhere("abcabcabcabc", 'c') } fun findWhere(str: String, findChar: Char): Pair<Int, Int> { var index = -1 var count = 0 for ((i, v) in str.withIndex()) { if (v == findChar) { if (index == -1) { index = i } ++count } } return Pair(index, count) }
Sila semak dokumentasi rasmi untuk mengetahui cara objek tersuai menyokong pemusnahan, supaya ia boleh dilalui seperti berikut:
for ((k, v) in map) { print("$k -> $v, ") }Fungsi tertib lebih tinggi dan ekspresi Lambda
"Ekspresi lambda" (ungkapan lambda) ialah fungsi tanpa nama yang dinamakan berdasarkan kalkulus lambda dalam matematik Ia sepadan secara langsung dengan abstraksi lambda (abstraksi lambda, iaitu fungsi tanpa nama). nama fungsi. Ungkapan Lambda boleh mewakili penutupan (perhatikan bahawa ia berbeza daripada pengertian matematik tradisional).
Ekspresi Lambda dalam Python:
add = lambda x, y:x+y
lambda dalam C++:
[](int x, int y) -> int{ return x + y; }
lambda dalam Kotlin:
var add = {x: Int, y: Int -> x + y}
Kotlin agak mudah sebagai bahasa yang ditaip dengan kuat.
Kita boleh menggunakan ungkapan lambda seperti ini:
fun main(args: Array) { val sumLambda = {a: Int, b: Int -> a + b} sumLambda(1, 2) }
Ia boleh dipanggil menggunakan () seperti fungsi Dalam kotlin, operator boleh terlebih beban Operator () sepadan dengan invoke() fungsi yang terlebih beban.
Anda juga boleh mentakrifkan pembolehubah seperti ini:
val numFun: (a: Int, b: Int) -> Int
Ia bukan pembolehubah biasa, ia mesti menunjuk kepada fungsi, dan tandatangan fungsi mestilah konsisten:
fun main(args: Array) { val sumLambda = {a: Int, b: Int -> a + b} var numFun: (a: Int, b: Int) -> Int numFun = {a: Int, b: Int -> a + b} numFun = sumLambda numFun = ::sum numFun(1,2) } fun sum(a: Int, b: Int): Int { return a + b }
Anda boleh melihat bahawa pembolehubah ini boleh sama dengan ungkapan lambda, pembolehubah ungkapan lambda lain atau fungsi biasa, tetapi anda perlu menambah (::) sebelum nama fungsi untuk mendapatkan rujukan fungsi.
Ini adalah serupa dengan penuding fungsi dalam C++ Namun, dalam Python anda boleh terus menggunakan nama fungsi sebagai rujukan fungsi Berikut ialah contoh penunjuk fungsi C++:
#include using namespace std; void swap(int &x, int &y); int main(int arg, char* args[]) { int x = 10; int y = 20; void (*methodPtr)(int &x, int &y);//声明一个函数指针 methodPtr = &swap; //函数指针赋值 methodPtr = swap;//取地址符可省略,效果和上面一致 methodPtr(x, y); //像给函数起了一个别名,可以直接使用()调用 cout << "x:" << x << " y:" << y << endl; //x:20 y:10 } void swap(int &x, int &y) { int tmp = x; x = y; y = tmp; }
Kembali ke Kotlin, kita juga boleh menghantar satu fungsi ke fungsi lain, seperti:
//函数参数 fun doMap(list: List, function: (it: T) -> Any) { for (item in list) { function(item) } }
Parameter pertama ialah Senarai, dan parameter kedua ialah fungsi Tujuannya adalah untuk melaksanakan fungsi kedua sekali untuk setiap elemen dalam Senarai. Cara penggunaan:
val strList = listOf("h" ,"e", "1", "a", "b", "2", " ", "", "c", "5", "7", "F") doMap(strList, {item ->print("item: ${upperLetter(item)}, ") }) fun upperLetter(item: String): String { if (item.isLetter()) { return item.toUpperCase() } return item }
Parameter kedua dihantar terus ke dalam ungkapan lambda Sudah tentu, rujukan fungsi juga boleh dihantar dalam:
val strList = listOf("h" ,"e", "1", "a", "b", "2", " ", "", "c", "5", "7", "F") doMap(strList, ::printUpperLetter) fun printUpperLetter(item: String) { print("item: ${upperLetter(item)}, ") } fun upperLetter(item: String): String { if (item.isLetter()) { return item.toUpperCase() } return item }
Kesannya sama seperti kod di atas.
Kesan yang serupa boleh dicapai menggunakan penunjuk fungsi dalam C++:
using namespace std; void mMap(vector list, void (*fun)(int item)); int main(int arg, char* args[]) { vector list = {2,3,4,3,2,1,2}; mMap(list, [](int item) -> void { cout << item << endl; }); } void mMap(vector list, void (*fun)(int item)) { for(int it : list) { fun(it); } }
Kembali ke Kotlin sekali lagi, jika fungsi tersebut adalah yang terakhir dalam senarai parameter sebagai parameter input, anda juga boleh melakukan ini dan menulisnya terus dalam kurungan kerinting:
fun main(args: Array) { log { sum(1,2) } } fun log(function: () -> T) { val result = function() println("result -> $result") }
Bukankah ini sedikit seperti cara fail konfigurasi gradle ditulis, jadi Kotlin boleh menulis bahasa khusus domain (DSL) dengan mudah
Selain itu, Kotlin juga menyokong fungsi dan fungsi setempat sebagai nilai pulangan, lihat kod berikut:
fun main(args: Array) { val addResult = lateAdd(2, 4) addResult() } //局部函数,函数引用 fun lateAdd(a: Int, b: Int): Function0 { fun add(): Int { return a + b } return ::add }
在lateAdd内部定义了一个局部函数,最后返回了该局部函数的引用,对结果使用()操作符拿到最终的结果,达到延迟计算的目的。
函数作为一级公民当然可以像普通对象一样放进map中,比如下面这样:
val funs = mapOf("sum" to ::sum) val mapFun = funs["sum"] if (mapFun != null) { val result = mapFun(1,2) println("sum result -> $result") } fun sum(a: Int, b: Int): Int { return a + b }
将一个函数引用作为value放进了map中,取出来之后使用()操作符调用,可以简化一些if,else的场景。
基于以上函数式编程的特性,Kotlin可以像RxJava一样很方便的进行相应式编程,比如:
fun printUpperLetter(list: List) { list .filter (fun(item):Boolean { return item.isNotEmpty() }) .filter { item -> item.isNotBlank()} .filter { item -> if (item.isNullOrEmpty()) { return@filter false } return@filter item.matches(Regex("^[a-z|A-Z]$")) } .filter { it.isLetter() } .map(String::toUpperCase) .sortedBy { it } .forEach { print("$it, ") } println() }
上面的代码只是做演示,并无实际意义。具体语法请查看官方文档。
我相信Kotlin作为一种强类型的现代化语言可以在保证稳定性的同时极大地提高开发者的开发效率。
Atas ialah kandungan terperinci Analisis mendalam tentang penggunaan fungsi Kotlin dan prinsip pengaturcaraan berfungsi. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!