Pelatihan - Kotlin
Diterbitkan 12 May 2022
Peta pikir

Pemrograman fungsional
Latihan diambil dari buku:
Pemrograman fungsional dalam Kotlin oleh tutorial
Ditulis oleh Massimo Carli
repo: https://github.com/kodecocodes/fpk-materials
Sintaksis
FirstProgramTest
konsep: tampilan layar, fungsi
FirstProgramTest:https://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/programming/FirstProgramTest.kt[sumber]+
ConcatFunctionTest
konsep: memori, variabel, nilai, objek, ekstensi fungsi
ExampleUnitTest: sumber+
BirthdayMessageTestOutput
konsep: himpunan, loop
Pengantar kotlin
BirthdayMessageTestOutput:https://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/programming/BirthdayMessageTestOutput.kt[sumber]+
Kursus kotlin
dasar fungsional
pendekatan deklaratif X imperatif
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")
})
}
}
Latihan 1.1
Implementasikan fungsi sumInRange, yang menjumlahkan nilai-nilai di dalam
sebuah List<String> dalam rentang yang diberikan. tanda tangan adalah :
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") }
)
}
Cobalah dan periksa jawaban Anda denganhttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/DeclarativeTests.kt[solusi, windows="_blank].
fungsi orde tinggi
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() }
}
Latihan 1.2
Menerapkan chrono, yang menerima fungsi dengan tipe`() →`
Unit pada masukan dan mengembalikan waktu yang dihabiskan untuk mengeksekusinya. Tanda tandanya:
fun chrono(fn : () -> Unité) : Long
@Test
fun `Exercise 1_2`() {
val waitOneSec = { sleep(ONE_SECOND) }
chrono(waitOneSec).apply {
println("chrono: $this")
assertEquals(1, sign)
}
}
Coba itu dan periksa jawaban Anda denganhttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/BasicsHOFTests.kt[solusi, windows="_blank].
komposisi
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))
}
}
Fungsi murni dan kemampuan diuji
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)
}
}
}
Penanganan pengecualian
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
)
}
}
poin-poin kunci
-
Sementara pemrograman berorientasi objek berarti memprogram dengan objek,
pemrograman fungsional berarti memprogram dengan fungsi. Anda memecah masalah menjadi beberapa sub-masalah, yang Anda modelkan dengan fungsi-fungsi.
-
Fungsi orde tinggi menerima fungsi lain sebagai input atau mengembalikan fungsi lain
berfungsi sebagai nilai pengembalian. Teori kategori adalah teori komposisi, dan Anda menggunakannya untuk memahami bagaimana menyusun fungsi-fungsimu dalam sebuah program kerja Nilai output dari fungsi murni hanya tergantung pada parameter inputnya, dan ia tidak memiliki efek samping
-
Sebuah efek samping adalah sesuatu yang dilakukan oleh sebuah fungsi ke dunia luar. Ini
mungkin menjadi log di output standar atau modifikasi nilai variabel global Pemrograman fungsional berfungsi untuk fungsi murni, tetapi juga menyediakan alat untuk mengubah fungsi tidak murni menjadi fungsi murni. Anda dapat membuat fungsi tidak murni menjadi murni dengan memindahkan efek untuk membuatnya bagian dari nilai pengembalian
-
Pemrograman fungsional adalah tentang komposisi.
Penanganan kesalahan adalah contoh khas efek samping, dan Kotlin memberi Anda alat. untuk mengelola mereka secara fungsional.
Mendalam java8: ekspresi lambda dan antarmuka fungsional
Teori Kategori
Teori matematika kategori:
Dasar-dasar fungsi
Latihan 2.1
Bisakah Anda menulis contoh fungsi yang memetakan nilai yang berbeda
yang memiliki domain dengan nilai-nilai yang tidak berbeda dalam rentang, seperti f(b) dan f(c) dalam gambar di bawah ini?
Cobalah, lalu periksa proyek tantangan untuk solusi yang menunjukkan bagaimana kamu melakukannya.
Anda akan menemukan saran dan penjelasan dengan mengikuti tautan ke solusi.
Latihan 2.2
Bisakah kamu menulis fungsi invers dari dua kali ?
Apa domain dan jangkauan untuk fungsi invers?
Lihat proyek tantangan dan Lampiran B untuk solusi.
fun chrono(fn : () -> Unité) : Long
@Test
fun `Exercise 1_2`() {
val waitOneSec = { sleep(ONE_SECOND) }
chrono(waitOneSec).apply {
println("chrono: $this")
assertEquals(1, sign)
}
}
Coba dan periksa jawaban Anda denganhttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/BasicsHOFTests.kt[solution, windows="_blank].
