Training - Kotlin
Publié le 12 May 2022
Mindmap
Bild:../../diagram/training_kotlin.png[training_kotlin]
Funktionale Programmierung
Die Übungen werden aus dem Buch entnommen:
Funktionale Programmierung in Kotlin anhand von Tutorials
Geschrieben von Massimo Carli
Repository: https://github.com/kodecocodes/fpk-materials
Syntax
FirstProgramTest
notions: Bildschirmanzeige, Funktion
FirstProgramTest:https://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/programming/FirstProgramTest.kt[Quelle]+
ConcatFunctionTest
Konzepte: Speicher, Variable, Wert, Objekt, Funktionserweiterung
ExampleUnitTest: Quelle+
BirthdayMessageTestOutput
Begriffe: Mengen, Schleifen
Einführung in Kotlin
BirthdayMessageTestOutput:https://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/programming/BirthdayMessageTestOutput.kt[Quelle]
Kotlin-Kurs
Funktionelle Grundlagen
deklarative X imperativer Ansatz
package functional
import kotlin.test.Test
import kotlin.test.assertEquals
class DeclarativeTests {
val input = listOf(
"123", "abc", "1ds", "987", "abdf", "1d3", "de1", "88", "101"
)
fun imperativeSum(list: List<String>): Int {
var sum = 0
for (item in list) {
try {
sum += item.toInt()
} catch (_: NumberFormatException) {
}
}
return sum
}
@Test
fun `test imperative approach`() {
imperativeSum(input).run {
println("Sum $this")
assertEquals(1299, this)
}
}
fun isValidNumber(s: String) = try {
s.toInt()
true
} catch (_: NumberFormatException) {
false
}
fun declarativeSum(list: List<String>) = list
.filter(::isValidNumber)
.map(String::toInt)
.sum()
@Test
fun `test declarative approach`() {
assertEquals(1299, declarativeSum(input).apply {
println("Sum $this")
})
}
}
Übung 1.1
Implementiere die Funktion sumInRange, die die Werte in
Eine List<String> in einem gegebenen Intervall. Die Signatur ist :
fun sumInRange(input: List<String>, range: IntRange): Int
@Test
fun `Exercise 1_1`() {
assertEquals(4, sumInRange(
listOf("1", "10", "a", "7", "ad2", "3"),
1..5
).apply { println("sumInRange 1..5: $this") }
)
}
Versuchen Sie es und überprüfen Sie Ihre Antwort mit demhttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/DeclarativeTests.kt[Lösung, windows="_blank].
Funktionen höherer Ordnung
package functional
import java.io.ByteArrayOutputStream
import java.io.PrintStream
import java.lang.System.*
import java.lang.Thread.sleep
import kotlin.math.sign
import kotlin.test.Test
import kotlin.test.assertEquals
class BasicsHOFTests {
val ONE_SECOND = 1000L
@Test
fun `high order function`() {
//capture de la sortie standard
val standardOut: PrintStream? = out
val outputStreamCaptor = ByteArrayOutputStream()
setOut(PrintStream(outputStreamCaptor))
3.times { println("Hello") }
assertEquals(
buildString {
repeat(3) { append("Hello\n") }
deleteAt(length - 1)
}, outputStreamCaptor
.toString()
.trim()
)
//libération de la sortie standard
setOut(standardOut)
}
fun Int.times1(fn: () -> Unit) {
for (i in 1..this) {
fn()
}
}
fun Int.times2(fn: () -> Unit) {
for (i in 1..this) fn()
}
fun Int.times3(fn: () -> Unit) =
(1..this).forEach { fn() }
fun Int.times4(fn: () -> Unit) =
repeat((1..this).count()) { fn() }
fun Int.times(fn: () -> Unit) =
(1..this).forEach { _ -> fn() }
}
Übung 1.2
Implementiere chrono, das eine Funktion vom Typ`() →`
Die Einheit wird als Eingabe übergeben und gibt die für die Ausführung benötigte Zeit zurück. Die Signatur lautet:
fun chrono(fn : () -> Unité) : Long
@Test
fun `Exercise 1_2`() {
val waitOneSec = { sleep(ONE_SECOND) }
chrono(waitOneSec).apply {
println("chrono: $this")
assertEquals(1, sign)
}
}
Versuchen Sie es und überprüfen Sie Ihre Antwort mit derhttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/BasicsHOFTests.kt[Lösung, windows="_blank].
Komposition
package functional
import kotlin.test.Test
import kotlin.test.assertEquals
fun double(x: Int): Int = 2 * x
fun square(x: Int): Int = x * x
fun squareAndDouble1(x: Int) = double(square(x))
infix fun <A, B, C> ((A) -> B).compose(g: (B) -> C)
: (A) -> C = { a -> g(this(a)) }
class CompositionTests {
@Test
fun composition_impure() {
assertEquals(200, double(square(10)))
assertEquals(200, squareAndDouble1(10))
}
@Test
fun composition_pure() {
val squareAndDouble = ::square compose ::double
assertEquals(200, squareAndDouble(10))
}
}
Reine Funktionen und Testbarkeit
package functional
import java.io.ByteArrayOutputStream
import java.io.PrintStream
import java.lang.System.out
import java.lang.System.setOut
import kotlin.test.Test
import kotlin.test.assertEquals
var count = 0
//impure car une variable global subit un effet de bord
fun impure(value: Int): Int {
count++
return value + count
}
//impure car utilisation de la sortie standard qui fait muter le system
fun addOneAndLog(x: Int): Int {
val result = x + 1
println("New Value is $result")
return result
}
//pure
fun addOne(x: Int) = (x + 1).run {
Pair(this, "New Value is $this")
}
class PureTests {
@Test
fun `impure fonction`() {
assertEquals(3, impure(2))
val standardOut = out
val outputStreamCaptor = ByteArrayOutputStream()
setOut(PrintStream(outputStreamCaptor))
addOneAndLog(3)
assertEquals(
"New Value is 4",
outputStreamCaptor
.toString()
.trim()
)
setOut(standardOut)
}
@Test
fun `pure fonction`() {
addOne(3).run {
assertEquals(4, first)
assertEquals("New Value is 4", second)
}
}
}
Ausnahmebehandlung
package functional
import org.junit.jupiter.api.assertThrows
import kotlin.Result.Companion.failure
import kotlin.Result.Companion.success
import kotlin.test.Test
import kotlin.test.assertEquals
//NumberFormatException est un effet de bord qui rend la fonction impure
fun strToInt(str: String) = str.toInt()
//pure
fun strToIntOrNull(str: String) = try {
str.toInt()
} catch (nfe: NumberFormatException) {
null
}
//pure avec gestion de l'exception plus élégante
fun strToIntResult(str: String): Result<Int> =
try {
success(str.toInt())
} catch (nfe: NumberFormatException) {
failure(nfe)
}
class ExceptionHandlingTests {
@Test
fun impure() {
assertThrows<NumberFormatException> { strToInt("foo") }
assertEquals(1, strToInt("1"))
}
@Test
fun pure() {
assertEquals(null, strToIntOrNull("foo"))
assertEquals(1, strToIntOrNull("1"))
}
@Test
fun `pure avec result`() {
assertEquals(1, strToIntResult("1").getOrNull())
assertEquals(
"For input string: \"foo\"",
strToIntResult("foo")
.exceptionOrNull()
?.message
)
}
}
Schlüsselpunkte
-
Während die objektorientierte Programmierung bedeutet, mit Objekten zu programmieren,
Funktionale Programmierung bedeutet, mit Funktionen zu programmieren. Du zerlegst ein Problem in mehrere Teilprobleme, die du mit die Funktionen.
-
Funktionen höherer Ordnung akzeptieren andere Funktionen als Eingabe oder geben andere
funktionieren wie Rückgabewerte. Die Kategorientheorie ist die Theorie der Komposition, und Sie verwenden sie, um zu verstehen Wie Sie Ihre Funktionen in einem Arbeitsprogramm komponieren. Der Ausgabewert einer reinen Funktion hängt ausschließlich von ihren Eingabeparametern ab, und sie hat keine Nebenwirkungen.
-
Ein Nebeneffekt ist etwas, was eine Funktion an die Außenwelt ausführt. Dies
Es kann ein Journal in der Standardausgabe oder die Änderung des Werts einer globalen Variablen sein. Funktionale Programmierung funktioniert für reine Funktionen, aber sie stellt auch die Werkzeuge zum Umwandeln von unreinen Funktionen in reine Funktionen. Sie können eine unreine Funktion rein machen, indem Sie die Effekte verschieben, um sie Teil des Rückgabewerts
-
Funktionale Programmierung ist eine Frage der Komposition.
Die Fehlerbehandlung ist ein typischer Fall von Nebenwirkungen, und Kotlin gibt dir die Werkzeuge. um sie funktional zu verwalten.
Java8 vertiefen: Lambda-Ausdrücke und funktionale Schnittstellen
Kategorientheorie
Die mathematische Kategorientheorie:
Grundlagen der Funktionen
Übung 2.1
Können Sie ein Beispiel für eine Funktion schreiben, die verschiedene Werte abbildet
dessen Definitionsbereich nicht verschiedene Werte im Wertebereich annimmt, wie f(b) und f(c) in der untenstehenden Abbildung?
Probier es aus, dann schau dir das Challenge-Projekt nach einer Lösung an, um zu sehen, wie du es gemacht hast.
Sie werden Ratschläge und eine Erklärung finden, indem Sie dem Link zur Lösung.
Übung 2.2
Können Sie die Umkehrfunktion von zwei Mal schreiben?
Was sind Definitionsbereich und Wertebereich der inversen Funktion?
Schauen Sie sich das Challenge-Projekt und Anhang B für die Lösung an.
fun chrono(fn : () -> Unité) : Long
@Test
fun `Exercise 1_2`() {
val waitOneSec = { sleep(ONE_SECOND) }
chrono(waitOneSec).apply {
println("chrono: $this")
assertEquals(1, sign)
}
}
Probiere es aus und überprüfe deine Antwort mit derhttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/BasicsHOFTests.kt[Lösung, windows="_blank].
