Heim > System-Tutorial > LINUX > Hauptteil

Eingehende Analyse der Verwendung von Kotlin-Funktionen und funktionaler Programmierprinzipien

WBOY
Freigeben: 2023-12-29 14:27:19
nach vorne
1334 Leute haben es durchsucht
Einführung Dieser Artikel stellt hauptsächlich die Verwendung von Kotlin-Funktionen und einige meiner Kenntnisse der funktionalen Programmierung vor. Und ich werde einige Vergleiche mit Python und C++ anstellen.

Seit Googles Vater Kotlin als seinen Patensohn bekannt gegeben hat, erfreut sich Kotlin in großen Gemeinden großer Beliebtheit.
Wenn Sie nichts über die Kotlin-Syntax wissen, wird empfohlen, vor dem Lesen dieses Artikels die offizielle Dokumentation oder die chinesische Website (https://www.kotlincn.net/docs/reference/) zu lesen, um ein tieferes Verständnis zu erhalten.

Hier ist die Definition von funktionaler Programmierung aus Wikipedia:

Funktionale Programmierung (englisch: Functional Programming), auch als funktionale Programmierung bekannt, ist ein Programmierparadigma, das Computeroperationen als mathematische Funktionsberechnungen behandelt und die Verwendung von Programmzuständen und flüchtigen Objekten vermeidet. Die wichtigste Grundlage funktionaler Programmiersprachen ist die Lambda-Kalküle. Und die Funktion der Lambda-Rechnung kann Funktionen als Eingabe (Argumente) und Ausgabe (ausgehender Wert) akzeptieren.

Das Folgende ist die Definition von Funktionen höherer Ordnung:

In der Mathematik und Informatik ist eine Funktion höherer Ordnung eine Funktion, die mindestens eine der folgenden Bedingungen erfüllt: eine oder mehrere Funktionen als Eingabe akzeptiert und eine Funktion ausgibt

Es ist nicht schwer zu schließen, dass die wichtigste Grundlage der funktionalen Programmierung Funktionen höherer Ordnung sind. Das heißt, die Unterstützungsfunktion kann Funktionen als Eingaben (Argumente) und Ausgaben (ausgehende Werte) akzeptieren.

Als erstklassiger Bürger in Kotlin können Funktionen wie andere Objekte als Eingabe und Ausgabe von Funktionen verwendet werden. Dies ist der Punkt, den Java-Programmierer beim Wechsel zu Kotlin als die größte Änderung empfinden und am schwersten zu verstehen. Wenn Sie bereits Python oder C++11 gelernt haben, ist dies möglicherweise einfacher für Sie. Aus diesem Grund werden in diesem Artikel hauptsächlich Kotlin-Funktionen und funktionale Programmierung vorgestellt.

Kotlin-Funktionen

Das Folgende ist die allgemeine Funktionsdefinition in Kotlin. Der Unterschied zu Java besteht darin, dass die Funktionsparameter an letzter Stelle stehen und der Rückgabewerttyp an letzter Stelle steht. Über das Gleichheitszeichen lässt sich der Funktionskörper der Funktionsdefinition zuordnen, auch hier ist die Gleichheit von Funktionen und Variablen erkennbar.

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
Nach dem Login kopieren

Darüber hinaus unterstützt Kotlin auch Funktionsstandardparameter, erweiterte Funktionen und Infix-Ausdrücke. Hier ist ein einfaches Beispiel:

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
}
Nach dem Login kopieren

Funktionen, die Standardparameter unterstützen, können die Funktionsüberlastung reduzieren.

Es gibt keine Methode, um festzustellen, ob es sich um einen Buchstaben im String-Objekt handelt. In Java definieren wir normalerweise einige Utils-Methoden, während wir in Kotlin Erweiterungsfunktionen der Klasse definieren können.
Das zweite Beispiel besteht darin, eine Erweiterungsfunktion für die Int-Klasse zu definieren. Die Erweiterungsfunktion wird als Infix-Ausdruck ausgedrückt, wodurch Entwickler das Recht erhalten, ähnliche Schlüsselwörter zu definieren.

Zum Beispiel können wir ein Kartenobjekt wie folgt erstellen:

val kv = mapOf("a" to 1, "b" to 2)
Nach dem Login kopieren

Hier ist ein Infix-Ausdruck, der wie folgt definiert ist:

public infix fun<A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
Nach dem Login kopieren

Pair ist ein in Map gespeichertes Objekt, daher können Sie es auch so erstellen

val kv = mapOf(Pair("a", 1), Pair("b", 2))
Nach dem Login kopieren

Wenn wir in Python möchten, dass eine Funktion mehrere Werte zurückgibt, können wir mit Kotlin auch ähnliche Funktionen basierend auf dem Destrukturierungsprinzip erreichen:

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)
}
Nach dem Login kopieren

Bitte lesen Sie in der offiziellen Dokumentation nach, wie benutzerdefinierte Objekte die Destrukturierung unterstützen, damit sie wie folgt durchlaufen werden kann:

for ((k, v) in map) {
    print("$k -> $v, ")
}
Nach dem Login kopieren
Funktionen höherer Ordnung und Lambda-Ausdrücke

„Lambda-Ausdruck“ (Lambda-Ausdruck) ist eine anonyme Funktion, die auf der Lambda-Abstraktion (Lambda-Abstraktion) basiert ein Funktionsname. Lambda-Ausdrücke können Abschlüsse darstellen (beachten Sie, dass sie sich vom traditionellen mathematischen Sinn unterscheiden).

Lambda-Ausdrücke in Python:

add = lambda x, y:x+y
Nach dem Login kopieren

lambda in C++:

[](int x, int y) -> int{ return x + y; }
Nach dem Login kopieren

Lambda in Kotlin:

var add = {x: Int, y: Int -> x + y}
Nach dem Login kopieren

Kotlin ist als stark typisierte Sprache relativ einfach.

Wir können einen Lambda-Ausdruck wie diesen verwenden:

fun main(args: Array) {
val sumLambda = {a: Int, b: Int -> a + b}
sumLambda(1, 2)
}
Nach dem Login kopieren

Es kann mit () wie eine Funktion aufgerufen werden. In Kotlin können Operatoren überladen werden. Der ()-Operator entspricht der überladenen Funktion invoke() der Klasse.

Sie können auch eine Variable wie diese definieren:

val numFun: (a: Int, b: Int) -> Int
Nach dem Login kopieren

Es handelt sich nicht um eine gewöhnliche Variable, sie muss auf eine Funktion verweisen und die Funktionssignatur muss konsistent sein:

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
}
Nach dem Login kopieren

Sie können sehen, dass diese Variable einem Lambda-Ausdruck, einer anderen Lambda-Ausdrucksvariablen oder einer gewöhnlichen Funktion entsprechen kann, Sie müssen jedoch (::) vor dem Funktionsnamen hinzufügen, um die Funktionsreferenz zu erhalten.

Dies ähnelt dem Funktionszeiger in C++. In Python können Sie jedoch den Funktionsnamen direkt als Funktionsreferenz verwenden. Das Folgende ist ein Beispiel für einen C++-Funktionszeiger

#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;
}
Nach dem Login kopieren

Zurück in Kotlin können wir auch eine Funktion an eine andere Funktion übergeben, wie zum Beispiel:

//函数参数
fun  doMap(list: List, function: (it: T) -> Any) {
    for (item in list) {
        function(item)
    }
}
Nach dem Login kopieren
Der erste Parameter ist eine Liste und der zweite Parameter ist eine Funktion. Der Zweck besteht darin, die zweite Funktion einmal für jedes Element in der Liste auszuführen. Anwendung:

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
}
Nach dem Login kopieren
Der zweite Parameter wird direkt in einen Lambda-Ausdruck übergeben. Natürlich kann auch eine Funktionsreferenz übergeben werden:

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
}
Nach dem Login kopieren
Der Effekt ist der gleiche wie beim obigen Code.

Ein ähnlicher Effekt kann mit Funktionszeigern in C++ erzielt werden:

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);
	}
}
Nach dem Login kopieren

Zurück zu Kotlin: Wenn die Funktion als Eingabeparameter die letzte in der Parameterliste ist, können Sie dies auch tun und direkt in die geschweiften Klammern schreiben:

fun main(args: Array) {
    log { sum(1,2) }
}

fun  log(function: () -> T) {
    val result = function()
    println("result -> $result")
}
Nach dem Login kopieren
Ist es nicht ein bisschen wie die Art und Weise, wie Gradle-Konfigurationsdateien geschrieben werden, sodass Kotlin problemlos domänenspezifische Sprachen (DSL) schreiben kann

?

Darüber hinaus unterstützt Kotlin auch lokale Funktionen und Funktionen als Rückgabewerte, siehe folgenden Code:

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
}
Nach dem Login kopieren

在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
}
Nach dem Login kopieren

将一个函数引用作为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()
}
Nach dem Login kopieren

上面的代码只是做演示,并无实际意义。具体语法请查看官方文档。

我相信Kotlin作为一种强类型的现代化语言可以在保证稳定性的同时极大地提高开发者的开发效率。

Das obige ist der detaillierte Inhalt vonEingehende Analyse der Verwendung von Kotlin-Funktionen und funktionaler Programmierprinzipien. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:linuxprobe.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage